mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-04-19 16:21:16 +00:00
Merge remote-tracking branch 'gzdoom/master' into master202008
This commit is contained in:
commit
6dc35238d3
261 changed files with 6301 additions and 3199 deletions
|
@ -1,3 +1,6 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
# Locate SDL2 library
|
||||
# This module defines
|
||||
# SDL2_LIBRARY, the name of the library to link against
|
||||
|
@ -57,19 +60,6 @@
|
|||
# was not created for redistribution, and exists temporarily pending official
|
||||
# SDL2 CMake modules.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
|
|
|
@ -96,6 +96,8 @@ function(target_architecture output_var)
|
|||
set(osx_arch_x86_64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
||||
set(osx_arch_ppc64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "arm64")
|
||||
set(osx_arch_arm64 TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
||||
endif()
|
||||
|
@ -117,6 +119,10 @@ function(target_architecture output_var)
|
|||
if(osx_arch_ppc64)
|
||||
list(APPEND ARCH ppc64)
|
||||
endif()
|
||||
|
||||
if(osx_arch_arm64)
|
||||
list(APPEND ARCH arm64)
|
||||
endif()
|
||||
else()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
|
||||
|
||||
|
|
106
fm_banks/GENMIDI-readme.txt
Normal file
106
fm_banks/GENMIDI-readme.txt
Normal file
|
@ -0,0 +1,106 @@
|
|||
DMXOPL3
|
||||
==================================================================
|
||||
https://github.com/sneakernets/DMXOPL
|
||||
==================================================================
|
||||
|
||||
New and improved DMX GENMIDI for Doom and sourceports, taking full advantage of
|
||||
the OPL3 waveforms. This takes things up a notch in terms of timbre.
|
||||
|
||||
# Summary
|
||||
This is a GENMIDI patch for DMX for OPL3 FM synthesis. This patch aims to remedy
|
||||
the "weak" default instruments to better match the Roland Sound Canvas, most
|
||||
notably the SC-55 and SC-88. Recommended minimum setup for no note-cuts is
|
||||
ZDoom 2.8.1 with DOSBOX OPL3 emulator core, with 6 chips emulated.
|
||||
|
||||
======FAQ======
|
||||
# Why OPL3 only?
|
||||
OPL3 has four additional waveforms - Alternating Sine, Camel Sine, Square, and
|
||||
Logarithmic Square (Sawtooth). The most interesting of these is the Square wave,
|
||||
for obvious reasons! This will benefit percussion instruments immensely.
|
||||
|
||||
# What did you use for this project?
|
||||
|
||||
Hex Editors, OPL3 Bank Editor, Fraggle's Python scripts, Adlib Tracker II,
|
||||
Edlib, ADLMidi. I also used the following keyboards and devices:
|
||||
|
||||
- Yamaha PSR-3 for basic voice ideas
|
||||
- Yamaha PSS-50 for layered voice ideas
|
||||
- Yamaha DX-7
|
||||
- Commodore 64 Music Module
|
||||
- VRC7 and related chips
|
||||
- Sound Blaster 16
|
||||
- Yamaha PCI cards
|
||||
- Sounds from various SEGA MegaDrive games
|
||||
|
||||
=======WOPL FAQ=======
|
||||
# What's the difference between the WOPL version and the DMX version?
|
||||
The main difference is with a few instruments that had to be tweaked to work
|
||||
with DMX. Most of these changes are negligible for General MIDI stuff. To hear
|
||||
what I intended DMXOPL to sound like in Doom, you'll have to wait for Eternity
|
||||
Engine's ADLMIDI support to be finalized.
|
||||
|
||||
# Any plans for GS/XG support?
|
||||
Yes. This will take considerable time, and voices will be added as I come across
|
||||
them in my MIDI files. You can check the progress on those through the XG and GS
|
||||
branches that I will make (or have already made). As I think the GM set is solid
|
||||
enough now, save for just a handful of instruments, I can start work on the
|
||||
other banks.
|
||||
|
||||
# Will the WOPL version be usable on any other FM chips?
|
||||
Depends on the chip, but more than likely the answer is no. YMF262 (and the OPL*
|
||||
family for that matter) operate differently than most of the other FM chips, and
|
||||
wouldn't likely transfer over to DX-7 or other instruments without considerable
|
||||
work, if they would work at all.
|
||||
|
||||
|
||||
# Is the best way to listen to this really through an emulator?
|
||||
Yes, unfortunately. Unless someone makes an FM chip that can handle 128+
|
||||
channels, this is likely never to change. If you're using this in your music
|
||||
projects and you still want to use the real thing, I recommend recording one
|
||||
track at a time and throwing the result in your favorite DAW - just be sure to
|
||||
put a highpass filter set to a really low value (I recommend 5 Hz) to get rid
|
||||
of the offset garbage, lest your mix splatter like crazy.
|
||||
|
||||
======Credits======
|
||||
* Wohlstand, for the OPL3BankEditor
|
||||
* Bisqwuit, for ADLMidi
|
||||
* Fraggle, for Chocolate Doom and GENMIDI research, as well as the Python scripts
|
||||
* SubZ3ro, for AdLib Tracker II
|
||||
* Esselfortium, for the encouragement and support
|
||||
* Jimmy, who will include this in the next Adventures of Square release
|
||||
* The Fat Man, who created the famous 2-op and 4-op patches everyone knows
|
||||
* Diode Milliampere, who made FM synth popular again
|
||||
* Patchouli, for keeping my spirits up
|
||||
* Graf Zahl, for continuing ZDoom as GZDoom
|
||||
* Randi, for implementing the OPL Emulation in ZDoom
|
||||
* Fisk, for miscellaneous feedback and MIDIs to test
|
||||
* Stewboy, for the Ancient Aliens MIDIs to test
|
||||
* Xaser, who said this patch passes the "Angry Scientist test"
|
||||
* Minigunner, just because
|
||||
* Altazimuth, who claims it'll be in Eternity someday (this is now true)
|
||||
* MTrop
|
||||
* Quasar, for Eternity Engine
|
||||
* Glaice, for patch advice
|
||||
* BlastFrog, for patch advice
|
||||
* Vogons Forums, for the OPL-3 Research and tools
|
||||
* AtariAge, for C64 Sound module preset banks
|
||||
* NintendoAge
|
||||
* John Chowning, the father of FM synthesis. I hope he can hear this someday.
|
||||
|
||||
## Extra Thanks to:
|
||||
* Doomworld Forums and the respective IRC/DISCORD channels
|
||||
* The 4th Modulator DISCORD channels
|
||||
* Giest118, who installed Doom again to listen to this
|
||||
* Nuke.YKT, for testing this in Raptor, and for the Nuked OPL core
|
||||
* kode54, who added this to Cog and FB2K, thank you!
|
||||
* Patch93, who contributed various patches
|
||||
* OlPainless, who contributed various patches
|
||||
* Papiezak, who contributed various of patches
|
||||
* Infurnus, for support
|
||||
* Leileilol, for support
|
||||
* MaliceX, for support
|
||||
* Kuschelmonster, for support
|
||||
* Anyone who makes music with this thing!
|
||||
|
||||
YMF262 forever.
|
||||
|
Binary file not shown.
7
fm_banks/fmmidi-readme.txt
Normal file
7
fm_banks/fmmidi-readme.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
A bank, created from hardcoded instruments, extracted from "fmmidi" project
|
||||
|
||||
http://unhaut.x10host.com/fmmidi/
|
||||
|
||||
It's license:
|
||||
This program is released under the "three clauses" BSD license
|
||||
|
BIN
fm_banks/fmmidi.wopn
Normal file
BIN
fm_banks/fmmidi.wopn
Normal file
Binary file not shown.
8
fm_banks/gems-fmlib-gmize-readme.txt
Normal file
8
fm_banks/gems-fmlib-gmize-readme.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
This bank was created by Wohlstand from imported instruments from the standard
|
||||
set of insruments pre-included with GEMS program which was a official Sega
|
||||
music creation system. Original set was not GM. Therefore, imported instruments
|
||||
are was organized to provide a proper GM set.
|
||||
|
||||
Some instruments was a bit modified, some melodic instruments and percussions
|
||||
are was taken from Wohlstand's xg.wopn bank.
|
||||
|
BIN
fm_banks/gems-fmlib-gmize.wopn
Normal file
BIN
fm_banks/gems-fmlib-gmize.wopn
Normal file
Binary file not shown.
25
fm_banks/gs-by-papiezak-and-sneakernets-readme.txt
Normal file
25
fm_banks/gs-by-papiezak-and-sneakernets-readme.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
=============
|
||||
https://github.com/sneakernets/DMXOPN2
|
||||
https://github.com/papiezak/DMXOPN2
|
||||
=============
|
||||
|
||||
== DMXOPN2 ==
|
||||
|
||||
No-nonsense patches for YM2612.
|
||||
|
||||
|
||||
== About ==
|
||||
|
||||
After much work on my DMXOPL project, I noticed that a lot of presets that
|
||||
I created were not compatible with the YM2612, which was the chip I started
|
||||
with, but quickly dropped. In response, I decided to rectify this by recreating
|
||||
the best patches from DMXOPL to OPN2 format. Don't expect miracles, as this is
|
||||
more of a learning experience so I can start working on expanding my FM synth
|
||||
knowledge.
|
||||
|
||||
I chose the name "DMX" not because it works with DMX, but that it will
|
||||
(hopefully) be of the same quality as the DMXOPL patch. Yeah, not very
|
||||
descriptive, but names aren't everything.
|
||||
|
||||
Watch this space.
|
||||
|
Binary file not shown.
|
@ -844,7 +844,6 @@ set (PCH_SOURCES
|
|||
gameconfigfile.cpp
|
||||
gitinfo.cpp
|
||||
hu_scores.cpp
|
||||
i_net.cpp
|
||||
m_cheat.cpp
|
||||
m_misc.cpp
|
||||
playsim/p_acs.cpp
|
||||
|
@ -1041,6 +1040,7 @@ set (PCH_SOURCES
|
|||
common/textures/skyboxtexture.cpp
|
||||
common/textures/animtexture.cpp
|
||||
common/textures/v_collection.cpp
|
||||
common/textures/animlib.cpp
|
||||
common/textures/formats/automaptexture.cpp
|
||||
common/textures/formats/brightmaptexture.cpp
|
||||
common/textures/formats/buildtexture.cpp
|
||||
|
@ -1059,6 +1059,7 @@ set (PCH_SOURCES
|
|||
common/textures/formats/shadertexture.cpp
|
||||
common/textures/formats/tgatexture.cpp
|
||||
common/textures/formats/stbtexture.cpp
|
||||
common/textures/formats/anmtexture.cpp
|
||||
common/textures/hires/hqresize.cpp
|
||||
common/models/models_md3.cpp
|
||||
common/models/models_md2.cpp
|
||||
|
@ -1091,6 +1092,7 @@ set (PCH_SOURCES
|
|||
common/utility/zstrformat.cpp
|
||||
common/utility/name.cpp
|
||||
common/utility/r_memory.cpp
|
||||
common/thirdparty/base64.cpp
|
||||
common/thirdparty/md5.cpp
|
||||
common/thirdparty/superfasthash.cpp
|
||||
common/filesystem/filesystem.cpp
|
||||
|
@ -1103,6 +1105,7 @@ set (PCH_SOURCES
|
|||
common/filesystem/file_zip.cpp
|
||||
common/filesystem/file_pak.cpp
|
||||
common/filesystem/file_whres.cpp
|
||||
common/filesystem/file_ssi.cpp
|
||||
common/filesystem/file_directory.cpp
|
||||
common/filesystem/resourcefile.cpp
|
||||
common/engine/cycler.cpp
|
||||
|
@ -1111,6 +1114,7 @@ set (PCH_SOURCES
|
|||
common/engine/sc_man.cpp
|
||||
common/engine/palettecontainer.cpp
|
||||
common/engine/stringtable.cpp
|
||||
common/engine/i_net.cpp
|
||||
common/engine/i_interface.cpp
|
||||
common/engine/renderstyle.cpp
|
||||
common/engine/v_colortables.cpp
|
||||
|
@ -1354,6 +1358,15 @@ add_custom_command(TARGET zdoom POST_BUILD
|
|||
${CMAKE_SOURCE_DIR}/fm_banks/gs-by-papiezak-and-sneakernets.wopn $<TARGET_FILE_DIR:zdoom>/fm_banks/gs-by-papiezak-and-sneakernets.wopn
|
||||
)
|
||||
|
||||
if( WIN32 )
|
||||
set( INSTALL_SOUNDFONT_PATH . CACHE STRING "Directory where soundfonts and WOPL/WOPN banks will be placed during install." )
|
||||
else()
|
||||
set( INSTALL_SOUNDFONT_PATH share/games/doom CACHE STRING "Directory where soundfonts and WOPL/WOPN banks will be placed during install." )
|
||||
endif()
|
||||
install(DIRECTORY "${PROJECT_BINARY_DIR}/soundfonts" "${PROJECT_BINARY_DIR}/fm_banks"
|
||||
DESTINATION ${INSTALL_SOUNDFONT_PATH}
|
||||
COMPONENT "Soundfont resources")
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
# GCC misoptimizes this file
|
||||
set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" )
|
||||
|
|
|
@ -401,10 +401,6 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
|
||||
double xscale = parms.destwidth / parms.texwidth;
|
||||
double yscale = parms.destheight / parms.texheight;
|
||||
double x = parms.x - parms.left * xscale;
|
||||
double y = parms.y - parms.top * yscale;
|
||||
double w = parms.destwidth;
|
||||
double h = parms.destheight;
|
||||
double u1, v1, u2, v2;
|
||||
PalEntry vertexcolor;
|
||||
|
||||
|
@ -414,9 +410,15 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
dg.mVertCount = 4;
|
||||
dg.mTexture = img;
|
||||
if (img->isWarped()) dg.mFlags |= DTF_Wrap;
|
||||
if (parms.indexed) dg.mFlags |= DTF_Indexed;
|
||||
|
||||
dg.mTranslationId = 0;
|
||||
SetStyle(img, parms, vertexcolor, dg);
|
||||
if (parms.indexed)
|
||||
{
|
||||
dg.mLightLevel = vertexcolor.Luminance();
|
||||
vertexcolor = 0xffffffff;
|
||||
}
|
||||
|
||||
if (!img->isHardwareCanvas() && parms.TranslationId != -1)
|
||||
{
|
||||
|
@ -427,44 +429,94 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
u2 = parms.srcx + parms.srcwidth;
|
||||
v2 = parms.srcy + parms.srcheight;
|
||||
|
||||
if (parms.flipX)
|
||||
std::swap(u1, u2);
|
||||
|
||||
if (parms.flipY)
|
||||
std::swap(v1, v2);
|
||||
|
||||
// This is crap. Only kept for backwards compatibility with scripts that may have used it.
|
||||
// Note that this only works for unflipped full textures.
|
||||
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
|
||||
if (parms.flipX)
|
||||
{
|
||||
double wi = std::min(parms.windowright, parms.texwidth);
|
||||
x += parms.windowleft * xscale;
|
||||
w -= (parms.texwidth - wi + parms.windowleft) * xscale;
|
||||
|
||||
u1 = float(u1 + parms.windowleft / parms.texwidth);
|
||||
u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
|
||||
std::swap(u1, u2);
|
||||
}
|
||||
|
||||
if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip)
|
||||
if (parms.flipY)
|
||||
{
|
||||
std::swap(v1, v2);
|
||||
}
|
||||
|
||||
if (parms.rotateangle == 0)
|
||||
{
|
||||
double x = parms.x - parms.left * xscale;
|
||||
double y = parms.y - parms.top * yscale;
|
||||
double w = parms.destwidth;
|
||||
double h = parms.destheight;
|
||||
|
||||
|
||||
// This is crap. Only kept for backwards compatibility with scripts that may have used it.
|
||||
// Note that this only works for unflipped and unrotated full textures.
|
||||
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
|
||||
{
|
||||
double wi = std::min(parms.windowright, parms.texwidth);
|
||||
x += parms.windowleft * xscale;
|
||||
w -= (parms.texwidth - wi + parms.windowleft) * xscale;
|
||||
|
||||
u1 = float(u1 + parms.windowleft / parms.texwidth);
|
||||
u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
|
||||
}
|
||||
|
||||
if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip)
|
||||
{
|
||||
dg.mScissor[0] = parms.lclip;
|
||||
dg.mScissor[1] = parms.uclip;
|
||||
dg.mScissor[2] = parms.rclip;
|
||||
dg.mScissor[3] = parms.dclip;
|
||||
dg.mFlags |= DTF_Scissor;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(dg.mScissor, 0, sizeof(dg.mScissor));
|
||||
}
|
||||
|
||||
dg.mVertCount = 4;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
TwoDVertex* ptr = &mVertices[dg.mVertIndex];
|
||||
ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
double radang = parms.rotateangle * (pi::pi() / 180.);
|
||||
double cosang = cos(radang);
|
||||
double sinang = sin(radang);
|
||||
double xd1 = -parms.left;
|
||||
double yd1 = -parms.top;
|
||||
double xd2 = xd1 + parms.texwidth;
|
||||
double yd2 = yd1 + parms.texheight;
|
||||
|
||||
double x1 = parms.x + xscale * (xd1 * cosang + yd1 * sinang);
|
||||
double y1 = parms.y - yscale * (xd1 * sinang - yd1 * cosang);
|
||||
|
||||
double x2 = parms.x + xscale * (xd1 * cosang + yd2 * sinang);
|
||||
double y2 = parms.y - yscale * (xd1 * sinang - yd2 * cosang);
|
||||
|
||||
double x3 = parms.x + xscale * (xd2 * cosang + yd1 * sinang);
|
||||
double y3 = parms.y - yscale * (xd2 * sinang - yd1 * cosang);
|
||||
|
||||
double x4 = parms.x + xscale * (xd2 * cosang + yd2 * sinang);
|
||||
double y4 = parms.y - yscale * (xd2 * sinang - yd2 * cosang);
|
||||
|
||||
dg.mScissor[0] = parms.lclip;
|
||||
dg.mScissor[1] = parms.uclip;
|
||||
dg.mScissor[2] = parms.rclip;
|
||||
dg.mScissor[3] = parms.dclip;
|
||||
dg.mFlags |= DTF_Scissor;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(dg.mScissor, 0, sizeof(dg.mScissor));
|
||||
}
|
||||
|
||||
dg.mVertCount = 4;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
TwoDVertex *ptr = &mVertices[dg.mVertIndex];
|
||||
ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++;
|
||||
dg.mVertCount = 4;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
TwoDVertex* ptr = &mVertices[dg.mVertIndex];
|
||||
ptr->Set(x1, y1, 0, u1, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x2, y2, 0, u1, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x3, y3, 0, u2, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x4, y4, 0, u2, v2, vertexcolor); ptr++;
|
||||
|
||||
}
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -693,7 +745,7 @@ float F2DDrawer::GetClassicFlatScalarHeight()
|
|||
return sh;
|
||||
}
|
||||
|
||||
void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin, double flatscale)
|
||||
void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin, double flatscale, PalEntry color)
|
||||
{
|
||||
float fU1, fU2, fV1, fV2;
|
||||
|
||||
|
@ -789,18 +841,18 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu
|
|||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
auto ptr = &mVertices[dg.mVertIndex];
|
||||
|
||||
ptr->Set(left, top, 0, fU1, fV1, 0xffffffff); ptr++;
|
||||
ptr->Set(left, top, 0, fU1, fV1, color); ptr++;
|
||||
if (local_origin < 4)
|
||||
{
|
||||
ptr->Set(left, bottom, 0, fU1, fV2, 0xffffffff); ptr++;
|
||||
ptr->Set(right, top, 0, fU2, fV1, 0xffffffff); ptr++;
|
||||
ptr->Set(left, bottom, 0, fU1, fV2, color); ptr++;
|
||||
ptr->Set(right, top, 0, fU2, fV1, color); ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->Set(left, bottom, 0, fU2, fV1, 0xffffffff); ptr++;
|
||||
ptr->Set(right, top, 0, fU1, fV2, 0xffffffff); ptr++;
|
||||
ptr->Set(left, bottom, 0, fU2, fV1, color); ptr++;
|
||||
ptr->Set(right, top, 0, fU1, fV2, color); ptr++;
|
||||
}
|
||||
ptr->Set(right, bottom, 0, fU2, fV2, 0xffffffff); ptr++;
|
||||
ptr->Set(right, bottom, 0, fU2, fV2, color); ptr++;
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -945,8 +997,12 @@ void F2DDrawer::AddPixel(int x1, int y1, uint32_t color)
|
|||
|
||||
void F2DDrawer::Clear()
|
||||
{
|
||||
mVertices.Clear();
|
||||
mIndices.Clear();
|
||||
mData.Clear();
|
||||
mIsFirstPass = true;
|
||||
if (!locked)
|
||||
{
|
||||
mVertices.Clear();
|
||||
mIndices.Clear();
|
||||
mData.Clear();
|
||||
mIsFirstPass = true;
|
||||
}
|
||||
screenFade = 1.f;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
DTF_Wrap = 1,
|
||||
DTF_Scissor = 2,
|
||||
DTF_Burn = 4,
|
||||
DTF_Indexed = 8,
|
||||
};
|
||||
|
||||
|
||||
|
@ -164,6 +165,8 @@ public:
|
|||
TArray<RenderCommand> mData;
|
||||
int Width, Height;
|
||||
bool isIn2D;
|
||||
bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades)
|
||||
float screenFade = 1.f;
|
||||
public:
|
||||
int fullscreenautoaspect = 0;
|
||||
int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1;
|
||||
|
@ -186,7 +189,7 @@ public:
|
|||
void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex,
|
||||
int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin = false, double flatscale = 1.0);
|
||||
void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin = false, double flatscale = 1.0, PalEntry color = 0xffffffff);
|
||||
|
||||
void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style = nullptr, bool prepend = false);
|
||||
void ClearScreen(PalEntry color = 0xff000000);
|
||||
|
@ -199,6 +202,9 @@ public:
|
|||
void AddPixel(int x1, int y1, uint32_t color);
|
||||
|
||||
void Clear();
|
||||
void Lock() { locked = true; }
|
||||
void SetScreenFade(float factor) { screenFade = factor; }
|
||||
void Unlock() { locked = false; }
|
||||
int GetWidth() const { return Width; }
|
||||
int GetHeight() const { return Height; }
|
||||
void SetSize(int w, int h) { Width = w; Height = h; }
|
||||
|
@ -210,6 +216,11 @@ public:
|
|||
void SetClipRect(int x, int y, int w, int h);
|
||||
void GetClipRect(int* x, int* y, int* w, int* h);
|
||||
|
||||
int DrawCount() const
|
||||
{
|
||||
return mData.Size();
|
||||
}
|
||||
|
||||
bool mIsFirstPass = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ EXTERN_CVAR(Int, vid_aspect)
|
|||
EXTERN_CVAR(Int, uiscale)
|
||||
CVAR(Bool, ui_screenborder_classic_scaling, true, CVAR_ARCHIVE)
|
||||
|
||||
static void VirtualToRealCoords(F2DDrawer* drawer, double Width, double Height, double& x, double& y, double& w, double& h,
|
||||
double vwidth, double vheight, bool vbottom, bool handleaspect);
|
||||
|
||||
// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none.
|
||||
int ActiveFakeRatio(int width, int height)
|
||||
{
|
||||
|
@ -187,6 +190,7 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t
|
|||
va_start(tags.list, tags_first);
|
||||
DrawParms parms;
|
||||
|
||||
if (!img || !img->isValid()) return;
|
||||
bool res = ParseDrawTextureTags(drawer, img, x, y, tags_first, tags, &parms, false);
|
||||
va_end(tags.list);
|
||||
if (!res)
|
||||
|
@ -208,6 +212,7 @@ static void DrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y
|
|||
{
|
||||
DrawParms parms;
|
||||
uint32_t tag = ListGetInt(args);
|
||||
if (!img || !img->isValid()) return;
|
||||
bool res = ParseDrawTextureTags(drawer, img, x, y, tag, args, &parms, false);
|
||||
if (!res) return;
|
||||
drawer->AddTexture(img, parms);
|
||||
|
@ -330,10 +335,19 @@ DEFINE_ACTION_FUNCTION(_Screen, GetClipRect)
|
|||
}
|
||||
|
||||
|
||||
static void CalcFullscreenScale(F2DDrawer* drawer, double srcwidth, double srcheight, int autoaspect, DoubleRect &rect)
|
||||
void CalcFullscreenScale(DrawParms *parms, double srcwidth, double srcheight, int oautoaspect, DoubleRect &rect)
|
||||
{
|
||||
auto GetWidth = [=]() { return drawer->GetWidth(); };
|
||||
auto GetHeight = [=]() {return drawer->GetHeight(); };
|
||||
auto GetWidth = [=]() { return parms->viewport.width; };
|
||||
auto GetHeight = [=]() {return parms->viewport.height; };
|
||||
|
||||
int autoaspect = oautoaspect;
|
||||
if (autoaspect == FSMode_ScaleToScreen)
|
||||
{
|
||||
rect.left = rect.top = 0;
|
||||
rect.width = GetWidth();
|
||||
rect.height = GetHeight();
|
||||
return;
|
||||
}
|
||||
|
||||
double aspect;
|
||||
if (srcheight == 200) aspect = srcwidth / 240.;
|
||||
|
@ -341,23 +355,35 @@ static void CalcFullscreenScale(F2DDrawer* drawer, double srcwidth, double srche
|
|||
else aspect = srcwidth / srcheight;
|
||||
rect.left = rect.top = 0;
|
||||
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
|
||||
if (autoaspect == 3)
|
||||
if (autoaspect == FSMode_ScaleToFit43 || autoaspect == FSMode_ScaleToFit43Top || autoaspect == FSMode_ScaleToFit43Bottom)
|
||||
{
|
||||
if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxed if the screen is taller than the image
|
||||
else if (screenratio > 1.32) autoaspect = 2; // on anything 4:3 and wider crop the sides of the image.
|
||||
// screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxed if the screen is taller than the image
|
||||
if (screenratio >= aspect || aspect < 1.4) autoaspect = FSMode_ScaleToFit;
|
||||
else if (screenratio > 1.32) autoaspect = FSMode_ScaleToFill; // on anything 4:3 and wider crop the sides of the image.
|
||||
else
|
||||
{
|
||||
// special case: Crop image to 4:3 and then letterbox this. This avoids too much cropping on narrow windows.
|
||||
double width4_3 = srcheight * (4. / 3.);
|
||||
rect.width = (double)GetWidth() * srcwidth / width4_3;
|
||||
rect.height = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image
|
||||
rect.top = (GetHeight() - rect.height) / 2;
|
||||
rect.left = -(srcwidth - width4_3) / 2;
|
||||
switch (oautoaspect)
|
||||
{
|
||||
default:
|
||||
rect.top = (GetHeight() - rect.height) / 2;
|
||||
break;
|
||||
case FSMode_ScaleToFit43Top:
|
||||
rect.top = 0;
|
||||
break;
|
||||
case FSMode_ScaleToFit43Bottom:
|
||||
rect.top = (GetHeight() - rect.height);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((screenratio > aspect) ^ (autoaspect == 2))
|
||||
if (autoaspect == FSMode_ScaleToHeight || (screenratio > aspect) ^ (autoaspect == FSMode_ScaleToFill))
|
||||
{
|
||||
// pillarboxed or vertically cropped (i.e. scale to height)
|
||||
rect.height = GetHeight();
|
||||
|
@ -369,10 +395,42 @@ static void CalcFullscreenScale(F2DDrawer* drawer, double srcwidth, double srche
|
|||
// letterboxed or horizontally cropped (i.e. scale to width)
|
||||
rect.width = GetWidth();
|
||||
rect.height = GetHeight() * screenratio / aspect;
|
||||
rect.top = (GetHeight() - rect.height) / 2;
|
||||
switch (oautoaspect)
|
||||
{
|
||||
default:
|
||||
rect.top = (GetHeight() - rect.height) / 2;
|
||||
break;
|
||||
case FSMode_ScaleToFit43Top:
|
||||
rect.top = 0;
|
||||
break;
|
||||
case FSMode_ScaleToFit43Bottom:
|
||||
rect.top = (GetHeight() - rect.height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetFullscreenRect)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_FLOAT(virtw);
|
||||
PARAM_FLOAT(virth);
|
||||
PARAM_INT(fsmode);
|
||||
|
||||
DrawParms parms;
|
||||
DoubleRect rect;
|
||||
parms.viewport.width = twod->GetWidth();
|
||||
parms.viewport.height = twod->GetHeight();
|
||||
CalcFullscreenScale(&parms, virtw, virth, fsmode, rect);
|
||||
if (numret >= 1) ret[0].SetFloat(rect.left);
|
||||
if (numret >= 2) ret[1].SetFloat(rect.top);
|
||||
if (numret >= 3) ret[2].SetFloat(rect.width);
|
||||
if (numret >= 4) ret[3].SetFloat(rect.height);
|
||||
return MIN(numret, 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Draw parameter parsing
|
||||
|
@ -381,8 +439,8 @@ static void CalcFullscreenScale(F2DDrawer* drawer, double srcwidth, double srche
|
|||
|
||||
bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, double xx, double yy)
|
||||
{
|
||||
auto GetWidth = [=]() { return drawer->GetWidth(); };
|
||||
auto GetHeight = [=]() {return drawer->GetHeight(); };
|
||||
auto GetWidth = [=]() { return parms->viewport.width; };
|
||||
auto GetHeight = [=]() {return parms->viewport.height; };
|
||||
if (img != NULL)
|
||||
{
|
||||
parms->x = xx;
|
||||
|
@ -399,12 +457,17 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
}
|
||||
if (parms->destwidth == INT_MAX || parms->fortext)
|
||||
{
|
||||
parms->destwidth = img->GetDisplayWidth();
|
||||
parms->destwidth = parms->texwidth;
|
||||
}
|
||||
if (parms->destheight == INT_MAX || parms->fortext)
|
||||
{
|
||||
parms->destheight = img->GetDisplayHeight();
|
||||
parms->destheight = parms->texheight;
|
||||
}
|
||||
parms->destwidth *= parms->patchscalex;
|
||||
parms->destheight *= parms->patchscaley;
|
||||
|
||||
if (parms->flipoffsets && parms->flipY) parms->top = parms->texheight - parms->top;
|
||||
if (parms->flipoffsets && parms->flipX) parms->left = parms->texwidth - parms->left;
|
||||
|
||||
switch (parms->cleanmode)
|
||||
{
|
||||
|
@ -418,6 +481,13 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
parms->destheight = parms->texheight * CleanYfac;
|
||||
break;
|
||||
|
||||
case DTA_CleanTop:
|
||||
parms->x = (parms->x - 160.0) * CleanXfac + (GetWidth() * 0.5);
|
||||
parms->y = (parms->y) * CleanYfac;
|
||||
parms->destwidth = parms->texwidth * CleanXfac;
|
||||
parms->destheight = parms->texheight * CleanYfac;
|
||||
break;
|
||||
|
||||
case DTA_CleanNoMove:
|
||||
parms->destwidth = parms->texwidth * CleanXfac;
|
||||
parms->destheight = parms->texheight * CleanYfac;
|
||||
|
@ -429,13 +499,14 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
break;
|
||||
|
||||
case DTA_Base:
|
||||
if (parms->fsscalemode != -1)
|
||||
if (parms->fsscalemode > 0)
|
||||
{
|
||||
// First calculate the destination rect for an image of the given size and then reposition this object in it.
|
||||
DoubleRect rect;
|
||||
CalcFullscreenScale(drawer, parms->virtWidth, parms->virtHeight, parms->fsscalemode, rect);
|
||||
parms->x = rect.left + parms->x * rect.width / parms->virtWidth;
|
||||
parms->y = rect.top + parms->y * rect.height / parms->virtHeight;
|
||||
CalcFullscreenScale(parms, parms->virtWidth, parms->virtHeight, parms->fsscalemode, rect);
|
||||
double adder = parms->keepratio < 0 ? 0 : parms->keepratio == 0 ? rect.left : 2 * rect.left;
|
||||
parms->x = parms->viewport.left + adder + parms->x * rect.width / parms->virtWidth;
|
||||
parms->y = parms->viewport.top + rect.top + parms->y * rect.height / parms->virtHeight;
|
||||
parms->destwidth = parms->destwidth * rect.width / parms->virtWidth;
|
||||
parms->destheight = parms->destheight * rect.height / parms->virtHeight;
|
||||
return false;
|
||||
|
@ -446,12 +517,13 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
case DTA_FullscreenEx:
|
||||
{
|
||||
DoubleRect rect;
|
||||
CalcFullscreenScale(drawer, img->GetDisplayWidth(), img->GetDisplayHeight(), parms->fsscalemode, rect);
|
||||
parms->keepratio = true;
|
||||
parms->x = rect.left;
|
||||
parms->y = rect.top;
|
||||
CalcFullscreenScale(parms, parms->texwidth, parms->texheight, parms->fsscalemode, rect);
|
||||
parms->keepratio = -1;
|
||||
parms->x = parms->viewport.left + rect.left;
|
||||
parms->y = parms->viewport.top + rect.top;
|
||||
parms->destwidth = rect.width;
|
||||
parms->destheight = rect.height;
|
||||
parms->top = parms->left = 0;
|
||||
return false; // Do not call VirtualToRealCoords for this!
|
||||
}
|
||||
|
||||
|
@ -478,9 +550,11 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
}
|
||||
if (parms->virtWidth != GetWidth() || parms->virtHeight != GetHeight())
|
||||
{
|
||||
VirtualToRealCoords(drawer, parms->x, parms->y, parms->destwidth, parms->destheight,
|
||||
VirtualToRealCoords(drawer, GetWidth(), GetHeight(), parms->x, parms->y, parms->destwidth, parms->destheight,
|
||||
parms->virtWidth, parms->virtHeight, parms->virtBottom, !parms->keepratio);
|
||||
}
|
||||
parms->x += parms->viewport.left;
|
||||
parms->y += parms->viewport.top;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -603,8 +677,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
parms->color = 0xffffffff;
|
||||
//parms->shadowAlpha = 0;
|
||||
parms->shadowColor = 0;
|
||||
parms->virtWidth = drawer->GetWidth();
|
||||
parms->virtHeight = drawer->GetHeight();
|
||||
parms->virtWidth = INT_MAX; // these need to match the viewport if not explicitly set, but we do not know that yet.
|
||||
parms->virtHeight = INT_MAX;
|
||||
parms->keepratio = false;
|
||||
parms->style.BlendOp = 255; // Dummy "not set" value
|
||||
parms->masked = true;
|
||||
|
@ -624,6 +698,11 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
parms->monospace = EMonospacing::Off;
|
||||
parms->spacing = 0;
|
||||
parms->fsscalemode = -1;
|
||||
parms->patchscalex = parms->patchscaley = 1;
|
||||
parms->viewport = { 0,0,drawer->GetWidth(), drawer->GetHeight() };
|
||||
parms->rotateangle = 0;
|
||||
parms->flipoffsets = false;
|
||||
parms->indexed = false;
|
||||
|
||||
// Parse the tag list for attributes. (For floating point attributes,
|
||||
// consider that the C ABI dictates that all floats be promoted to
|
||||
|
@ -665,6 +744,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
break;
|
||||
|
||||
case DTA_Clean:
|
||||
case DTA_CleanTop:
|
||||
boolval = ListGetInt(tags);
|
||||
if (boolval)
|
||||
{
|
||||
|
@ -746,9 +826,18 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
|
||||
case DTA_FullscreenScale:
|
||||
intval = ListGetInt(tags);
|
||||
if (intval >= 0 && intval <= 3)
|
||||
if (intval >= FSMode_None && intval < FSMode_Max)
|
||||
{
|
||||
parms->fsscalemode = (uint8_t)intval;
|
||||
parms->fsscalemode = (int8_t)intval;
|
||||
}
|
||||
else if (intval >= FSMode_Predefined && intval < FSMode_Predefined_Max)
|
||||
{
|
||||
static const uint8_t modes[] = { FSMode_ScaleToFit43, FSMode_ScaleToFit43, FSMode_ScaleToFit43, FSMode_ScaleToFit43, FSMode_ScaleToFit43Top};
|
||||
static const uint16_t widths[] = { 320, 320, 640, 640, 320};
|
||||
static const uint16_t heights[] = { 200, 240, 400, 480, 200};
|
||||
parms->fsscalemode = modes[intval - FSMode_Predefined];
|
||||
parms->virtWidth = widths[intval - FSMode_Predefined];
|
||||
parms->virtHeight = heights[intval - FSMode_Predefined];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -821,6 +910,10 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
parms->flipY = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_FlipOffsets:
|
||||
parms->flipoffsets = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_SrcX:
|
||||
parms->srcx = ListGetDouble(tags) / img->GetDisplayWidth();
|
||||
break;
|
||||
|
@ -861,6 +954,16 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
parms->left = ListGetDouble(tags);
|
||||
break;
|
||||
|
||||
case DTA_TopLeft:
|
||||
assert(fortext == false);
|
||||
if (fortext) return false;
|
||||
if (ListGetInt(tags))
|
||||
{
|
||||
parms->left = 0;
|
||||
parms->top = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DTA_CenterOffset:
|
||||
assert(fortext == false);
|
||||
if (fortext) return false;
|
||||
|
@ -871,6 +974,16 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
}
|
||||
break;
|
||||
|
||||
case DTA_CenterOffsetRel:
|
||||
assert(fortext == false);
|
||||
if (fortext) return false;
|
||||
if (ListGetInt(tags))
|
||||
{
|
||||
parms->left = img->GetDisplayLeftOffset() + img->GetDisplayWidth() * 0.5;
|
||||
parms->top = img->GetDisplayTopOffset() + img->GetDisplayHeight() * 0.5;
|
||||
}
|
||||
break;
|
||||
|
||||
case DTA_CenterBottomOffset:
|
||||
assert(fortext == false);
|
||||
if (fortext) return false;
|
||||
|
@ -958,6 +1071,14 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
}
|
||||
break;
|
||||
|
||||
case DTA_ScaleX:
|
||||
parms->patchscalex = ListGetDouble(tags);
|
||||
break;
|
||||
|
||||
case DTA_ScaleY:
|
||||
parms->patchscaley = ListGetDouble(tags);
|
||||
break;
|
||||
|
||||
case DTA_Masked:
|
||||
parms->masked = ListGetInt(tags);
|
||||
break;
|
||||
|
@ -967,8 +1088,10 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
break;
|
||||
|
||||
case DTA_KeepRatio:
|
||||
// I think this is a terribly misleading name, since it actually turns
|
||||
// *off* aspect ratio correction.
|
||||
parms->keepratio = ListGetInt(tags) ? -1 : 0;
|
||||
break;
|
||||
|
||||
case DTA_Pin:
|
||||
parms->keepratio = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
|
@ -1012,11 +1135,39 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
parms->burn = true;
|
||||
break;
|
||||
|
||||
case DTA_ViewportX:
|
||||
parms->viewport.left = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_ViewportY:
|
||||
parms->viewport.top = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_ViewportWidth:
|
||||
parms->viewport.width = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_ViewportHeight:
|
||||
parms->viewport.height = ListGetInt(tags);
|
||||
break;
|
||||
|
||||
case DTA_Rotate:
|
||||
assert(fortext == false);
|
||||
if (fortext) return false;
|
||||
parms->rotateangle = ListGetDouble(tags);
|
||||
break;
|
||||
|
||||
case DTA_Indexed:
|
||||
parms->indexed = !!ListGetInt(tags);
|
||||
break;
|
||||
}
|
||||
tag = ListGetInt(tags);
|
||||
}
|
||||
ListEnd(tags);
|
||||
|
||||
if (parms->virtWidth == INT_MAX) parms->virtWidth = parms->viewport.width;
|
||||
if (parms->virtHeight == INT_MAX) parms->virtHeight = parms->viewport.height;
|
||||
|
||||
auto clipleft = drawer->clipleft;
|
||||
auto cliptop = drawer->cliptop;
|
||||
auto clipwidth = drawer->clipwidth;
|
||||
|
@ -1084,12 +1235,10 @@ template bool ParseDrawTextureTags<VMVa_List>(F2DDrawer* drawer, FGameTexture *i
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void VirtualToRealCoords(F2DDrawer *drawer, double &x, double &y, double &w, double &h,
|
||||
static void VirtualToRealCoords(F2DDrawer *drawer, double Width, double Height, double &x, double &y, double &w, double &h,
|
||||
double vwidth, double vheight, bool vbottom, bool handleaspect)
|
||||
{
|
||||
auto Width = drawer->GetWidth();
|
||||
auto Height = drawer->GetHeight();
|
||||
float myratio = handleaspect ? ActiveRatio (Width, Height) : (4.0f / 3.0f);
|
||||
float myratio = float(handleaspect ? ActiveRatio (Width, Height) : (4.0 / 3.0));
|
||||
|
||||
// if 21:9 AR, map to 16:9 for all callers.
|
||||
// this allows for black bars and stops the stretching of fullscreen images
|
||||
|
@ -1129,6 +1278,14 @@ void VirtualToRealCoords(F2DDrawer *drawer, double &x, double &y, double &w, dou
|
|||
}
|
||||
}
|
||||
|
||||
void VirtualToRealCoords(F2DDrawer* drawer, double& x, double& y, double& w, double& h,
|
||||
double vwidth, double vheight, bool vbottom, bool handleaspect)
|
||||
{
|
||||
auto Width = drawer->GetWidth();
|
||||
auto Height = drawer->GetHeight();
|
||||
VirtualToRealCoords(drawer, Width, Height, x, y, w, h, vwidth, vheight, vbottom, handleaspect);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "v_2ddrawer.h"
|
||||
#include "c_cvars.h"
|
||||
#include "intrect.h"
|
||||
|
||||
// TagItem definitions for DrawTexture. As far as I know, tag lists
|
||||
// originated on the Amiga.
|
||||
|
@ -13,11 +14,38 @@
|
|||
// uint32_t ti_Data;
|
||||
// };
|
||||
|
||||
#define TAG_DONE (0) /* Used to indicate the end of the Tag list */
|
||||
#define TAG_END (0) /* Ditto */
|
||||
/* list pointed to in ti_Data */
|
||||
enum tags : uint32_t
|
||||
{
|
||||
TAG_DONE = (0), /* Used to indicate the end of the Tag list */
|
||||
TAG_END = (0), /* Ditto */
|
||||
/* list pointed to in ti_Data */
|
||||
|
||||
#define TAG_USER ((uint32_t)(1u<<30))
|
||||
TAG_USER = ((uint32_t)(1u << 30))
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FSMode_None = 0,
|
||||
FSMode_ScaleToFit = 1,
|
||||
FSMode_ScaleToFill = 2,
|
||||
FSMode_ScaleToFit43 = 3,
|
||||
FSMode_ScaleToScreen = 4,
|
||||
FSMode_ScaleToFit43Top = 5,
|
||||
FSMode_ScaleToFit43Bottom = 6,
|
||||
FSMode_ScaleToHeight = 7,
|
||||
|
||||
|
||||
FSMode_Max,
|
||||
|
||||
// These all use ScaleToFit43, their purpose is to cut down on verbosity because they imply the virtual screen size.
|
||||
FSMode_Predefined = 1000,
|
||||
FSMode_Fit320x200 = 1000,
|
||||
FSMode_Fit320x240,
|
||||
FSMode_Fit640x400,
|
||||
FSMode_Fit640x480,
|
||||
FSMode_Fit320x200Top,
|
||||
FSMode_Predefined_Max,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -89,6 +117,20 @@ enum
|
|||
|
||||
DTA_FullscreenEx,
|
||||
DTA_FullscreenScale,
|
||||
DTA_ScaleX,
|
||||
DTA_ScaleY,
|
||||
|
||||
DTA_ViewportX, // Defines the viewport on the screen that should be rendered to.
|
||||
DTA_ViewportY,
|
||||
DTA_ViewportWidth,
|
||||
DTA_ViewportHeight,
|
||||
DTA_CenterOffsetRel, // Apply texture offsets relative to center, instead of top left. This is standard alignment for Build's 2D content.
|
||||
DTA_TopLeft, // always align to top left. Added to have a boolean condition for this alignment.
|
||||
DTA_Pin, // Pin a non-widescreen image to the left/right edge of the screen.
|
||||
DTA_Rotate,
|
||||
DTA_FlipOffsets, // Flips offsets when using DTA_FlipX and DTA_FlipY, this cannot be automatic due to unexpected behavior with unoffsetted graphics.
|
||||
DTA_Indexed, // Use an indexed texture combined with the given translation.
|
||||
DTA_CleanTop, // Like DTA_Clean but aligns to the top of the screen instead of the center.
|
||||
|
||||
};
|
||||
|
||||
|
@ -154,9 +196,14 @@ struct DrawParms
|
|||
bool fortext;
|
||||
bool virtBottom;
|
||||
bool burn;
|
||||
bool flipoffsets;
|
||||
bool indexed;
|
||||
int8_t fsscalemode;
|
||||
double srcx, srcy;
|
||||
double srcwidth, srcheight;
|
||||
double patchscalex, patchscaley;
|
||||
double rotateangle;
|
||||
IntRect viewport;
|
||||
};
|
||||
|
||||
struct Va_List
|
||||
|
@ -187,14 +234,8 @@ int GetUIScale(F2DDrawer* drawer, int altval);
|
|||
int GetConScale(F2DDrawer* drawer, int altval);
|
||||
|
||||
EXTERN_CVAR(Int, uiscale);
|
||||
EXTERN_CVAR(Int, con_scaletext);
|
||||
EXTERN_CVAR(Int, con_scale);
|
||||
|
||||
inline int active_con_scaletext(F2DDrawer* drawer, bool newconfont = false)
|
||||
{
|
||||
return newconfont ? GetConScale(drawer, con_scaletext) : GetUIScale(drawer, con_scaletext);
|
||||
}
|
||||
|
||||
inline int active_con_scale(F2DDrawer *drawer)
|
||||
{
|
||||
return GetConScale(drawer, con_scale);
|
||||
|
|
|
@ -258,8 +258,13 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d
|
|||
int kerning;
|
||||
FGameTexture *pic;
|
||||
|
||||
double scalex = parms.scalex * parms.patchscalex;
|
||||
double scaley = parms.scaley * parms.patchscaley;
|
||||
|
||||
if (parms.celly == 0) parms.celly = font->GetHeight() + 1;
|
||||
parms.celly *= parms.scaley;
|
||||
parms.celly = int (parms.celly * scaley);
|
||||
|
||||
bool palettetrans = (normalcolor == CR_UNDEFINED && parms.TranslationId != 0);
|
||||
|
||||
if (normalcolor >= NumTextColors)
|
||||
normalcolor = CR_UNTRANSLATED;
|
||||
|
@ -267,7 +272,7 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d
|
|||
|
||||
PalEntry colorparm = parms.color;
|
||||
PalEntry color = 0xffffffff;
|
||||
trans = font->GetColorTranslation((EColorRange)normalcolor, &color);
|
||||
trans = palettetrans? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color);
|
||||
parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255);
|
||||
|
||||
kerning = font->GetDefaultKerning();
|
||||
|
@ -311,7 +316,8 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d
|
|||
bool redirected = false;
|
||||
if (NULL != (pic = font->GetChar(c, currentcolor, &w, &redirected)))
|
||||
{
|
||||
parms.TranslationId = redirected? -1 : trans;
|
||||
// if palette translation is used, font colors will be ignored.
|
||||
if (!palettetrans) parms.TranslationId = redirected? -1 : trans;
|
||||
SetTextureParms(drawer, &parms, pic, cx, cy);
|
||||
if (parms.cellx)
|
||||
{
|
||||
|
@ -330,11 +336,11 @@ void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, d
|
|||
}
|
||||
if (parms.monospace == EMonospacing::Off)
|
||||
{
|
||||
cx += (w + kerning + parms.spacing) * parms.scalex;
|
||||
cx += (w + kerning + parms.spacing) * scalex;
|
||||
}
|
||||
else
|
||||
{
|
||||
cx += (parms.spacing) * parms.scalex;
|
||||
cx += (parms.spacing) * scalex;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -95,6 +95,26 @@ void S_SetMusicCallbacks(MusicCallbacks* cb)
|
|||
|
||||
static std::unique_ptr<SoundStream> musicStream;
|
||||
|
||||
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata)
|
||||
{
|
||||
int flags = 0;
|
||||
if (numchannels < 2) flags |= SoundStream::Mono;
|
||||
auto stream = GSnd->CreateStream(cb, size, flags, samplerate, userdata);
|
||||
if (stream) stream->Play(true, 1);
|
||||
return stream;
|
||||
}
|
||||
|
||||
void S_StopCustomStream(SoundStream *stream)
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
stream->Stop();
|
||||
delete stream;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
|
||||
{
|
||||
bool written = ZMusic_FillStream(mus_playing.handle, buff, len);
|
||||
|
@ -123,6 +143,7 @@ void S_CreateStream()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void S_PauseStream(bool paused)
|
||||
{
|
||||
if (musicStream) musicStream->SetPaused(paused);
|
||||
|
@ -298,7 +319,7 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
|||
|
||||
if (!force && PlayList.GetNumSongs())
|
||||
{ // Don't change if a playlist is active
|
||||
return false;
|
||||
return true; // do not report an error here.
|
||||
}
|
||||
// Do game specific lookup.
|
||||
FString musicname_;
|
||||
|
|
|
@ -99,9 +99,9 @@ CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR
|
|||
FORWARD_STRING_CVAR(adl_custom_bank);
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, adl_volume_model, 3/*ADLMIDI_VolumeModel_DMX*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
CUSTOM_CVAR(Int, adl_volume_model, 0 /*ADLMIDI_VolumeModel_AUTO*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
{
|
||||
FORWARD_CVAR(adl_bank);
|
||||
FORWARD_CVAR(adl_volume_model);
|
||||
}
|
||||
#endif
|
||||
//==========================================================================
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
#include <zmusic.h>
|
||||
|
||||
class FileReader;
|
||||
class SoundStream;
|
||||
|
||||
|
||||
typedef bool(*StreamCallback)(SoundStream* stream, void* buff, int len, void* userdata);
|
||||
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata);
|
||||
void S_StopCustomStream(SoundStream* stream);
|
||||
|
||||
struct MusicCallbacks
|
||||
{
|
||||
|
|
|
@ -181,7 +181,7 @@ class OpenALSoundStream : public SoundStream
|
|||
ALuint Source;
|
||||
|
||||
std::atomic<bool> Playing;
|
||||
bool Looping;
|
||||
//bool Looping;
|
||||
ALfloat Volume;
|
||||
|
||||
bool SetupSource()
|
||||
|
@ -227,7 +227,7 @@ class OpenALSoundStream : public SoundStream
|
|||
|
||||
public:
|
||||
OpenALSoundStream(OpenALSoundRenderer *renderer)
|
||||
: Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f)
|
||||
: Renderer(renderer), Source(0), Playing(false), Volume(1.0f)
|
||||
{
|
||||
memset(Buffers, 0, sizeof(Buffers));
|
||||
Renderer->AddStream(this);
|
||||
|
@ -1098,6 +1098,10 @@ SoundHandle OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length)
|
|||
data.resize(total * 2);
|
||||
}
|
||||
data.resize(total);
|
||||
if (total == 0)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
SoundDecoder_Close(decoder);
|
||||
|
||||
ALenum err;
|
||||
|
@ -1516,6 +1520,9 @@ void OpenALSoundRenderer::StopChannel(FISoundChannel *chan)
|
|||
if((i=SfxGroup.Find(source)) < SfxGroup.Size())
|
||||
SfxGroup.Delete(i);
|
||||
|
||||
if (!(chan->ChanFlags & CHANF_EVICTED))
|
||||
soundEngine->SoundDone(chan);
|
||||
|
||||
FreeSfx.Push(source);
|
||||
}
|
||||
|
||||
|
|
|
@ -183,20 +183,31 @@ static ReverbContainer Underwater =
|
|||
false
|
||||
};
|
||||
|
||||
static ReverbContainer SewerPipe4 =
|
||||
static ReverbContainer SewerPipe3 =
|
||||
{
|
||||
&Underwater,
|
||||
"Sewer Pipe 2",
|
||||
"Sewer Pipe 3",
|
||||
0x1503,
|
||||
true,
|
||||
false,
|
||||
{0,21, 1.7f, 0.80f, -1000, -1000, 0, 1.54f, 0.14f, 1.0f, 200, 0.014f, 0.0f,0.0f,0.0f, 1023, 0.021f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 80.0f, 60.0f, 0x3f },
|
||||
false
|
||||
};
|
||||
|
||||
static ReverbContainer SewerPipe2 =
|
||||
{
|
||||
&SewerPipe3,
|
||||
"Sewer Pipe 2",
|
||||
0x1502,
|
||||
true,
|
||||
false,
|
||||
{0,21, 1.7f, 0.80f, -1000, -1000, 0, 1.81f, 0.14f, 1.0f, 229, 0.014f, 0.0f,0.0f,0.0f, 1023, 0.021f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 80.0f, 60.0f, 0x3f },
|
||||
false
|
||||
};
|
||||
|
||||
static ReverbContainer SewerPipe =
|
||||
{
|
||||
&SewerPipe4,
|
||||
&SewerPipe2,
|
||||
"Sewer Pipe",
|
||||
0x1500,
|
||||
true,
|
||||
|
|
|
@ -41,13 +41,14 @@
|
|||
#include "m_swap.h"
|
||||
#include "superfasthash.h"
|
||||
#include "s_music.h"
|
||||
#include "m_random.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_PITCH = 128,
|
||||
};
|
||||
|
||||
static FRandom pr_soundpitch ("SoundPitch");
|
||||
SoundEngine* soundEngine;
|
||||
int sfx_empty = -1;
|
||||
|
||||
|
@ -405,6 +406,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
int near_limit = sfx->NearLimit;
|
||||
float limit_range = sfx->LimitRange;
|
||||
float defpitch = sfx->DefPitch;
|
||||
float defpitchmax = sfx->DefPitchMax;
|
||||
auto pitchmask = sfx->PitchMask;
|
||||
rolloff = &sfx->Rolloff;
|
||||
|
||||
|
@ -421,6 +423,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
near_limit = newsfx->NearLimit;
|
||||
limit_range = newsfx->LimitRange;
|
||||
defpitch = newsfx->DefPitch;
|
||||
defpitchmax = newsfx->DefPitchMax;
|
||||
}
|
||||
if (rolloff->MinDistance == 0)
|
||||
{
|
||||
|
@ -551,8 +554,8 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
|
||||
float sfxlength = (float)GSnd->GetMSLength(sfx->data) / 1000.f;
|
||||
startTime = (startflags & SNDF_LOOP)
|
||||
? (sfxlength > 0 ? fmod(startTime, sfxlength) : 0)
|
||||
: clamp<float>(startTime, 0.f, sfxlength);
|
||||
? (sfxlength > 0 ? fmodf(startTime, sfxlength) : 0.f)
|
||||
: clamp(startTime, 0.f, sfxlength);
|
||||
|
||||
if (attenuation > 0 && type != SOURCE_None)
|
||||
{
|
||||
|
@ -590,6 +593,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
chan->Priority = basepriority;
|
||||
chan->DistanceScale = float(attenuation);
|
||||
chan->SourceType = type;
|
||||
chan->UserData = 0;
|
||||
if (type == SOURCE_Unattached)
|
||||
{
|
||||
chan->Point[0] = pt->X; chan->Point[1] = pt->Y; chan->Point[2] = pt->Z;
|
||||
|
@ -602,7 +606,23 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
if (spitch > 0.0) // A_StartSound has top priority over all others.
|
||||
SetPitch(chan, spitch);
|
||||
else if (defpitch > 0.0) // $PitchSet overrides $PitchShift
|
||||
{
|
||||
if (defpitchmax > 0.0)
|
||||
{
|
||||
if (defpitchmax < defpitch)
|
||||
std::swap(defpitch, defpitchmax);
|
||||
|
||||
if (defpitch != defpitchmax)
|
||||
{
|
||||
FRandom &rng = pr_soundpitch;
|
||||
int random = (rng)(0x7FFF);
|
||||
float frandom = random / float(0x7FFF);
|
||||
|
||||
defpitch = frandom * (defpitchmax - defpitch) + defpitch;
|
||||
}
|
||||
}
|
||||
SetPitch(chan, defpitch);
|
||||
}
|
||||
}
|
||||
|
||||
return chan;
|
||||
|
@ -1074,6 +1094,16 @@ int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int so
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (FSoundChan* chan = Channels; chan != NULL; chan = chan->NextChan)
|
||||
{
|
||||
if ((sourcetype == SOURCE_Any || (chan->SourceType == sourcetype && chan->Source == source)))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -1327,13 +1357,29 @@ void SoundEngine::ChannelEnded(FISoundChannel *ichan)
|
|||
}
|
||||
if (!evicted)
|
||||
{
|
||||
ReturnChannel(schan);
|
||||
schan->ChanFlags &= ~CHANF_EVICTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
schan->ChanFlags |= CHANF_EVICTED;
|
||||
schan->SysChannel = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SoundEngine::SoundDone(FISoundChannel* ichan)
|
||||
{
|
||||
FSoundChan* schan = static_cast<FSoundChan*>(ichan);
|
||||
if (schan != NULL)
|
||||
{
|
||||
ReturnChannel(schan);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1495,6 +1541,7 @@ int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitc
|
|||
newsfx.Attenuation = 1;
|
||||
newsfx.PitchMask = CurrentPitchMask;
|
||||
newsfx.DefPitch = 0.0;
|
||||
newsfx.DefPitchMax = 0.0;
|
||||
newsfx.NearLimit = nearlimit;
|
||||
newsfx.LimitRange = 256 * 256;
|
||||
newsfx.bRandomHeader = false;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct sfxinfo_t
|
|||
int16_t NearLimit; // 0 means unlimited
|
||||
float LimitRange; // Range for sound limiting (squared for faster computations)
|
||||
float DefPitch; // A defined pitch instead of a random one the sound plays at, similar to A_StartSound.
|
||||
float DefPitchMax; // Randomized range with stronger control over pitch itself.
|
||||
|
||||
unsigned bRandomHeader:1;
|
||||
unsigned bLoadRAW:1;
|
||||
|
@ -165,6 +166,7 @@ struct FSoundChan : public FISoundChannel
|
|||
FSoundID OrgID; // Sound ID of sound used to start this channel.
|
||||
float Volume;
|
||||
int EntChannel; // Actor's sound channel.
|
||||
int UserData; // Not used by the engine, the caller can use this to store some additional info.
|
||||
int16_t Pitch; // Pitch variation.
|
||||
int16_t NearLimit;
|
||||
int8_t Priority;
|
||||
|
@ -302,6 +304,10 @@ public:
|
|||
virtual void CacheSound(sfxinfo_t* sfx);
|
||||
void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); }
|
||||
void UnloadSound(sfxinfo_t* sfx);
|
||||
void UnloadSound(int sfx)
|
||||
{
|
||||
UnloadSound(&S_sfx[sfx]);
|
||||
}
|
||||
|
||||
void UpdateSounds(int time);
|
||||
|
||||
|
@ -409,6 +415,7 @@ public:
|
|||
// Allow this to be overridden for special needs.
|
||||
virtual float GetRolloff(const FRolloffInfo* rolloff, float distance);
|
||||
virtual void ChannelEnded(FISoundChannel* ichan); // allows the client to do bookkeeping on the sound.
|
||||
virtual void SoundDone(FISoundChannel* ichan); // gets called when the sound has been completely taken down.
|
||||
|
||||
// Lookup utilities.
|
||||
int FindSound(const char* logicalname);
|
||||
|
|
|
@ -739,7 +739,7 @@ void C_SetDefaultKeys(const char* baseconfig)
|
|||
//
|
||||
//
|
||||
//=============================================================================
|
||||
CVAR(Int, cl_defaultconfiguration, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, cl_defaultconfiguration, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
void C_BindDefaults()
|
||||
|
|
|
@ -87,7 +87,6 @@ public:
|
|||
extern FKeyBindings Bindings;
|
||||
extern FKeyBindings DoubleBindings;
|
||||
extern FKeyBindings AutomapBindings;
|
||||
extern FKeyBindings MenuBindings;
|
||||
|
||||
|
||||
bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds);
|
||||
|
|
|
@ -57,6 +57,7 @@ extern constate_e ConsoleState;
|
|||
void C_InitConsole (int width, int height, bool ingame);
|
||||
void C_DeinitConsole ();
|
||||
void C_InitConback();
|
||||
void C_ClearMessages();
|
||||
|
||||
// Adjust the console for a new screen mode
|
||||
void C_NewModeAdjust (void);
|
||||
|
@ -83,6 +84,7 @@ bool C_Responder (event_t *ev);
|
|||
void C_AddTabCommand (const char *name);
|
||||
void C_RemoveTabCommand (const char *name);
|
||||
void C_ClearTabCommands(); // Removes all tab commands
|
||||
void C_SetNotifyFontScale(double scale);
|
||||
|
||||
extern const char *console_bar;
|
||||
|
||||
|
|
|
@ -150,6 +150,11 @@ const char *FBaseCVar::GetHumanString(int precision) const
|
|||
return GetGenericRep(CVAR_String).String;
|
||||
}
|
||||
|
||||
const char *FBaseCVar::GetHumanStringDefault(int precision) const
|
||||
{
|
||||
return GetGenericRepDefault(CVAR_String).String;
|
||||
}
|
||||
|
||||
void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend)
|
||||
{
|
||||
DoSet (value, type);
|
||||
|
@ -653,6 +658,16 @@ const char *FFloatCVar::GetHumanString(int precision) const
|
|||
return cstrbuf;
|
||||
}
|
||||
|
||||
const char *FFloatCVar::GetHumanStringDefault(int precision) const
|
||||
{
|
||||
if (precision < 0)
|
||||
{
|
||||
precision = 6;
|
||||
}
|
||||
mysnprintf(cstrbuf, countof(cstrbuf), "%.*g", precision, DefaultValue);
|
||||
return cstrbuf;
|
||||
}
|
||||
|
||||
UCVarValue FFloatCVar::GetGenericRep (ECVarType type) const
|
||||
{
|
||||
return FromFloat (Value, type);
|
||||
|
@ -1519,7 +1534,12 @@ CCMD (toggle)
|
|||
val = var->GetGenericRep (CVAR_Bool);
|
||||
val.Bool = !val.Bool;
|
||||
var->SetGenericRep (val, CVAR_Bool);
|
||||
Printf ("\"%s\" = \"%s\"\n", var->GetName(),
|
||||
auto msg = var->GetToggleMessage(val.Bool);
|
||||
if (msg.IsNotEmpty())
|
||||
{
|
||||
Printf(PRINT_NOTIFY, "%s\n", msg.GetChars());
|
||||
}
|
||||
else Printf ("\"%s\" = \"%s\"\n", var->GetName(),
|
||||
val.Bool ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,6 +161,7 @@ public:
|
|||
virtual UCVarValue GetGenericRep (ECVarType type) const = 0;
|
||||
virtual UCVarValue GetFavoriteRep (ECVarType *type) const = 0;
|
||||
|
||||
virtual const char *GetHumanStringDefault(int precision = -1) const;
|
||||
virtual UCVarValue GetGenericRepDefault (ECVarType type) const = 0;
|
||||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const = 0;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) = 0;
|
||||
|
@ -176,6 +177,13 @@ public:
|
|||
static void ListVars (const char *filter, bool plain);
|
||||
|
||||
const FString &GetDescription() const { return Description; };
|
||||
const FString& GetToggleMessage(int which) { return ToggleMessages[which]; }
|
||||
void SetToggleMessages(const char* on, const char* off)
|
||||
{
|
||||
ToggleMessages[0] = off;
|
||||
ToggleMessages[1] = on;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type) = 0;
|
||||
|
@ -192,13 +200,13 @@ protected:
|
|||
FString VarName;
|
||||
FString SafeValue;
|
||||
FString Description;
|
||||
FString ToggleMessages[2];
|
||||
uint32_t Flags;
|
||||
bool inCallback = false;
|
||||
|
||||
private:
|
||||
FBaseCVar (const FBaseCVar &var) = delete;
|
||||
FBaseCVar (const char *name, uint32_t flags);
|
||||
|
||||
void (*m_Callback)(FBaseCVar &);
|
||||
FBaseCVar *m_Next;
|
||||
|
||||
|
@ -332,6 +340,7 @@ public:
|
|||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const override;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) override;
|
||||
const char *GetHumanString(int precision) const override;
|
||||
const char *GetHumanStringDefault(int precision) const override;
|
||||
|
||||
float operator= (float floatval)
|
||||
{ UCVarValue val; val.Float = floatval; SetGenericRep (val, CVAR_Float); return floatval; }
|
||||
|
|
|
@ -302,7 +302,8 @@ void C_DoCommand (const char *cmd, int keynum)
|
|||
else
|
||||
{ // Get the variable's value
|
||||
if (var->GetDescription().Len()) Printf("%s\n", GStrings.localize(var->GetDescription()));
|
||||
Printf ("\"%s\" is \"%s\"\n", var->GetName(), var->GetHumanString());
|
||||
Printf ("\"%s\" is \"%s\" ", var->GetName(), var->GetHumanString());
|
||||
Printf ("(default: \"%s\")\n", var->GetHumanStringDefault());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1123,7 +1124,7 @@ int C_RegisterFunction(const char* pszName, const char* pszDesc, int (*func)(CCm
|
|||
{
|
||||
if (args.argc() > 0) args.operator[](0);
|
||||
CCmdFuncParm param = { args.argc() - 1, nname.GetChars(), (const char**)args._argv + 1, args.cmd };
|
||||
if (func(¶m) != CCMD_OK)
|
||||
if (func(¶m) != CCMD_OK && pszDesc)
|
||||
{
|
||||
Printf("%s\n", pszDesc);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ extern bool ParsingKeyConf, UnsafeExecutionContext;
|
|||
extern FString StoredWarp; // [RH] +warp at the command line
|
||||
|
||||
|
||||
extern bool CheckCheatmode (bool printmsg = true);
|
||||
extern bool CheckCheatmode (bool printmsg = true, bool sponly = false);
|
||||
|
||||
FExecList *C_ParseCmdLineParams(FExecList *exec);
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ enum EKeyCodes
|
|||
KEY_PGUP = 0xc9, // DIK_PRIOR
|
||||
KEY_PGDN = 0xd1, // DIK_NEXT
|
||||
|
||||
KEY_VOLUMEDOWN = 0xAE, // DIK_VOLUMEDOWN
|
||||
KEY_VOLUMEUP = 0xB0, // DIK_VOLUMEUP
|
||||
|
||||
KEY_FIRSTMOUSEBUTTON = 0x100,
|
||||
KEY_MOUSE1 = 0x100,
|
||||
KEY_MOUSE2 = 0x101,
|
||||
|
@ -72,6 +75,8 @@ enum EKeyCodes
|
|||
KEY_JOY6,
|
||||
KEY_JOY7,
|
||||
KEY_JOY8,
|
||||
KEY_JOY14 = KEY_FIRSTJOYBUTTON+13,
|
||||
KEY_JOY15 = KEY_FIRSTJOYBUTTON+14,
|
||||
KEY_LASTJOYBUTTON = 0x187,
|
||||
KEY_JOYPOV1_UP = 0x188,
|
||||
KEY_JOYPOV1_RIGHT = 0x189,
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "utf8.h"
|
||||
#include "m_joy.h"
|
||||
#include "vm.h"
|
||||
#include "gamestate.h"
|
||||
#include "i_interface.h"
|
||||
|
||||
bool G_Responder(event_t* ev);
|
||||
|
||||
|
@ -48,6 +50,11 @@ int eventhead;
|
|||
int eventtail;
|
||||
event_t events[MAXEVENTS];
|
||||
|
||||
CVAR(Float, m_sensitivity_x, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Float, m_sensitivity_y, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_ProcessEvents
|
||||
|
@ -69,6 +76,8 @@ void D_ProcessEvents (void)
|
|||
continue;
|
||||
if (ev->type == EV_DeviceChange)
|
||||
UpdateJoystickMenu(I_UpdateDeviceList());
|
||||
if (gamestate == GS_INTRO)
|
||||
continue;
|
||||
if (C_Responder (ev))
|
||||
continue; // console ate the event
|
||||
if (M_Responder (ev))
|
||||
|
@ -113,6 +122,57 @@ void D_RemoveNextCharEvent()
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// D_PostEvent
|
||||
//
|
||||
// Called by the I/O functions when input is detected.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void D_PostEvent(event_t* ev)
|
||||
{
|
||||
// Do not post duplicate consecutive EV_DeviceChange events.
|
||||
if (ev->type == EV_DeviceChange && events[eventhead].type == EV_DeviceChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (sysCallbacks.DispatchEvent && sysCallbacks.DispatchEvent(ev))
|
||||
return;
|
||||
|
||||
events[eventhead] = *ev;
|
||||
eventhead = (eventhead + 1) & (MAXEVENTS - 1);
|
||||
}
|
||||
|
||||
|
||||
void PostMouseMove(int xx, int yy)
|
||||
{
|
||||
static float lastx = 0, lasty = 0;
|
||||
event_t ev{};
|
||||
|
||||
float x = float(xx) * m_sensitivity_x;
|
||||
float y = -float(yy) * m_sensitivity_y;
|
||||
|
||||
if (m_filter)
|
||||
{
|
||||
ev.x = (x + lastx) / 2;
|
||||
ev.y = (y + lasty) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.x = x;
|
||||
ev.y = y;
|
||||
}
|
||||
lastx = x;
|
||||
lasty = y;
|
||||
if (ev.x || ev.y)
|
||||
{
|
||||
ev.type = EV_Mouse;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FInputEvent::FInputEvent(const event_t *ev)
|
||||
{
|
||||
Type = (EGenericEvent)ev->type;
|
||||
|
@ -132,8 +192,8 @@ FInputEvent::FInputEvent(const event_t *ev)
|
|||
KeyString = FString(char(ev->data1));
|
||||
break;
|
||||
case EV_Mouse:
|
||||
MouseX = ev->x;
|
||||
MouseY = ev->y;
|
||||
MouseX = int(ev->x);
|
||||
MouseY = int(ev->y);
|
||||
break;
|
||||
default:
|
||||
break; // EV_DeviceChange = wat?
|
||||
|
|
|
@ -22,16 +22,17 @@ struct event_t
|
|||
int16_t data1; // keys / mouse/joystick buttons
|
||||
int16_t data2;
|
||||
int16_t data3;
|
||||
int x; // mouse/joystick x move
|
||||
int y; // mouse/joystick y move
|
||||
float x; // mouse/joystick x move
|
||||
float y; // mouse/joystick y move
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent (const event_t* ev);
|
||||
void D_PostEvent (event_t* ev);
|
||||
void D_RemoveNextCharEvent();
|
||||
void D_ProcessEvents(void);
|
||||
void PostMouseMove(int x, int y);
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -6,4 +6,4 @@ void I_PutInClipboard (const char *str);
|
|||
FString I_GetFromClipboard (bool use_primary_selection);
|
||||
void I_SetMouseCapture();
|
||||
void I_ReleaseMouseCapture();
|
||||
|
||||
void I_GetEvent();
|
|
@ -1,8 +1,7 @@
|
|||
#include "i_interface.h"
|
||||
|
||||
// Some global engine variables taken out of the backend code.
|
||||
SystemCallbacks *sysCallbacks;
|
||||
double refreshfreq;
|
||||
SystemCallbacks sysCallbacks;
|
||||
FString endoomName;
|
||||
bool batchrun;
|
||||
float menuBlurAmount;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "zstring.h"
|
||||
#include "intrect.h"
|
||||
|
||||
struct event_t;
|
||||
|
||||
struct SystemCallbacks
|
||||
{
|
||||
bool (*WantGuiCapture)();
|
||||
|
@ -18,9 +20,11 @@ struct SystemCallbacks
|
|||
IntRect(*GetSceneRect)();
|
||||
FString(*GetLocationDescription)();
|
||||
void (*MenuDim)();
|
||||
FString(*GetPlayerName)(int i);
|
||||
bool (*DispatchEvent)(event_t* ev);
|
||||
};
|
||||
|
||||
extern SystemCallbacks *sysCallbacks;
|
||||
extern SystemCallbacks sysCallbacks;
|
||||
|
||||
struct WadStuff
|
||||
{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 1993-1996 id Software
|
||||
// Copyright 1999-2016 Randy Heit
|
||||
// $Id: i_net.c,v 1.2 1997/12/29 19:50:54 pekangas Exp $
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,7 +18,19 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Alternatively the following applies:
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Low-level networking code. Uses BSD sockets for UDP networking.
|
||||
|
@ -53,16 +67,15 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
#include "d_net.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_crc32.h"
|
||||
#include "d_player.h"
|
||||
#include "st_start.h"
|
||||
#include "m_misc.h"
|
||||
#include "engineerrors.h"
|
||||
#include "cmdlib.h"
|
||||
#include "printf.h"
|
||||
#include "i_interface.h"
|
||||
#include "templates.h"
|
||||
|
||||
#include "i_net.h"
|
||||
|
||||
|
@ -91,6 +104,10 @@ typedef int SOCKET;
|
|||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
bool netgame, multiplayer;
|
||||
int consoleplayer; // i.e. myconnectindex in Build.
|
||||
doomcom_t doomcom;
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
//
|
||||
|
@ -143,6 +160,12 @@ struct PreGamePacket
|
|||
|
||||
uint8_t TransmitBuffer[TRANSMIT_SIZE];
|
||||
|
||||
FString GetPlayerName(int num)
|
||||
{
|
||||
if (sysCallbacks.GetPlayerName) return sysCallbacks.GetPlayerName(sendplayer[num]);
|
||||
else return FStringf("Player %d", sendplayer[num] + 1);
|
||||
}
|
||||
|
||||
//
|
||||
// UDPsocket
|
||||
//
|
||||
|
@ -272,12 +295,12 @@ void PacketGet (void)
|
|||
if (StartScreen != NULL)
|
||||
{
|
||||
StartScreen->NetMessage ("The connection from %s was dropped.\n",
|
||||
players[sendplayer[node]].userinfo.GetName());
|
||||
GetPlayerName(node).GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("The connection from %s was dropped.\n",
|
||||
players[sendplayer[node]].userinfo.GetName());
|
||||
GetPlayerName(node).GetChars());
|
||||
}
|
||||
|
||||
doomcom.data[0] = 0x80; // NCMD_EXIT
|
||||
|
@ -945,7 +968,7 @@ int I_InitNetwork (void)
|
|||
v = Args->CheckValue ("-dup");
|
||||
if (v)
|
||||
{
|
||||
doomcom.ticdup = clamp (atoi (v), 1, MAXTICDUP);
|
||||
doomcom.ticdup = clamp<int> (atoi (v), 1, MAXTICDUP);
|
||||
}
|
||||
else
|
||||
{
|
85
src/common/engine/i_net.h
Normal file
85
src/common/engine/i_net.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#ifndef __I_NET_H__
|
||||
#define __I_NET_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Called by D_DoomMain.
|
||||
int I_InitNetwork (void);
|
||||
void I_NetCmd (void);
|
||||
|
||||
enum ENetConstants
|
||||
{
|
||||
MAXNETNODES = 8, // max computers in a game
|
||||
DOOMCOM_ID = 0x12345678,
|
||||
BACKUPTICS = 36, // number of tics to remember
|
||||
MAXTICDUP = 5,
|
||||
LOCALCMDTICS =(BACKUPTICS*MAXTICDUP),
|
||||
MAX_MSGLEN = 14000,
|
||||
|
||||
CMD_SEND = 1,
|
||||
CMD_GET = 2,
|
||||
};
|
||||
|
||||
// [RH]
|
||||
// New generic packet structure:
|
||||
//
|
||||
// Header:
|
||||
// One byte with following flags.
|
||||
// One byte with starttic
|
||||
// One byte with master's maketic (master -> slave only!)
|
||||
// If NCMD_RETRANSMIT set, one byte with retransmitfrom
|
||||
// If NCMD_XTICS set, one byte with number of tics (minus 3, so theoretically up to 258 tics in one packet)
|
||||
// If NCMD_QUITTERS, one byte with number of players followed by one byte with each player's consolenum
|
||||
// If NCMD_MULTI, one byte with number of players followed by one byte with each player's consolenum
|
||||
// - The first player's consolenum is not included in this list, because it always matches the sender
|
||||
//
|
||||
// For each tic:
|
||||
// Two bytes with consistancy check, followed by tic data
|
||||
//
|
||||
// Setup packets are different, and are described just before D_ArbitrateNetStart().
|
||||
|
||||
enum ENCMD
|
||||
{
|
||||
NCMD_EXIT = 0x80,
|
||||
NCMD_RETRANSMIT = 0x40,
|
||||
NCMD_SETUP = 0x20,
|
||||
NCMD_MULTI = 0x10, // multiple players in this packet
|
||||
NCMD_QUITTERS = 0x08, // one or more players just quit (packet server only)
|
||||
NCMD_COMPRESSED = 0x04, // remainder of packet is compressed
|
||||
|
||||
NCMD_XTICS = 0x03, // packet contains >2 tics
|
||||
NCMD_2TICS = 0x02, // packet contains 2 tics
|
||||
NCMD_1TICS = 0x01, // packet contains 1 tic
|
||||
NCMD_0TICS = 0x00, // packet contains 0 tics
|
||||
};
|
||||
|
||||
//
|
||||
// Network packet data.
|
||||
//
|
||||
struct doomcom_t
|
||||
{
|
||||
uint32_t id; // should be DOOMCOM_ID
|
||||
int16_t intnum; // DOOM executes an int to execute commands
|
||||
|
||||
// communication between DOOM and the driver
|
||||
int16_t command; // CMD_SEND or CMD_GET
|
||||
int16_t remotenode; // dest for send, set by get (-1 = no packet).
|
||||
int16_t datalength; // bytes in data to be sent
|
||||
|
||||
// info common to all nodes
|
||||
int16_t numnodes; // console is always node 0.
|
||||
int16_t ticdup; // 1 = no duplication, 2-5 = dup for slow nets
|
||||
|
||||
// info specific to this node
|
||||
int16_t consoleplayer;
|
||||
int16_t numplayers;
|
||||
|
||||
// packet data to be sent
|
||||
uint8_t data[MAX_MSGLEN];
|
||||
|
||||
};
|
||||
|
||||
extern doomcom_t doomcom;
|
||||
extern bool netgame, multiplayer;
|
||||
|
||||
#endif
|
|
@ -660,7 +660,10 @@ xx(Static)
|
|||
xx(Staticconst)
|
||||
xx(DeathmatchStatusScreen)
|
||||
xx(CoopStatusScreen)
|
||||
xx(DoomStatusScreen)
|
||||
xx(RavenStatusScreen)
|
||||
xx(DoomStatusScreenSized)
|
||||
xx(RavenStatusScreenSized)
|
||||
xx(StatusbarWidget)
|
||||
xx(StatusbarHead)
|
||||
xx(StatusbarCondition)
|
||||
|
@ -1039,6 +1042,9 @@ xx(AttackZOffset)
|
|||
xx(SpawnMask)
|
||||
xx(ScoreIcon)
|
||||
xx(ViewHeight)
|
||||
xx(ViewAngle)
|
||||
xx(ViewPitch)
|
||||
xx(ViewRoll)
|
||||
xx(FallingScreamMinSpeed)
|
||||
xx(FallingScreamMaxSpeed)
|
||||
xx(GruntSpeed)
|
||||
|
@ -1071,4 +1077,12 @@ xx(PlayerColors)
|
|||
xx(PlayerSkin)
|
||||
xx(NewPlayerMenu)
|
||||
xx(AltHud)
|
||||
xx(GameScreen)
|
||||
|
||||
// summary
|
||||
xx(cwidth)
|
||||
xx(cheight)
|
||||
xx(wrapwidth)
|
||||
xx(scalefactorx)
|
||||
xx(scalefactory)
|
||||
xx(scalemode)
|
||||
|
|
|
@ -36,6 +36,7 @@ struct FRemapTable
|
|||
bool Inactive = false; // This table is inactive and should be treated as if it was passed as NULL
|
||||
bool TwodOnly = false; // Only used for 2D rendering
|
||||
bool ForFont = false; // Mark font translations because they may require different handling than the ones for sprites-
|
||||
bool NoTransparency = false; // This palette has no transparent index and must be excluded from all treatment for that.
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -58,19 +59,22 @@ private:
|
|||
};
|
||||
|
||||
|
||||
#define TRANSLATION_SHIFT 16
|
||||
#define TRANSLATION_MASK ((1<<TRANSLATION_SHIFT)-1)
|
||||
#define TRANSLATIONTYPE_MASK (255<<TRANSLATION_SHIFT)
|
||||
enum
|
||||
{
|
||||
TRANSLATION_SHIFT = 16,
|
||||
TRANSLATION_MASK = ((1 << TRANSLATION_SHIFT) - 1),
|
||||
TRANSLATIONTYPE_MASK = (255 << TRANSLATION_SHIFT)
|
||||
};
|
||||
|
||||
inline uint32_t TRANSLATION(uint8_t a, uint32_t b)
|
||||
inline constexpr uint32_t TRANSLATION(uint8_t a, uint32_t b)
|
||||
{
|
||||
return (a << TRANSLATION_SHIFT) | b;
|
||||
}
|
||||
inline int GetTranslationType(uint32_t trans)
|
||||
inline constexpr int GetTranslationType(uint32_t trans)
|
||||
{
|
||||
return (trans & TRANSLATIONTYPE_MASK) >> TRANSLATION_SHIFT;
|
||||
}
|
||||
inline int GetTranslationIndex(uint32_t trans)
|
||||
inline constexpr int GetTranslationIndex(uint32_t trans)
|
||||
{
|
||||
return (trans & TRANSLATION_MASK);
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ enum
|
|||
PRINT_TYPES = 1023, // Bitmask.
|
||||
PRINT_NONOTIFY = 1024, // Flag - do not add to notify buffer
|
||||
PRINT_NOLOG = 2048, // Flag - do not print to log file
|
||||
PRINT_NOTIFY = 4096, // Flag - add to notify buffer
|
||||
PRINT_NOTIFY = 4096, // Flag - add to game-native notify display - messages without this only go to the generic notification buffer.
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "templates.h"
|
||||
#include "zstring.h"
|
||||
#include "name.h"
|
||||
#include <inttypes.h>
|
||||
#include "filesystem.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
@ -300,6 +301,12 @@ void FScanner :: OpenLumpNum (int lump)
|
|||
|
||||
void FScanner::PrepareScript ()
|
||||
{
|
||||
// If the file got a UTF-8 byte order mark, remove that.
|
||||
if (ScriptBuffer.Len() > 3 && ScriptBuffer[0] == (char)0xEF && ScriptBuffer[1] == (char)0xBB && ScriptBuffer[2] == (char)0xBF)
|
||||
{
|
||||
ScriptBuffer = ScriptBuffer.Mid(3);
|
||||
}
|
||||
|
||||
// The scanner requires the file to end with a '\n', so add one if
|
||||
// it doesn't already.
|
||||
if (ScriptBuffer.Len() == 0 || ScriptBuffer.Back() != '\n')
|
||||
|
@ -400,6 +407,13 @@ void FScanner::RestorePos (const FScanner::SavedPos &pos)
|
|||
Crossed = false;
|
||||
}
|
||||
|
||||
long long FScanner::mystrtoll(const char* p, char** endp, int base)
|
||||
{
|
||||
// Do not treat a leading 0 as an octal identifier if so desired.
|
||||
if (NoOctals && *p == '0' && p[1] != 'x' && p[1] != 'X' && base == 0) base = 10;
|
||||
return strtoll(p, endp, base);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FScanner :: isText
|
||||
|
@ -491,6 +505,7 @@ bool FScanner::ScanString (bool tokens)
|
|||
const char *marker, *tok;
|
||||
bool return_val;
|
||||
|
||||
ParseError = false;
|
||||
CheckOpen();
|
||||
if (AlreadyGot)
|
||||
{
|
||||
|
@ -590,7 +605,7 @@ bool FScanner::CheckString (const char *name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetToken ()
|
||||
bool FScanner::GetToken (bool evaluate)
|
||||
{
|
||||
if (ScanString (true))
|
||||
{
|
||||
|
@ -608,7 +623,7 @@ bool FScanner::GetToken ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll(String, &stopper, 0);
|
||||
BigNumber = mystrtoll(String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
Float = Number;
|
||||
}
|
||||
|
@ -620,7 +635,19 @@ bool FScanner::GetToken ()
|
|||
}
|
||||
else if (TokenType == TK_StringConst)
|
||||
{
|
||||
StringLen = strbin(String);
|
||||
StringLen = strbin(const_cast<char*>(String));
|
||||
}
|
||||
else if (TokenType == TK_Identifier && evaluate && symbols.CountUsed() > 0)
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym)
|
||||
{
|
||||
TokenType = sym->tokenType;
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -633,9 +660,9 @@ bool FScanner::GetToken ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetAnyToken (void)
|
||||
void FScanner::MustGetAnyToken (bool evaluate)
|
||||
{
|
||||
if (GetToken () == false)
|
||||
if (GetToken (evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing token (unexpected end of file).");
|
||||
}
|
||||
|
@ -663,9 +690,9 @@ void FScanner::TokenMustBe (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetToken (int token)
|
||||
void FScanner::MustGetToken (int token, bool evaluate)
|
||||
{
|
||||
MustGetAnyToken ();
|
||||
MustGetAnyToken (evaluate);
|
||||
TokenMustBe(token);
|
||||
}
|
||||
|
||||
|
@ -678,9 +705,9 @@ void FScanner::MustGetToken (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckToken (int token)
|
||||
bool FScanner::CheckToken (int token, bool evaluate)
|
||||
{
|
||||
if (GetToken ())
|
||||
if (GetToken (evaluate))
|
||||
{
|
||||
if (TokenType == token)
|
||||
{
|
||||
|
@ -697,7 +724,7 @@ bool FScanner::CheckToken (int token)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetNumber ()
|
||||
bool FScanner::GetNumber (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -710,11 +737,25 @@ bool FScanner::GetNumber ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll(String, &stopper, 0);
|
||||
BigNumber = mystrtoll(String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Float = Number;
|
||||
|
@ -732,9 +773,9 @@ bool FScanner::GetNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetNumber ()
|
||||
void FScanner::MustGetNumber (bool evaluate)
|
||||
{
|
||||
if (GetNumber() == false)
|
||||
if (GetNumber(evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing integer (unexpected end of file).");
|
||||
}
|
||||
|
@ -749,7 +790,7 @@ void FScanner::MustGetNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckNumber ()
|
||||
bool FScanner::CheckNumber (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -767,10 +808,23 @@ bool FScanner::CheckNumber ()
|
|||
}
|
||||
else
|
||||
{
|
||||
BigNumber = strtoll (String, &stopper, 0);
|
||||
BigNumber = mystrtoll (String, &stopper, 0);
|
||||
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
UnGet();
|
||||
return false;
|
||||
}
|
||||
|
@ -792,7 +846,7 @@ bool FScanner::CheckNumber ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::CheckFloat ()
|
||||
bool FScanner::CheckFloat (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -807,6 +861,20 @@ bool FScanner::CheckFloat ()
|
|||
Float = strtod (String, &stopper);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UnGet();
|
||||
return false;
|
||||
}
|
||||
|
@ -825,7 +893,7 @@ bool FScanner::CheckFloat ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::GetFloat ()
|
||||
bool FScanner::GetFloat (bool evaluate)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
|
@ -835,7 +903,21 @@ bool FScanner::GetFloat ()
|
|||
Float = strtod (String, &stopper);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
if (evaluate && symbols.CountUsed())
|
||||
{
|
||||
auto sym = symbols.CheckKey(String);
|
||||
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
|
||||
{
|
||||
BigNumber = sym->Number;
|
||||
Number = (int)sym->Number;
|
||||
Float = sym->Float;
|
||||
// String will retain the actual symbol name.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptError ("SC_GetFloat: Bad numeric constant \"%s\".", String);
|
||||
return false;
|
||||
}
|
||||
Number = (int)Float;
|
||||
return true;
|
||||
|
@ -852,9 +934,9 @@ bool FScanner::GetFloat ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::MustGetFloat ()
|
||||
void FScanner::MustGetFloat (bool evaluate)
|
||||
{
|
||||
if (GetFloat() == false)
|
||||
if (GetFloat(evaluate) == false)
|
||||
{
|
||||
ScriptError ("Missing floating-point number (unexpected end of file).");
|
||||
}
|
||||
|
@ -938,44 +1020,54 @@ bool FScanner::Compare (const char *text)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::ScanValue(bool allowfloat)
|
||||
bool FScanner::ScanValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
bool neg = false;
|
||||
if (!GetToken())
|
||||
if (!GetToken(evaluate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (TokenType == '-' || TokenType == '+')
|
||||
{
|
||||
neg = TokenType == '-';
|
||||
if (!GetToken())
|
||||
if (!GetToken(evaluate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (TokenType != TK_IntConst && (TokenType != TK_FloatConst || !allowfloat))
|
||||
{
|
||||
|
||||
if (TokenType == TK_FloatConst && !allowfloat)
|
||||
return false;
|
||||
|
||||
if (TokenType != TK_IntConst && TokenType != TK_FloatConst)
|
||||
{
|
||||
auto d = constants.CheckKey(String);
|
||||
if (!d) return false;
|
||||
if (!allowfloat && int64_t(*d) != *d) return false;
|
||||
BigNumber = *d;
|
||||
Number = *d;
|
||||
Float = *d;
|
||||
}
|
||||
if (neg)
|
||||
{
|
||||
BigNumber = -BigNumber;
|
||||
Number = -Number;
|
||||
Float = -Float;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FScanner::CheckValue(bool allowfloat)
|
||||
bool FScanner::CheckValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
auto savedstate = SavePos();
|
||||
bool res = ScanValue(allowfloat);
|
||||
bool res = ScanValue(allowfloat, evaluate);
|
||||
if (!res) RestorePos(savedstate);
|
||||
return res;
|
||||
}
|
||||
|
||||
void FScanner::MustGetValue(bool allowfloat)
|
||||
void FScanner::MustGetValue(bool allowfloat, bool evaluate)
|
||||
{
|
||||
if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
|
||||
if (!ScanValue(allowfloat, evaluate)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
|
||||
}
|
||||
|
||||
bool FScanner::CheckBoolToken()
|
||||
|
@ -1079,6 +1171,12 @@ void FScanner::ScriptError (const char *message, ...)
|
|||
va_end (arglist);
|
||||
}
|
||||
|
||||
if (NoFatalErrors)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
|
||||
AlreadyGot ? AlreadyGotLine : Line, composed.GetChars());
|
||||
return;
|
||||
}
|
||||
I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
|
||||
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
|
||||
}
|
||||
|
@ -1123,6 +1221,72 @@ void FScanner::CheckOpen()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char *name, int64_t value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_IntConst;
|
||||
sym.Number = value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char* name, uint64_t value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_UIntConst;
|
||||
sym.Number = value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::SkipToEndOfBlock()
|
||||
{
|
||||
int depth = 0;
|
||||
while (1)
|
||||
{
|
||||
MustGetString(); // this will abort if it reaches the end of the file
|
||||
if (Compare("{")) depth++;
|
||||
else if (Compare("}"))
|
||||
{
|
||||
depth--;
|
||||
if (depth < 0) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner::AddSymbol(const char* name, double value)
|
||||
{
|
||||
Symbol sym;
|
||||
sym.tokenType = TK_FloatConst;
|
||||
sym.Number = (int64_t)value;
|
||||
sym.Float = value;
|
||||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// a class that remembers a parser position
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __SC_MAN_H__
|
||||
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
#include "name.h"
|
||||
#include "basics.h"
|
||||
|
||||
|
@ -46,6 +47,16 @@ public:
|
|||
int SavedScriptLine;
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
int tokenType;
|
||||
int64_t Number;
|
||||
double Float;
|
||||
};
|
||||
|
||||
|
||||
TMap<FName, Symbol> symbols;
|
||||
|
||||
// Methods ------------------------------------------------------
|
||||
FScanner();
|
||||
FScanner(const FScanner &other);
|
||||
|
@ -70,11 +81,19 @@ public:
|
|||
}
|
||||
|
||||
void SetCMode(bool cmode);
|
||||
void SetNoOctals(bool cmode) { NoOctals = cmode; }
|
||||
void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; }
|
||||
void SetEscape(bool esc);
|
||||
void SetStateMode(bool stately);
|
||||
void DisableStateOptions();
|
||||
const SavedPos SavePos();
|
||||
void RestorePos(const SavedPos &pos);
|
||||
void AddSymbol(const char* name, int64_t value);
|
||||
void AddSymbol(const char* name, uint64_t value);
|
||||
inline void AddSymbol(const char* name, int32_t value) { return AddSymbol(name, int64_t(value)); }
|
||||
inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); }
|
||||
void AddSymbol(const char* name, double value);
|
||||
void SkipToEndOfBlock();
|
||||
|
||||
static FString TokenName(int token, const char *string=NULL);
|
||||
|
||||
|
@ -83,30 +102,40 @@ public:
|
|||
void MustGetStringName(const char *name);
|
||||
bool CheckString(const char *name);
|
||||
|
||||
bool GetToken();
|
||||
void MustGetAnyToken();
|
||||
bool GetToken(bool evaluate = false);
|
||||
void MustGetAnyToken(bool evaluate = false);
|
||||
void TokenMustBe(int token);
|
||||
void MustGetToken(int token);
|
||||
bool CheckToken(int token);
|
||||
void MustGetToken(int token, bool evaluate = false);
|
||||
bool CheckToken(int token, bool evaluate = false);
|
||||
bool CheckTokenId(ENamedName id);
|
||||
|
||||
bool GetNumber();
|
||||
void MustGetNumber();
|
||||
bool CheckNumber();
|
||||
bool GetNumber(bool evaluate = false);
|
||||
void MustGetNumber(bool evaluate = false);
|
||||
bool CheckNumber(bool evaluate = false);
|
||||
|
||||
bool GetFloat();
|
||||
void MustGetFloat();
|
||||
bool CheckFloat();
|
||||
bool GetFloat(bool evaluate = false);
|
||||
void MustGetFloat(bool evaluate = false);
|
||||
bool CheckFloat(bool evaluate = false);
|
||||
|
||||
double *LookupConstant(FName name)
|
||||
{
|
||||
return constants.CheckKey(name);
|
||||
}
|
||||
|
||||
// Token based variant
|
||||
bool CheckValue(bool allowfloat);
|
||||
void MustGetValue(bool allowfloat);
|
||||
bool CheckValue(bool allowfloat, bool evaluate = true);
|
||||
void MustGetValue(bool allowfloat, bool evaluate = true);
|
||||
bool CheckBoolToken();
|
||||
void MustGetBoolToken();
|
||||
|
||||
void UnGet();
|
||||
|
||||
bool Compare(const char *text);
|
||||
inline bool Compare(const std::initializer_list<const char*>& list)
|
||||
{
|
||||
for (auto c : list) if (Compare(c)) return true;
|
||||
return false;
|
||||
}
|
||||
int MatchString(const char * const *strings, size_t stride = sizeof(char*));
|
||||
int MustMatchString(const char * const *strings, size_t stride = sizeof(char*));
|
||||
int GetMessageLine();
|
||||
|
@ -125,11 +154,13 @@ public:
|
|||
double Float;
|
||||
int Line;
|
||||
bool End;
|
||||
bool ParseError = false;
|
||||
bool Crossed;
|
||||
int LumpNum;
|
||||
FString ScriptName;
|
||||
|
||||
protected:
|
||||
long long mystrtoll(const char* p, char** endp, int base);
|
||||
void PrepareScript();
|
||||
void CheckOpen();
|
||||
bool ScanString(bool tokens);
|
||||
|
@ -137,6 +168,8 @@ protected:
|
|||
// Strings longer than this minus one will be dynamically allocated.
|
||||
static const int MAX_STRING_SIZE = 128;
|
||||
|
||||
TMap<FName, double> constants;
|
||||
|
||||
bool ScriptOpen;
|
||||
FString ScriptBuffer;
|
||||
const char *ScriptPtr;
|
||||
|
@ -149,13 +182,15 @@ protected:
|
|||
const char *LastGotPtr;
|
||||
int LastGotLine;
|
||||
bool CMode;
|
||||
bool NoOctals = false;
|
||||
bool NoFatalErrors = false;
|
||||
uint8_t StateMode;
|
||||
bool StateOptions;
|
||||
bool Escape;
|
||||
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
|
||||
|
||||
|
||||
bool ScanValue(bool allowfloat);
|
||||
bool ScanValue(bool allowfloat, bool evaluate);
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "engineerrors.h"
|
||||
#include "textures.h"
|
||||
#include "texturemanager.h"
|
||||
#include "base64.h"
|
||||
|
||||
extern DObject *WP_NOCHANGE;
|
||||
bool save_full = false; // for testing. Should be removed afterward.
|
||||
|
@ -675,6 +676,7 @@ void FSerializer::ReadObjects(bool hubtravel)
|
|||
{
|
||||
Printf(TEXTCOLOR_RED "Failed to restore all objects in savegame\n");
|
||||
mErrors++;
|
||||
mObjectErrors++;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
|
@ -771,6 +773,31 @@ error:
|
|||
return buff;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSerializer &FSerializer::SerializeMemory(const char *key, void* mem, size_t length)
|
||||
{
|
||||
if (isWriting())
|
||||
{
|
||||
auto array = base64_encode((const uint8_t*)mem, length);
|
||||
AddString(key, (const char*)array.Data());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cp = GetString(key);
|
||||
if (key)
|
||||
{
|
||||
base64_decode(mem, length, cp);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -95,6 +95,7 @@ public:
|
|||
virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def);
|
||||
// This is only needed by the type system.
|
||||
virtual FSerializer& StatePointer(const char* key, void* ptraddr, bool *res);
|
||||
FSerializer& SerializeMemory(const char* key, void* mem, size_t length);
|
||||
|
||||
FSerializer &StringPtr(const char *key, const char *&charptr); // This only retrieves the address but creates no permanent copy of the string unlike the regular char* serializer.
|
||||
FSerializer &AddString(const char *key, const char *charptr);
|
||||
|
@ -181,6 +182,7 @@ public:
|
|||
}
|
||||
|
||||
int mErrors = 0;
|
||||
int mObjectErrors = 0;
|
||||
};
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, char& value, char* defval);
|
||||
|
@ -218,7 +220,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value,
|
|||
{
|
||||
if (arc.isWriting())
|
||||
{
|
||||
if (value.Size() == 0) return arc; // do not save empty arrays
|
||||
if (value.Size() == 0 && key) return arc; // do not save empty arrays
|
||||
}
|
||||
bool res = arc.BeginArray(key);
|
||||
if (arc.isReading())
|
||||
|
@ -238,6 +240,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value,
|
|||
return arc;
|
||||
}
|
||||
|
||||
template<int size>
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray<size>& value, FixedBitArray<size>* def)
|
||||
{
|
||||
return arc.SerializeMemory(key, value.Storage(), value.StorageSize());
|
||||
}
|
||||
|
||||
template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def);
|
||||
template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def);
|
||||
template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def);
|
||||
|
@ -257,7 +265,8 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, DVector2 &p, DV
|
|||
return arc.Array<double>(key, &p[0], def? &(*def)[0] : nullptr, 2, true);
|
||||
}
|
||||
|
||||
inline FSerializer &Serialize(FSerializer &arc, const char *key, DAngle &p, DAngle *def)
|
||||
template<class T>
|
||||
inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle<T> &p, TAngle<T> *def)
|
||||
{
|
||||
return Serialize(arc, key, p.Degrees, def? &def->Degrees : nullptr);
|
||||
}
|
||||
|
|
|
@ -226,15 +226,44 @@ struct FReader
|
|||
//==========================================================================
|
||||
|
||||
template<class T>
|
||||
FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T **defval, T *base)
|
||||
FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T **defval, T *base, const int64_t count)
|
||||
{
|
||||
assert(base != nullptr);
|
||||
assert(count > 0);
|
||||
if (arc.isReading() || !arc.w->inObject() || defval == nullptr || value != *defval)
|
||||
{
|
||||
int64_t vv = value == nullptr ? -1 : value - base;
|
||||
int64_t vv = -1;
|
||||
if (value != nullptr)
|
||||
{
|
||||
vv = value - base;
|
||||
if (vv < 0 || vv >= count)
|
||||
{
|
||||
Printf("Trying to serialize out-of-bounds array value with key '%s', index = %lli, size = %lli\n", key, vv, count);
|
||||
vv = -1;
|
||||
}
|
||||
}
|
||||
Serialize(arc, key, vv, nullptr);
|
||||
value = vv < 0 ? nullptr : base + vv;
|
||||
if (vv == -1)
|
||||
value = nullptr;
|
||||
else if (vv < 0 || vv >= count)
|
||||
{
|
||||
Printf("Trying to serialize out-of-bounds array value with key '%s', index = %lli, size = %lli\n", key, vv, count);
|
||||
value = nullptr;
|
||||
}
|
||||
else
|
||||
value = base + vv;
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T **defval, TArray<T> &array)
|
||||
{
|
||||
if (array.Size() == 0)
|
||||
{
|
||||
Printf("Trying to serialize a value with key '%s' from empty array\n", key);
|
||||
return arc;
|
||||
}
|
||||
return SerializePointer(arc, key, value, defval, array.Data(), array.Size());
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,9 @@ inline uint64_t rdtsc()
|
|||
}
|
||||
while (upper != temp);
|
||||
return (static_cast<unsigned long long>(upper) << 32) | lower;
|
||||
#elif defined __aarch64__
|
||||
// TODO: Implement and test on ARM64
|
||||
return 0;
|
||||
#else // i386
|
||||
if (CPU.bRDTSC)
|
||||
{
|
||||
|
|
|
@ -450,7 +450,7 @@ void FStringTable::InsertString(int lumpnum, int langid, FName label, const FStr
|
|||
auto replace = allMacros.CheckKey(lookupname);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
const char *replacement = replace && replace->Replacements[i] ? replace->Replacements[i].GetChars() : "";
|
||||
const char *replacement = replace? replace->Replacements[i].GetChars() : "";
|
||||
te.strings[i].Substitute(replacee, replacement);
|
||||
}
|
||||
}
|
||||
|
@ -575,7 +575,10 @@ const char *FStringTable::GetString(const char *name, uint32_t *langtable, int g
|
|||
if (item)
|
||||
{
|
||||
if (langtable) *langtable = map.first;
|
||||
return item->strings[gender].GetChars();
|
||||
auto c = item->strings[gender].GetChars();
|
||||
if (c && *c == '$' && c[1] == '$')
|
||||
return GetString(c + 2, langtable, gender);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,8 @@ public:
|
|||
bool exists(const char *name);
|
||||
void SetCallbacks(StringtableCallbacks* cb) { callbacks = cb; }
|
||||
|
||||
void InsertString(int lumpnum, int langid, FName label, const FString& string);
|
||||
|
||||
private:
|
||||
|
||||
FString activeLanguage;
|
||||
|
@ -124,7 +126,6 @@ private:
|
|||
|
||||
bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray<uint8_t> &buffer);
|
||||
bool readMacros(int lumpnum);
|
||||
void InsertString(int lumpnum, int langid, FName label, const FString &string);
|
||||
void DeleteString(int langid, FName label);
|
||||
void DeleteForLabel(int lumpnum, FName label);
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpF
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, k7zSignature, k7zSignatureSize))
|
||||
{
|
||||
FResourceFile *rf = new F7ZFile(filename, file);
|
||||
auto rf = new F7ZFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
|
@ -254,9 +254,9 @@ int FDirectoryLump::FillCache()
|
|||
|
||||
FResourceFile *CheckDir(const char *filename, bool quiet, bool nosubdirflag, LumpFilterInfo* filter)
|
||||
{
|
||||
FResourceFile *rf = new FDirectory(filename, nosubdirflag);
|
||||
auto rf = new FDirectory(filename, nosubdirflag);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
delete rf;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, Lump
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "KenSilverman", 12))
|
||||
{
|
||||
FResourceFile *rf = new FGrpFile(filename, file);
|
||||
auto rf = new FGrpFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
|
@ -94,7 +94,7 @@ bool FLumpFile::Open(bool quiet, LumpFilterInfo*)
|
|||
FResourceFile *CheckLump(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
|
||||
{
|
||||
// always succeeds
|
||||
FResourceFile *rf = new FLumpFile(filename, file);
|
||||
auto rf = new FLumpFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
|
|
|
@ -134,7 +134,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, Lump
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "PACK", 4))
|
||||
{
|
||||
FResourceFile *rf = new FPakFile(filename, file);
|
||||
auto rf = new FPakFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
|
@ -248,7 +248,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, Lump
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "RFF\x1a", 4))
|
||||
{
|
||||
FResourceFile *rf = new FRFFFile(filename, file);
|
||||
auto rf = new FRFFFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
155
src/common/filesystem/file_ssi.cpp
Normal file
155
src/common/filesystem/file_ssi.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
** file_grp.cpp
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2009 Randy Heit
|
||||
** Copyright 2005-2020 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "resourcefile.h"
|
||||
#include "printf.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Build GRP file
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FSSIFile : public FUncompressedFile
|
||||
{
|
||||
public:
|
||||
FSSIFile(const char * filename, FileReader &file);
|
||||
bool Open(bool quiet, int version, int lumpcount, LumpFilterInfo* filter);
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Initializes a Build GRP file
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSSIFile::FSSIFile(const char *filename, FileReader &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Open it
|
||||
// Note that SSIs can contain embedded GRPs which must be flagged accordingly.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*)
|
||||
{
|
||||
NumLumps = lumpcount*2;
|
||||
Lumps.Resize(lumpcount*2);
|
||||
|
||||
|
||||
int32_t j = (version == 2 ? 267 : 254) + (lumpcount * 121);
|
||||
for (uint32_t i = 0; i < NumLumps; i+=2)
|
||||
{
|
||||
char fn[13];
|
||||
int strlength = Reader.ReadUInt8();
|
||||
if (strlength > 12) strlength = 12;
|
||||
|
||||
Reader.Read(fn, 12);
|
||||
fn[strlength] = 0;
|
||||
int flength = Reader.ReadInt32();
|
||||
|
||||
|
||||
Lumps[i].LumpNameSetup(fn);
|
||||
Lumps[i].Position = j;
|
||||
Lumps[i].LumpSize = flength;
|
||||
Lumps[i].Owner = this;
|
||||
if (strstr(fn, ".GRP")) Lumps[i].Flags |= LUMPF_EMBEDDED;
|
||||
|
||||
// SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container,
|
||||
// so we have no choice but to create another file record for the altered name.
|
||||
std::swap(fn[strlength - 1], fn[strlength - 3]);
|
||||
Lumps[i+1].LumpNameSetup(fn);
|
||||
Lumps[i+1].Position = j;
|
||||
Lumps[i+1].LumpSize = flength;
|
||||
Lumps[i+1].Owner = this;
|
||||
if (strstr(fn, ".GRP")) Lumps[i+1].Flags |= LUMPF_EMBEDDED;
|
||||
|
||||
j += flength;
|
||||
|
||||
Reader.Seek(104, FileReader::SeekCur);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// File open
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter)
|
||||
{
|
||||
char zerobuf[72];
|
||||
char buf[72];
|
||||
memset(zerobuf, 0, 72);
|
||||
|
||||
auto skipstring = [&](size_t length)
|
||||
{
|
||||
size_t strlength = file.ReadUInt8();
|
||||
if (strlength > length) return false;
|
||||
size_t count = file.Read(buf, length);
|
||||
buf[length] = 0;
|
||||
if (count != length || strlen(buf) != strlength) return false;
|
||||
if (length != strlength && memcmp(buf + strlength, zerobuf, length - strlength)) return false;
|
||||
return true;
|
||||
};
|
||||
if (file.GetLength() >= 12)
|
||||
{
|
||||
// check if SSI
|
||||
// this performs several checks because there is no "SSI" magic
|
||||
int version = file.ReadInt32();
|
||||
if (version == 1 || version == 2) // if
|
||||
{
|
||||
int numfiles = file.ReadInt32();
|
||||
if (!skipstring(32)) return nullptr;
|
||||
if (version == 2 && !skipstring(12)) return nullptr;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (!skipstring(70)) return nullptr;
|
||||
}
|
||||
auto ssi = new FSSIFile(filename, file);
|
||||
if (ssi->Open(filename, version, numfiles, filter)) return ssi;
|
||||
file = std::move(ssi->Reader); // to avoid destruction of reader
|
||||
delete ssi;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -70,8 +70,8 @@ public:
|
|||
|
||||
int GetNamespace() const override { return Namespace; }
|
||||
|
||||
int GetFileOffset() { return Position; }
|
||||
FileReader *GetReader()
|
||||
int GetFileOffset() override { return Position; }
|
||||
FileReader *GetReader() override
|
||||
{
|
||||
if(!Compressed)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
int FillCache()
|
||||
int FillCache() override
|
||||
{
|
||||
if(!Compressed)
|
||||
{
|
||||
|
@ -472,7 +472,7 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, Lump
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
|
||||
{
|
||||
FResourceFile *rf = new FWadFile(filename, file);
|
||||
auto rf = new FWadFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
|
@ -148,7 +148,7 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, Lu
|
|||
if (offset != checkpos || length <= 0) return nullptr;
|
||||
checkpos += (length+4095) / 4096;
|
||||
}
|
||||
FResourceFile *rf = new FWHResFile(filename, file);
|
||||
auto rf = new FWHResFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
|
|
|
@ -464,7 +464,7 @@ FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, Lump
|
|||
file.Seek(0, FileReader::SeekSet);
|
||||
if (!memcmp(head, "PK\x3\x4", 4))
|
||||
{
|
||||
FResourceFile *rf = new FZipFile(filename, file);
|
||||
auto rf = new FZipFile(filename, file);
|
||||
if (rf->Open(quiet, filter)) return rf;
|
||||
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
|
|
|
@ -1634,79 +1634,8 @@ static void PrintLastError ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceLump *FileSystem::Lookup(const char *name, const char *type)
|
||||
{
|
||||
FStringf fname("%s.%s", name, type);
|
||||
auto lump = FindFile(fname);
|
||||
if (lump >= 0) return FileInfo[lump].lump;
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
FResourceLump *FileSystem::Lookup(unsigned int id, const char *type)
|
||||
{
|
||||
auto lump = FindResource(id, type);
|
||||
if (lump >= 0) return FileInfo[lump].lump;
|
||||
else return nullptr;
|
||||
}
|
||||
FResourceLump* FileSystem::GetFileAt(int no)
|
||||
{
|
||||
return FileInfo[no].lump;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Stand-ins for Blood's resource class
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const void *FileSystem::Lock(int lump)
|
||||
{
|
||||
if ((size_t)lump >= FileInfo.Size()) return nullptr;
|
||||
auto lumpp = FileInfo[lump].lump;
|
||||
return lumpp->Lock();
|
||||
}
|
||||
|
||||
void FileSystem::Unlock(int lump)
|
||||
{
|
||||
if ((size_t)lump >= FileInfo.Size()) return;
|
||||
auto lumpp = FileInfo[lump].lump;
|
||||
lumpp->Unlock();
|
||||
}
|
||||
|
||||
const void *FileSystem::Get(int lump)
|
||||
{
|
||||
if ((size_t)lump >= FileInfo.Size()) return nullptr;
|
||||
auto lumpp = FileInfo[lump].lump;
|
||||
auto p = lumpp->Lock();
|
||||
lumpp->RefCount = INT_MAX/2; // lock forever.
|
||||
return p;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Stand-ins for Blood's resource class
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const void *FileSystem::Lock(FResourceLump *lump)
|
||||
{
|
||||
if (lump) return lump->Lock();
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
void FileSystem::Unlock(FResourceLump *lump)
|
||||
{
|
||||
if (lump) lump->Unlock();
|
||||
}
|
||||
|
||||
const void *FileSystem::Load(FResourceLump *lump)
|
||||
{
|
||||
if (lump)
|
||||
{
|
||||
auto p = lump->Lock();
|
||||
lump->RefCount = INT_MAX/2; // lock forever.
|
||||
return p;
|
||||
}
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,20 +187,8 @@ public:
|
|||
int AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags);
|
||||
FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
void InitHashChains();
|
||||
|
||||
// Blood stuff
|
||||
FResourceLump* Lookup(const char* name, const char* type);
|
||||
FResourceLump* Lookup(unsigned int id, const char* type);
|
||||
|
||||
FResourceLump* GetFileAt(int no);
|
||||
|
||||
const void* Lock(int lump);
|
||||
void Unlock(int lump);
|
||||
const void* Get(int lump);
|
||||
static const void* Lock(FResourceLump* lump);
|
||||
static void Unlock(FResourceLump* lump);
|
||||
static const void* Load(FResourceLump* lump);;
|
||||
|
||||
protected:
|
||||
|
||||
struct LumpRecord;
|
||||
|
|
|
@ -240,10 +240,11 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, Lump
|
|||
FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
|
||||
FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
|
||||
FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
|
||||
FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter);
|
||||
FResourceFile *CheckLump(const char *filename,FileReader &file, bool quiet, LumpFilterInfo* filter);
|
||||
FResourceFile *CheckDir(const char *filename, bool quiet, bool nosub, LumpFilterInfo* filter);
|
||||
|
||||
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckLump };
|
||||
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckLump };
|
||||
|
||||
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter)
|
||||
{
|
||||
|
|
|
@ -164,7 +164,6 @@ public:
|
|||
const FString &GetHash() const { return Hash; }
|
||||
|
||||
|
||||
virtual bool Open(bool quiet, LumpFilterInfo* filter) = 0;
|
||||
virtual FResourceLump *GetLump(int no) = 0;
|
||||
FResourceLump *FindLump(const char *name);
|
||||
};
|
||||
|
|
|
@ -214,8 +214,8 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
|
|||
// Because a lot of wads with their own font seem to foolishly
|
||||
// copy STCFN121 and make it a '|' themselves, wads must
|
||||
// provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load as a 'y'.
|
||||
FStringf c120("%s120", nametemplate);
|
||||
FStringf c122("%s122", nametemplate);
|
||||
FStringf c120(nametemplate, 120);
|
||||
FStringf c122(nametemplate, 122);
|
||||
if (!TexMan.CheckForTexture(c120, ETextureType::MiscPatch).isValid() ||
|
||||
!TexMan.CheckForTexture(c122, ETextureType::MiscPatch).isValid())
|
||||
{
|
||||
|
@ -328,14 +328,14 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
|
|||
|
||||
auto orig = pic->GetTexture();
|
||||
auto tex = MakeGameTexture(orig, nullptr, ETextureType::FontChar);
|
||||
tex->CopySize(pic);
|
||||
tex->CopySize(pic, true);
|
||||
TexMan.AddGameTexture(tex);
|
||||
Chars[i].OriginalPic = tex;
|
||||
|
||||
if (!noTranslate)
|
||||
{
|
||||
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1(orig->GetImage())), nullptr, ETextureType::FontChar);
|
||||
Chars[i].TranslatedPic->CopySize(pic);
|
||||
Chars[i].TranslatedPic->CopySize(pic, true);
|
||||
TexMan.AddGameTexture(Chars[i].TranslatedPic);
|
||||
}
|
||||
else
|
||||
|
@ -441,9 +441,9 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
|
|||
auto pic = (*lump)->GetTexture();
|
||||
Chars[i].OriginalPic = (*lump)->GetUseType() == ETextureType::FontChar? (*lump) : MakeGameTexture(pic, nullptr, ETextureType::FontChar);
|
||||
Chars[i].OriginalPic->SetUseType(ETextureType::FontChar);
|
||||
Chars[i].OriginalPic->CopySize(*lump);
|
||||
Chars[i].OriginalPic->CopySize(*lump, true);
|
||||
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1(pic->GetImage())), nullptr, ETextureType::FontChar);
|
||||
Chars[i].TranslatedPic->CopySize(*lump);
|
||||
Chars[i].TranslatedPic->CopySize(*lump, true);
|
||||
Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar);
|
||||
if (Chars[i].OriginalPic != *lump) TexMan.AddGameTexture(Chars[i].OriginalPic);
|
||||
TexMan.AddGameTexture(Chars[i].TranslatedPic);
|
||||
|
@ -860,7 +860,7 @@ int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
|
|||
}
|
||||
if (color != nullptr) *color = retcolor;
|
||||
}
|
||||
if (ActiveColors == 0)
|
||||
if (ActiveColors == 0 || range == CR_UNDEFINED)
|
||||
return -1;
|
||||
else if (range >= NumTextColors)
|
||||
range = CR_UNTRANSLATED;
|
||||
|
@ -880,6 +880,8 @@ int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
|
|||
|
||||
int FFont::GetCharCode(int code, bool needpic) const
|
||||
{
|
||||
int newcode;
|
||||
|
||||
if (code < 0 && code >= -128)
|
||||
{
|
||||
// regular chars turn negative when the 8th bit is set.
|
||||
|
@ -905,8 +907,7 @@ int FFont::GetCharCode(int code, bool needpic) const
|
|||
}
|
||||
}
|
||||
// Try stripping accents from accented characters.
|
||||
int newcode = stripaccent(code);
|
||||
if (newcode != code)
|
||||
while ((newcode = stripaccent(code)) != code)
|
||||
{
|
||||
code = newcode;
|
||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].TranslatedPic != nullptr))
|
||||
|
@ -918,7 +919,6 @@ int FFont::GetCharCode(int code, bool needpic) const
|
|||
else
|
||||
{
|
||||
int originalcode = code;
|
||||
int newcode;
|
||||
|
||||
// Try stripping accents from accented characters. This may repeat to allow multi-step fallbacks.
|
||||
while ((newcode = stripaccent(code)) != code)
|
||||
|
@ -977,7 +977,7 @@ FGameTexture *FFont::GetChar (int code, int translation, int *const width, bool
|
|||
if (code < 0) return nullptr;
|
||||
|
||||
|
||||
if (translation == CR_UNTRANSLATED && !forceremap)
|
||||
if ((translation == CR_UNTRANSLATED || translation == CR_UNDEFINED) && !forceremap)
|
||||
{
|
||||
bool redirect = Chars[code].OriginalPic && Chars[code].OriginalPic != Chars[code].TranslatedPic;
|
||||
if (redirected) *redirected = redirect;
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
|
||||
// FFont interface
|
||||
FGameTexture *GetChar(int code, int translation, int *const width, bool *redirected = nullptr) const override;
|
||||
int GetCharWidth (int code) const;
|
||||
int GetCharWidth (int code) const override;
|
||||
|
||||
protected:
|
||||
FTextureID PicNum;
|
||||
|
|
|
@ -105,13 +105,13 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture
|
|||
{
|
||||
auto pic = charlumps[i];
|
||||
Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar);
|
||||
Chars[i].OriginalPic->CopySize(pic);
|
||||
Chars[i].OriginalPic->CopySize(pic, true);
|
||||
TexMan.AddGameTexture(Chars[i].OriginalPic);
|
||||
|
||||
if (!noTranslate)
|
||||
{
|
||||
Chars[i].TranslatedPic = MakeGameTexture(new FImageTexture(new FFontChar1 (charlumps[i]->GetTexture()->GetImage())), nullptr, ETextureType::FontChar);
|
||||
Chars[i].TranslatedPic->CopySize(charlumps[i]);
|
||||
Chars[i].TranslatedPic->CopySize(charlumps[i], true);
|
||||
TexMan.AddGameTexture(Chars[i].TranslatedPic);
|
||||
}
|
||||
else Chars[i].TranslatedPic = Chars[i].OriginalPic;
|
||||
|
|
|
@ -786,7 +786,7 @@ void V_InitFonts()
|
|||
}
|
||||
if (!(IntermissionFont = FFont::FindFont("IntermissionFont")))
|
||||
{
|
||||
if (fileSystem.CheckNumForName("WINUM0") >= 0)
|
||||
if (TexMan.CheckForTexture("WINUM0", ETextureType::MiscPatch).isValid())
|
||||
{
|
||||
IntermissionFont = FFont::FindFont("IntermissionFont_Doom");
|
||||
}
|
||||
|
|
|
@ -56,13 +56,13 @@ protected:
|
|||
public:
|
||||
FVoxelModel(FVoxel *voxel, bool owned);
|
||||
~FVoxelModel();
|
||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length);
|
||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||
void Initialize();
|
||||
virtual int FindFrame(const char * name);
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0);
|
||||
virtual void AddSkins(uint8_t *hitlist);
|
||||
virtual int FindFrame(const char * name) override;
|
||||
virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) override;
|
||||
virtual void AddSkins(uint8_t *hitlist) override;
|
||||
FTextureID GetPaletteTexture() const { return mPalette; }
|
||||
void BuildVertexBuffer(FModelRenderer *renderer);
|
||||
void BuildVertexBuffer(FModelRenderer *renderer) override;
|
||||
float getAspectFactor(float vscale) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
PT_TwoSided = 1, // like normal, but don't cull backfaces
|
||||
PT_Translucent = 2, // additive blending
|
||||
PT_Masked = 3, // draw with alpha testing
|
||||
PT_Modulated = 4, // modulated blending (src*dest*2)
|
||||
PT_Modulated = 4, // overlay-like blending (rgb values below 128 darken, 128 is unchanged, and above 128 lighten)
|
||||
// types mask
|
||||
PT_Type = 7,
|
||||
// flags
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
|
@ -665,7 +666,7 @@ PClass *PClass::FindClassTentative(FName name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc)
|
||||
int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType)
|
||||
{
|
||||
auto proto = variant->Proto;
|
||||
for (unsigned i = 0; i < Virtuals.Size(); i++)
|
||||
|
@ -693,7 +694,10 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction
|
|||
|
||||
for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++)
|
||||
{
|
||||
if (proto->ReturnTypes[a] != vproto->ReturnTypes[a])
|
||||
PType* expected = vproto->ReturnTypes[a];
|
||||
PType* actual = proto->ReturnTypes[a];
|
||||
|
||||
if (expected != actual && (exactReturnType || !AreCompatiblePointerTypes(expected, actual)))
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
void InitializeSpecials(void* addr, void* defaults, TArray<FTypeAndOffset> PClass::* Inits);
|
||||
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
||||
bool ReadAllFields(FSerializer &ar, void *addr) const;
|
||||
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc);
|
||||
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType);
|
||||
PSymbol *FindSymbol(FName symname, bool searchparents) const;
|
||||
PField *AddField(FName name, PType *type, uint32_t flags);
|
||||
void InitializeDefaults();
|
||||
|
|
|
@ -52,8 +52,6 @@
|
|||
EXTERN_CVAR(Int, m_use_mouse)
|
||||
|
||||
CVAR(Bool, use_mouse, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, m_noprescale, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CVAR(Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
@ -75,7 +73,7 @@ size_t s_skipMouseMoves;
|
|||
|
||||
void CheckGUICapture()
|
||||
{
|
||||
bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture();
|
||||
bool wantCapt = sysCallbacks.WantGuiCapture && sysCallbacks.WantGuiCapture();
|
||||
|
||||
if (wantCapt != GUICapture)
|
||||
{
|
||||
|
@ -151,7 +149,7 @@ void CheckNativeMouse()
|
|||
}
|
||||
else
|
||||
{
|
||||
bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame();
|
||||
bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame();
|
||||
wantNative = (!m_use_mouse || MENU_WaitKey != menuactive)
|
||||
&& (!captureModeInGame || GUICapture);
|
||||
}
|
||||
|
@ -163,7 +161,7 @@ void CheckNativeMouse()
|
|||
&& (MENU_On == menuactive || MENU_OnNoPause == menuactive);
|
||||
}
|
||||
|
||||
if (!wantNative && sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse())
|
||||
if (!wantNative && sysCallbacks.WantNativeMouse && sysCallbacks.WantNativeMouse())
|
||||
wantNative = true;
|
||||
|
||||
I_SetNativeMouse(wantNative);
|
||||
|
@ -488,42 +486,9 @@ void ProcessMouseMoveInMenu(NSEvent* theEvent)
|
|||
void ProcessMouseMoveInGame(NSEvent* theEvent)
|
||||
{
|
||||
int x([theEvent deltaX]);
|
||||
int y(-[theEvent deltaY]);
|
||||
int y([theEvent deltaY]);
|
||||
|
||||
if (0 == x && 0 == y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_noprescale)
|
||||
{
|
||||
x <<= 2;
|
||||
}
|
||||
|
||||
event_t event = {};
|
||||
|
||||
static int lastX = 0, lastY = 0;
|
||||
|
||||
if (m_filter)
|
||||
{
|
||||
event.x = (x + lastX) / 2;
|
||||
event.y = (y + lastY) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
event.x = x;
|
||||
event.y = y;
|
||||
}
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
|
||||
if (0 != event.x || 0 != event.y)
|
||||
{
|
||||
event.type = EV_Mouse;
|
||||
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
PostMouseMove(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1066,7 +1066,7 @@ void IOKitJoystickManager::UseAxesPolling(const bool axesPolling)
|
|||
|
||||
void PostDeviceChangeEvent()
|
||||
{
|
||||
const event_t event = { EV_DeviceChange };
|
||||
event_t event = { EV_DeviceChange };
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,15 +101,26 @@ void I_DetectOS()
|
|||
|
||||
const char* name = "Unknown version";
|
||||
|
||||
if (10 == version.majorVersion) switch (version.minorVersion)
|
||||
if (10 == version.majorVersion)
|
||||
{
|
||||
case 9: name = "OS X Mavericks"; break;
|
||||
case 10: name = "OS X Yosemite"; break;
|
||||
case 11: name = "OS X El Capitan"; break;
|
||||
case 12: name = "macOS Sierra"; break;
|
||||
case 13: name = "macOS High Sierra"; break;
|
||||
case 14: name = "macOS Mojave"; break;
|
||||
case 15: name = "macOS Catalina"; break;
|
||||
switch (version.minorVersion)
|
||||
{
|
||||
case 9: name = "OS X Mavericks"; break;
|
||||
case 10: name = "OS X Yosemite"; break;
|
||||
case 11: name = "OS X El Capitan"; break;
|
||||
case 12: name = "macOS Sierra"; break;
|
||||
case 13: name = "macOS High Sierra"; break;
|
||||
case 14: name = "macOS Mojave"; break;
|
||||
case 15: name = "macOS Catalina"; break;
|
||||
case 16: name = "macOS Big Sur"; break;
|
||||
}
|
||||
}
|
||||
else if (11 == version.majorVersion)
|
||||
{
|
||||
switch (version.minorVersion)
|
||||
{
|
||||
case 0: name = "macOS Big Sur"; break;
|
||||
}
|
||||
}
|
||||
|
||||
char release[16] = "unknown";
|
||||
|
@ -124,7 +135,9 @@ void I_DetectOS()
|
|||
#ifdef __i386__
|
||||
"32-bit Intel";
|
||||
#elif defined __x86_64__
|
||||
"64-bit Intel";
|
||||
"64-bit Intel";
|
||||
#elif defined __aarch64__
|
||||
"64-bit ARM";
|
||||
#else
|
||||
"Unknown";
|
||||
#endif
|
||||
|
|
|
@ -102,6 +102,7 @@ EXTERN_CVAR(Int, vid_preferbackend)
|
|||
EXTERN_CVAR(Bool, vk_debug)
|
||||
|
||||
CVAR(Bool, mvk_debug, false, 0)
|
||||
CVAR(Bool, vid_nativefullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
{
|
||||
|
@ -290,6 +291,7 @@ CocoaWindow* CreateWindow(const NSUInteger styleMask)
|
|||
[window setOpaque:YES];
|
||||
[window makeFirstResponder:appCtrl];
|
||||
[window setAcceptsMouseMovedEvents:YES];
|
||||
[window exitAppOnClose];
|
||||
|
||||
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
|
||||
[nc addObserver:window
|
||||
|
@ -633,7 +635,6 @@ void SystemBaseFrameBuffer::SetWindowedMode()
|
|||
const NSRect frameSize = NSMakeRect(win_x, win_y, win_w, win_h);
|
||||
[m_window setFrame:frameSize display:YES];
|
||||
[m_window enterFullscreenOnZoom];
|
||||
[m_window exitAppOnClose];
|
||||
}
|
||||
|
||||
void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI)
|
||||
|
@ -650,7 +651,11 @@ void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI)
|
|||
[m_window.contentView layer].contentsScale = hiDPI ? m_window.screen.backingScaleFactor : 1.0;
|
||||
}
|
||||
|
||||
if (fullscreen)
|
||||
if (vid_nativefullscreen && fullscreen != m_fullscreen)
|
||||
{
|
||||
[m_window toggleFullScreen:(nil)];
|
||||
}
|
||||
else if (fullscreen)
|
||||
{
|
||||
SetFullscreenMode();
|
||||
}
|
||||
|
@ -742,7 +747,11 @@ void SystemGLFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI)
|
|||
NSOpenGLView* const glView = [m_window contentView];
|
||||
[glView setWantsBestResolutionOpenGLSurface:hiDPI];
|
||||
|
||||
if (fullscreen)
|
||||
if (vid_nativefullscreen && fullscreen != m_fullscreen)
|
||||
{
|
||||
[m_window toggleFullScreen:(nil)];
|
||||
}
|
||||
else if (fullscreen)
|
||||
{
|
||||
SetFullscreenMode();
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
|
|||
- (void)dealloc;
|
||||
- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads;
|
||||
|
||||
- (int)numberOfRowsInTableView:(NSTableView *)aTableView;
|
||||
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex;
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
|
||||
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex;
|
||||
@end
|
||||
|
||||
@implementation IWADTableData
|
||||
|
@ -100,12 +100,12 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
|
|||
return self;
|
||||
}
|
||||
|
||||
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
|
||||
{
|
||||
return [data count];
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
|
||||
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
|
||||
{
|
||||
NSParameterAssert(rowIndex >= 0 && (unsigned int) rowIndex < [data count]);
|
||||
NSMutableDictionary *record = [data objectAtIndex:rowIndex];
|
||||
|
@ -375,6 +375,8 @@ static NSString* GetArchitectureString()
|
|||
return @"i386";
|
||||
#elif defined __x86_64__
|
||||
return @"x86_64";
|
||||
#elif defined __aarch64__
|
||||
return @"arm64";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -382,13 +384,6 @@ static void RestartWithParameters(const WadStuff& wad, NSString* parameters)
|
|||
{
|
||||
assert(nil != parameters);
|
||||
|
||||
defaultiwad = wad.Name;
|
||||
|
||||
GameConfig->ArchiveGlobalData();
|
||||
GameConfig->WriteConfigFile();
|
||||
delete GameConfig;
|
||||
GameConfig = nullptr;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
@try
|
||||
|
@ -396,22 +391,14 @@ static void RestartWithParameters(const WadStuff& wad, NSString* parameters)
|
|||
NSString* executablePath = [NSString stringWithUTF8String:Args->GetArg(0)];
|
||||
|
||||
NSMutableArray* const arguments = [[NSMutableArray alloc] init];
|
||||
|
||||
// The following value shoud be equal to NSAppKitVersionNumber10_5
|
||||
// It's hard-coded in order to build with earlier SDKs
|
||||
const bool canSelectArchitecture = NSAppKitVersionNumber >= 949;
|
||||
|
||||
if (canSelectArchitecture)
|
||||
{
|
||||
[arguments addObject:@"-arch"];
|
||||
[arguments addObject:GetArchitectureString()];
|
||||
[arguments addObject:executablePath];
|
||||
|
||||
executablePath = @"/usr/bin/arch";
|
||||
}
|
||||
|
||||
[arguments addObject:@"-arch"];
|
||||
[arguments addObject:GetArchitectureString()];
|
||||
[arguments addObject:executablePath];
|
||||
[arguments addObject:@"-iwad"];
|
||||
[arguments addObject:[NSString stringWithUTF8String:wad.Path]];
|
||||
[arguments addObject:@"+defaultiwad"];
|
||||
[arguments addObject:[NSString stringWithUTF8String:wad.Name]];
|
||||
[arguments addObject:[NSString stringWithFormat:@"+osx_additional_parameters \"%@\"", parameters]];
|
||||
|
||||
for (int i = 1, count = Args->NumArgs(); i < count; ++i)
|
||||
{
|
||||
|
@ -433,7 +420,7 @@ static void RestartWithParameters(const WadStuff& wad, NSString* parameters)
|
|||
wordfree(&expansion);
|
||||
}
|
||||
|
||||
[NSTask launchedTaskWithLaunchPath:executablePath
|
||||
[NSTask launchedTaskWithLaunchPath:@"/usr/bin/arch"
|
||||
arguments:arguments];
|
||||
|
||||
_exit(0); // to avoid atexit()'s functions
|
||||
|
@ -454,11 +441,10 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad
|
|||
IWADPicker *picker = [IWADPicker alloc];
|
||||
int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad];
|
||||
|
||||
NSString* parametersToAppend = [picker commandLineParameters];
|
||||
osx_additional_parameters = [parametersToAppend UTF8String];
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
NSString* parametersToAppend = [picker commandLineParameters];
|
||||
|
||||
if (0 != [parametersToAppend length])
|
||||
{
|
||||
RestartWithParameters(wads[ret], parametersToAppend);
|
||||
|
|
|
@ -52,6 +52,7 @@ bool I_SetCursor(FGameTexture *cursorpic)
|
|||
return false;
|
||||
}
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
if (cursorSurface == NULL)
|
||||
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
|
||||
|
||||
|
@ -67,6 +68,7 @@ bool I_SetCursor(FGameTexture *cursorpic)
|
|||
SDL_FreeCursor (cursor);
|
||||
cursor = SDL_CreateColorCursor (cursorSurface, 0, 0);
|
||||
SDL_SetCursor (cursor);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -54,8 +54,6 @@ bool GUICapture;
|
|||
static bool NativeMouse = true;
|
||||
|
||||
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
|
||||
extern int WaitingForKey, chatmodeon;
|
||||
|
@ -167,7 +165,7 @@ static const TMap<SDL_Scancode, uint8_t> KeyScanToDIK(InitKeyScanMap());
|
|||
|
||||
static void I_CheckGUICapture ()
|
||||
{
|
||||
bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture();
|
||||
bool wantCapt = sysCallbacks.WantGuiCapture && sysCallbacks.WantGuiCapture();
|
||||
|
||||
if (wantCapt != GUICapture)
|
||||
{
|
||||
|
@ -191,30 +189,6 @@ void I_ReleaseMouseCapture()
|
|||
SDL_SetRelativeMouseMode (SDL_FALSE);
|
||||
}
|
||||
|
||||
static void PostMouseMove (int x, int y)
|
||||
{
|
||||
static int lastx = 0, lasty = 0;
|
||||
event_t ev = { 0,0,0,0,0,0,0 };
|
||||
|
||||
if (m_filter)
|
||||
{
|
||||
ev.x = (x + lastx) / 2;
|
||||
ev.y = (y + lasty) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.x = x;
|
||||
ev.y = y;
|
||||
}
|
||||
lastx = x;
|
||||
lasty = y;
|
||||
if (ev.x | ev.y)
|
||||
{
|
||||
ev.type = EV_Mouse;
|
||||
D_PostEvent (&ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void MouseRead ()
|
||||
{
|
||||
int x, y;
|
||||
|
@ -225,21 +199,17 @@ static void MouseRead ()
|
|||
}
|
||||
|
||||
SDL_GetRelativeMouseState (&x, &y);
|
||||
|
||||
if (x | y)
|
||||
{
|
||||
PostMouseMove (m_noprescale ? x : x << 2, -y);
|
||||
}
|
||||
PostMouseMove (x, y);
|
||||
}
|
||||
|
||||
static void I_CheckNativeMouse ()
|
||||
{
|
||||
bool focus = SDL_GetKeyboardFocus() != NULL;
|
||||
|
||||
bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame();
|
||||
bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame();
|
||||
bool wantNative = !focus || (!use_mouse || GUICapture || !captureModeInGame);
|
||||
|
||||
if (!wantNative && sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse())
|
||||
if (!wantNative && sysCallbacks.WantNativeMouse && sysCallbacks.WantNativeMouse())
|
||||
wantNative = true;
|
||||
|
||||
if (wantNative != NativeMouse)
|
||||
|
@ -493,13 +463,10 @@ void MessagePump (const SDL_Event &sev)
|
|||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
if (!GUICapture)
|
||||
{
|
||||
event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
|
||||
event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button;
|
||||
if(event.data1 != 0)
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
|
||||
event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button;
|
||||
if(event.data1 != 0)
|
||||
D_PostEvent(&event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ FArgs *Args;
|
|||
|
||||
static int GetCrashInfo (char *buffer, char *end)
|
||||
{
|
||||
if (sysCallbacks && sysCallbacks->CrashInfo) sysCallbacks->CrashInfo(buffer, end - buffer, "\n");
|
||||
if (sysCallbacks.CrashInfo) sysCallbacks.CrashInfo(buffer, end - buffer, "\n");
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
extern double refreshfreq;
|
||||
extern IVideo *Video;
|
||||
|
||||
EXTERN_CVAR (Int, vid_adapter)
|
||||
|
@ -451,19 +450,6 @@ SDLVideo::SDLVideo ()
|
|||
Priv::CreateWindow(SDL_WINDOW_HIDDEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get refresh rate for current display.
|
||||
SDL_DisplayMode display;
|
||||
|
||||
if(SDL_GetCurrentDisplayMode(vid_adapter, &display) == 0)
|
||||
{
|
||||
refreshfreq = display.refresh_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Failed to get refresh rate: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SDLVideo::~SDLVideo ()
|
||||
|
|
|
@ -58,7 +58,6 @@ extern "C" {
|
|||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
void GetRefreshRate(HWND hWnd);
|
||||
|
||||
EXTERN_CVAR(Int, vid_defwidth)
|
||||
EXTERN_CVAR(Int, vid_defheight)
|
||||
|
@ -339,7 +338,6 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
|||
}
|
||||
m_Fullscreen = fullscreen;
|
||||
SetSize(GetClientWidth(), GetClientHeight());
|
||||
GetRefreshRate(Window);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -109,7 +109,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst
|
|||
//
|
||||
//==========================================================================
|
||||
EXTERN_CVAR(Bool, vid_vsync);
|
||||
CUSTOM_CVAR(Bool, gl_control_tear, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CUSTOM_CVAR(Bool, gl_control_tear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
vid_vsync.Callback();
|
||||
}
|
||||
|
|
|
@ -459,7 +459,7 @@ void FDInputJoystick::ProcessInput()
|
|||
{
|
||||
// Since we sorted the axes, we know that the first two are definitely X and Y.
|
||||
// They are probably a single stick, so use angular position to determine buttons.
|
||||
buttonstate = Joy_XYAxesToButtons(axisval, Axes[0].Value);
|
||||
buttonstate = Joy_XYAxesToButtons(Axes[0].Value, axisval);
|
||||
Joy_GenerateButtonEvents(info->ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS);
|
||||
}
|
||||
info->ButtonValue = buttonstate;
|
||||
|
|
|
@ -135,8 +135,7 @@ LPDIRECTINPUT g_pdi3;
|
|||
extern bool AppActive;
|
||||
|
||||
int SessionState = 0;
|
||||
int BlockMouseMove;
|
||||
extern double refreshfreq;
|
||||
int BlockMouseMove;
|
||||
|
||||
static bool EventHandlerResultForNativeMouse;
|
||||
|
||||
|
@ -148,7 +147,7 @@ extern int chatmodeon;
|
|||
|
||||
static void I_CheckGUICapture ()
|
||||
{
|
||||
bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture();
|
||||
bool wantCapt = sysCallbacks.WantGuiCapture && sysCallbacks.WantGuiCapture();
|
||||
|
||||
if (wantCapt != GUICapture)
|
||||
{
|
||||
|
@ -345,22 +344,6 @@ bool CallHook(FInputDevice *device, HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
return device->WndProcHook(hWnd, message, wParam, lParam, result);
|
||||
}
|
||||
|
||||
void GetRefreshRate(HWND hWnd)
|
||||
{
|
||||
HMONITOR moni = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFOEXA moninf;
|
||||
moninf.cbSize = sizeof(moninf);
|
||||
if (GetMonitorInfoA(moni, (LPMONITORINFO)&moninf))
|
||||
{
|
||||
DEVMODEA dm;
|
||||
dm.dmSize = sizeof(DEVMODEA);
|
||||
if (EnumDisplaySettingsA(moninf.szDevice, ENUM_CURRENT_SETTINGS, &dm))
|
||||
{
|
||||
refreshfreq = dm.dmDisplayFrequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT result;
|
||||
|
@ -411,7 +394,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
return result;
|
||||
}
|
||||
|
||||
if (message == WM_LBUTTONDOWN && sysCallbacks && sysCallbacks->WantLeftButton() && sysCallbacks->WantLeftButton())
|
||||
if (message == WM_LBUTTONDOWN && sysCallbacks.WantLeftButton() && sysCallbacks.WantLeftButton())
|
||||
{
|
||||
if (GUIWndProcHook(hWnd, message, wParam, lParam, &result))
|
||||
{
|
||||
|
@ -446,7 +429,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
GetRefreshRate(hWnd);
|
||||
I_CheckNativeMouse (false, EventHandlerResultForNativeMouse); // This cannot call the event handler. Doing it from here is unsafe.
|
||||
break;
|
||||
|
||||
|
@ -491,8 +473,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
GetRefreshRate(hWnd);
|
||||
// fall through
|
||||
case WM_STYLECHANGED:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
|
||||
|
@ -524,7 +504,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS);
|
||||
}
|
||||
else if (!noidle && !(sysCallbacks && sysCallbacks->NetGame && sysCallbacks->NetGame()))
|
||||
else if (!noidle && !(sysCallbacks.NetGame && sysCallbacks.NetGame()))
|
||||
{
|
||||
SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);
|
||||
}
|
||||
|
@ -769,7 +749,7 @@ void I_StartTic ()
|
|||
BlockMouseMove--;
|
||||
buttonMap.ResetButtonTriggers ();
|
||||
I_CheckGUICapture ();
|
||||
EventHandlerResultForNativeMouse = sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse();
|
||||
EventHandlerResultForNativeMouse = sysCallbacks.WantNativeMouse && sysCallbacks.WantNativeMouse();
|
||||
I_CheckNativeMouse (false, EventHandlerResultForNativeMouse);
|
||||
I_GetEvent ();
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@ public:
|
|||
virtual void Ungrab() = 0;
|
||||
|
||||
protected:
|
||||
void PostMouseMove(int x, int y);
|
||||
void WheelMoved(int axis, int wheelmove);
|
||||
void PostButtonEvent(int button, bool down);
|
||||
void ClearButtonState();
|
||||
|
|
|
@ -277,6 +277,8 @@ void FKeyboard::PostKeyEvent(int key, INTBOOL down, bool foreground)
|
|||
}
|
||||
ev.data1 = key;
|
||||
ev.data2 = Convert[key];
|
||||
ev.data3 = 0;
|
||||
if (CheckKey(DIK_LSHIFT) || CheckKey(DIK_RSHIFT)) ev.data3 |= 1;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
|
||||
|
|
|
@ -1108,7 +1108,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info)
|
|||
char *custominfo = (char *)HeapAlloc (GetProcessHeap(), 0, 16384);
|
||||
|
||||
CrashPointers = *info;
|
||||
if (sysCallbacks && sysCallbacks->CrashInfo && custominfo) sysCallbacks->CrashInfo(custominfo, 16384, "\r\n");
|
||||
if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n");
|
||||
CreateCrashLog (custominfo, (DWORD)strlen(custominfo), ConWindow);
|
||||
|
||||
// If the main thread crashed, then make it clean up after itself.
|
||||
|
|
|
@ -162,8 +162,6 @@ bool NativeMouse;
|
|||
bool CursorState;
|
||||
|
||||
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, m_hidepointer, true, 0)
|
||||
|
||||
CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
|
@ -271,7 +269,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
|||
else
|
||||
{
|
||||
bool pauseState = false;
|
||||
bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame();
|
||||
bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame();
|
||||
want_native = ((!m_use_mouse || menuactive != MENU_WaitKey) &&
|
||||
(!captureModeInGame || GUICapture));
|
||||
}
|
||||
|
@ -314,38 +312,6 @@ FMouse::FMouse()
|
|||
WheelMove[1] = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: PostMouseMove
|
||||
//
|
||||
// Posts a mouse movement event, potentially averaging it with the previous
|
||||
// movement. If there is no movement to post, then no event is generated.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMouse::PostMouseMove(int x, int y)
|
||||
{
|
||||
event_t ev = { 0 };
|
||||
|
||||
if (m_filter)
|
||||
{
|
||||
ev.x = (x + LastX) / 2;
|
||||
ev.y = (y + LastY) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.x = x;
|
||||
ev.y = y;
|
||||
}
|
||||
LastX = x;
|
||||
LastY = y;
|
||||
if (ev.x | ev.y)
|
||||
{
|
||||
ev.type = EV_Mouse;
|
||||
D_PostEvent(&ev);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMouse :: WheelMoved
|
||||
|
@ -620,8 +586,8 @@ bool FRawMouse::ProcessRawInput(RAWINPUT *raw, int code)
|
|||
{
|
||||
WheelMoved(1, (SHORT)raw->data.mouse.usButtonData);
|
||||
}
|
||||
int x = m_noprescale ? raw->data.mouse.lLastX : raw->data.mouse.lLastX << 2;
|
||||
int y = -raw->data.mouse.lLastY;
|
||||
int x = raw->data.mouse.lLastX;
|
||||
int y = raw->data.mouse.lLastY;
|
||||
PostMouseMove(x, y);
|
||||
if (x | y)
|
||||
{
|
||||
|
@ -847,7 +813,7 @@ void FDInputMouse::ProcessInput()
|
|||
}
|
||||
}
|
||||
}
|
||||
PostMouseMove(m_noprescale ? dx : dx<<2, -dy);
|
||||
PostMouseMove(dx, dy);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -952,18 +918,13 @@ void FWin32Mouse::ProcessInput()
|
|||
}
|
||||
|
||||
x = pt.x - PrevX;
|
||||
y = PrevY - pt.y;
|
||||
y = pt.y - PrevY;
|
||||
|
||||
if (!m_noprescale)
|
||||
{
|
||||
x *= 3;
|
||||
y *= 2;
|
||||
}
|
||||
if (x | y)
|
||||
{
|
||||
CenterMouse(pt.x, pt.y, &PrevX, &PrevY);
|
||||
}
|
||||
PostMouseMove(x, y);
|
||||
PostMouseMove(2* x, 2* y); // The factor of 2 is needed to match this with raw mouse input.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "printf.h"
|
||||
#include "startupinfo.h"
|
||||
#include "i_interface.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -607,6 +608,7 @@ int RunEndoom()
|
|||
|
||||
void ST_Endoom()
|
||||
{
|
||||
TexMan.DeleteAll();
|
||||
int code = RunEndoom();
|
||||
throw CExitEvent(code);
|
||||
|
||||
|
|
|
@ -396,8 +396,8 @@ static const int StrifeStartupPicSizes[4 + 2 + 1] =
|
|||
|
||||
static void ST_Sound(const char* sndname)
|
||||
{
|
||||
if (sysCallbacks && sysCallbacks->PlayStartupSound)
|
||||
sysCallbacks->PlayStartupSound(sndname);
|
||||
if (sysCallbacks.PlayStartupSound)
|
||||
sysCallbacks.PlayStartupSound(sndname);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
void Swap();
|
||||
bool IsHWGammaActive() const { return HWGammaActive; }
|
||||
|
||||
void SetVSync(bool vsync);
|
||||
void SetVSync(bool vsync) override;
|
||||
|
||||
void Draw2D() override;
|
||||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||
|
|
|
@ -49,7 +49,7 @@ void FGLRenderer::RenderScreenQuad()
|
|||
{
|
||||
auto buffer = static_cast<GLVertexBuffer *>(screen->mVertexData->GetBufferObjects().first);
|
||||
buffer->Bind(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 3);
|
||||
}
|
||||
|
||||
void FGLRenderer::PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||
|
|
|
@ -329,12 +329,24 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio
|
|||
|
||||
if (base->BindOrCreate(tex->GetTexture(), 0, clampmode, translation, layer->scaleFlags))
|
||||
{
|
||||
for (int i = 1; i<numLayers; i++)
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
auto systex = static_cast<FHardwareTexture*>(mat->GetLayer(i, 0, &layer));
|
||||
// fixme: Upscale flags must be disabled for certain layers.
|
||||
systex->BindOrCreate(layer->layerTexture, i, clampmode, 0, layer->scaleFlags);
|
||||
maxbound = i;
|
||||
for (int i = 1; i < numLayers; i++)
|
||||
{
|
||||
auto systex = static_cast<FHardwareTexture*>(mat->GetLayer(i, 0, &layer));
|
||||
// fixme: Upscale flags must be disabled for certain layers.
|
||||
systex->BindOrCreate(layer->layerTexture, i, clampmode, 0, layer->scaleFlags);
|
||||
maxbound = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
auto systex = static_cast<FHardwareTexture*>(mat->GetLayer(i, translation, &layer));
|
||||
systex->Bind(i, false);
|
||||
maxbound = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// unbind everything from the last texture that's still active
|
||||
|
|
|
@ -109,8 +109,17 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
|
|||
|
||||
void FSamplerManager::SetTextureFilterMode()
|
||||
{
|
||||
UnbindAll();
|
||||
int filter = sysCallbacks && sysCallbacks->DisableTextureFilter && sysCallbacks->DisableTextureFilter() ? 0 : gl_texture_filter;
|
||||
GLint bounds[IHardwareTexture::MAX_TEXTURES];
|
||||
|
||||
// Unbind all
|
||||
for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glGetIntegerv(GL_SAMPLER_BINDING, &bounds[i]);
|
||||
glBindSampler(i, 0);
|
||||
}
|
||||
|
||||
int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
|
@ -122,6 +131,10 @@ void FSamplerManager::SetTextureFilterMode()
|
|||
glSamplerParameteri(mSamplers[CLAMP_XY_NOMIP], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
|
||||
glSamplerParameteri(mSamplers[CLAMP_CAMTEX], GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter);
|
||||
glSamplerParameteri(mSamplers[CLAMP_CAMTEX], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
|
||||
for(int i = 0; i < IHardwareTexture::MAX_TEXTURES; i++)
|
||||
{
|
||||
glBindSampler(i, bounds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -246,7 +246,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
uniform vec4 uTextureBlendColor;
|
||||
uniform vec4 uTextureModulateColor;
|
||||
uniform vec4 uTextureAddColor;
|
||||
uniform vec4 uBlendColor;
|
||||
uniform vec4 uFogColor;
|
||||
uniform float uDesaturationFactor;
|
||||
uniform float uInterpolationFactor;
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
virtual void Resize(size_t newsize) = 0;
|
||||
virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface.
|
||||
virtual void Unmap() {}
|
||||
void *Memory() { assert(map); return map; }
|
||||
void *Memory() { return map; }
|
||||
size_t Size() { return buffersize; }
|
||||
};
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
|
|||
|
||||
// and this is for the postprocessing copy operation
|
||||
vbo_shadowdata[8].Set(-1.0f, -1.0f, 0, 0.0f, 0.0f);
|
||||
vbo_shadowdata[9].Set(-1.0f, 1.0f, 0, 0.0f, 1.f);
|
||||
vbo_shadowdata[10].Set(1.0f, -1.0f, 0, 1.f, 0.0f);
|
||||
vbo_shadowdata[11].Set(1.0f, 1.0f, 0, 1.f, 1.f);
|
||||
vbo_shadowdata[9].Set(3.0f, -1.0f, 0, 2.f, 0.0f);
|
||||
vbo_shadowdata[10].Set(-1.0f, 3.0f, 0, 0.0f, 2.f);
|
||||
vbo_shadowdata[11].Set(3.0f, 3.0f, 0, 2.f, 2.f); // Note: not used anymore
|
||||
|
||||
// The next two are the stencil caps.
|
||||
vbo_shadowdata[12].Set(-32767.0f, 32767.0f, -32767.0f, 0, 0);
|
||||
|
|
|
@ -166,7 +166,7 @@ void CheckBench()
|
|||
|
||||
FString compose;
|
||||
|
||||
if (sysCallbacks && sysCallbacks->GetLocationDescription) compose = sysCallbacks->GetLocationDescription();
|
||||
if (sysCallbacks.GetLocationDescription) compose = sysCallbacks.GetLocationDescription();
|
||||
|
||||
AppendRenderStats(compose);
|
||||
AppendRenderTimes(compose);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "matrix.h"
|
||||
#include "hw_material.h"
|
||||
#include "texmanip.h"
|
||||
#include "version.h"
|
||||
|
||||
struct FColormap;
|
||||
class IVertexBuffer;
|
||||
|
@ -290,7 +291,7 @@ public:
|
|||
mStreamData.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
#ifdef NPOT_EMULATION
|
||||
mStreamData.uNpotEmulation = { 0,0 };
|
||||
|
@ -459,7 +460,15 @@ public:
|
|||
|
||||
void SetDynLight(float r, float g, float b)
|
||||
{
|
||||
mStreamData.uDynLightColor = { r, g, b, 0.0f };
|
||||
mStreamData.uDynLightColor.X = r;
|
||||
mStreamData.uDynLightColor.Y = g;
|
||||
mStreamData.uDynLightColor.Z = b;
|
||||
}
|
||||
|
||||
void SetScreenFade(float f)
|
||||
{
|
||||
// This component is otherwise unused.
|
||||
mStreamData.uDynLightColor.W = f;
|
||||
}
|
||||
|
||||
void SetObjectColor(PalEntry pe)
|
||||
|
@ -569,7 +578,7 @@ public:
|
|||
mMaterial.mChanged = true;
|
||||
mTextureModeFlags = mat->GetLayerFlags();
|
||||
auto scale = mat->GetDetailScale();
|
||||
mStreamData.uDetailParms = { scale.X, scale.Y, 0, 0 };
|
||||
mStreamData.uDetailParms = { scale.X, scale.Y, 2, 0 };
|
||||
}
|
||||
|
||||
void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader)
|
||||
|
|
|
@ -277,7 +277,7 @@ const FDefaultShader defaultshaders[] =
|
|||
{"Warp 2", "shaders/glsl/func_warp2.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Specular", "shaders/glsl/func_spec.fp", "shaders/glsl/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||
{"PBR","shaders/glsl/func_pbr.fp", "shaders/glsl/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||
{"Paletted", "shaders/glsl/func_paletted.fp", "shaders/glsl/material_nolight.fp", ""},
|
||||
{"Paletted", "shaders/glsl/func_paletted.fp", "shaders/glsl/material_nolight.fp", "#define PALETTE_EMULATION\n"},
|
||||
{"No Texture", "shaders/glsl/func_notexture.fp", "shaders/glsl/material_normal.fp", "#define NO_LAYERS\n"},
|
||||
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp", "shaders/glsl/material_normal.fp", ""},
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue