Give the software renderer some love! #186
No files matched your search
+7
-19
@@ -181,7 +181,8 @@ objdir:=$(makedir)/objs
|
||||
|
||||
# very sophisticated dependency
|
||||
sources+=\
|
||||
$(call List,Sourcefile)
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,core/Sourcefile)
|
||||
|
||||
sources+=\
|
||||
$(call List,blua/Sourcefile)
|
||||
@@ -262,12 +263,10 @@ opts+=$(debug_opts)
|
||||
opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
|
||||
|
||||
opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
cxxopts:=$(opts) $(CXXFLAGS) -std=c++17
|
||||
|
||||
cxxopts:=$(opts)
|
||||
cxxopts+=-std=c++17
|
||||
cxxopts+=$(CXXFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++ -lpthread
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
|
||||
cc=$(CC)
|
||||
cxx=$(CXX)
|
||||
@@ -288,6 +287,7 @@ ifndef SILENT
|
||||
ifndef MAKE_RESTARTS
|
||||
ifndef destructive
|
||||
$(shell $(CC) -v)
|
||||
#$(shell $(CXX) -v)
|
||||
define flags =
|
||||
|
||||
SHELL ..... $(SHELL)
|
||||
@@ -315,6 +315,7 @@ endif
|
||||
|
||||
LD:=$(CC)
|
||||
cc:=$(cc) $(opts)
|
||||
cxx:=$(cxx) $(cxxopts)
|
||||
ifdef UPX
|
||||
upx=$(UPX) $(UPX_OPTS)
|
||||
endif
|
||||
@@ -377,19 +378,6 @@ endif
|
||||
$(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
# dependency recipe template (C++)
|
||||
# 1: source file suffix
|
||||
# 2: extra flags to gcc
|
||||
define _recipecxx =
|
||||
$(depdir)/%.d : %.$(1) | $$$$(@D)/
|
||||
ifndef WINDOWSHELL
|
||||
ifdef Echo_name
|
||||
@printf '%-20.20s\r' $$<
|
||||
endif
|
||||
endif
|
||||
$(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
$(eval $(call _recipe,c))
|
||||
$(eval $(call _recipe,cpp))
|
||||
$(eval $(call _recipe,s,$(asflags)))
|
||||
|
||||
@@ -4,8 +4,6 @@ sources+=$(call List,dedicated/Sourcefile)
|
||||
|
||||
opts+=-DDEDICATED
|
||||
|
||||
libs+=-lpthread
|
||||
|
||||
ifdef MINGW
|
||||
libs+=-mconsole
|
||||
endif
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
makedir:=$(makedir)/SDL
|
||||
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
|
||||
NOUPNP=1
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ $(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\
|
||||
$(and $(findstring =,$(v)),\
|
||||
$(eval $(call _predecessor,$(subst =, ,$(v))))))
|
||||
|
||||
# aggregate returns seem to happen alot in c++ so just supress em lel
|
||||
CXXFLAGS+= -Wno-aggregate-return
|
||||
|
||||
# -W -Wno-unused
|
||||
|
||||
ifdef GCC150
|
||||
|
||||
+5
-4
@@ -49,14 +49,15 @@ r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.c
|
||||
r_main.cpp
|
||||
r_patch.c
|
||||
r_patchrotation.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
r_plane.cpp
|
||||
r_segs.cpp
|
||||
r_skins.c
|
||||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.c
|
||||
r_things.cpp
|
||||
r_portal.c
|
||||
p_ceilng.c
|
||||
p_enemy.c
|
||||
|
||||
+1
-1
@@ -341,7 +341,7 @@ static void AM_FrameBufferInit(void)
|
||||
f_x = f_y = 0;
|
||||
f_w = vid.width;
|
||||
f_h = vid.height;
|
||||
am_buf = screens[0];
|
||||
am_buf = vid.screens[0];
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum)
|
||||
vid.modenum = 0;
|
||||
vid.width = 320;
|
||||
vid.height = 240;
|
||||
vid.bpp = 1;
|
||||
vid.buffer = android_surface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
@@ -38,6 +39,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __COMMAND_H__
|
||||
#define __COMMAND_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "doomdef.h"
|
||||
|
||||
@@ -189,4 +193,8 @@ UINT8 CV_CheatsEnabled(void);
|
||||
// Returns cvar by name. Exposed here for Lua.
|
||||
consvar_t *CV_FindVar(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __COMMAND_H__
|
||||
@@ -1321,13 +1321,6 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
|
||||
//
|
||||
void CONS_Error(const char *msg)
|
||||
{
|
||||
#ifdef RPC_NO_WINDOWS_H
|
||||
if (!graphics_started)
|
||||
{
|
||||
MessageBoxA(vid.WndParent, msg, "SRB2Kart Warning", MB_OK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CONS_Printf("\x82%s", msg); // write error msg in different colour
|
||||
CONS_Printf(M_GetText("Press ENTER to continue\n"));
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
target_sourcefile(cpp)
|
||||
@@ -0,0 +1,2 @@
|
||||
memory.cpp
|
||||
thread_pool.cpp
|
||||
@@ -0,0 +1,71 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#include <array>
|
||||
#include <new>
|
||||
|
||||
#include "../z_zone.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class LinearMemory
|
||||
{
|
||||
size_t size_;
|
||||
size_t height_;
|
||||
void* memory_;
|
||||
|
||||
public:
|
||||
constexpr explicit LinearMemory(size_t size) noexcept;
|
||||
|
||||
void* allocate(size_t size);
|
||||
void reset() noexcept;
|
||||
};
|
||||
|
||||
constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {}
|
||||
|
||||
void* LinearMemory::allocate(size_t size)
|
||||
{
|
||||
size_t aligned_size = (size + 15) & ~15;
|
||||
if (height_ + aligned_size > size_)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
if (memory_ == nullptr)
|
||||
{
|
||||
memory_ = Z_Malloc(size_, PU_STATIC, nullptr);
|
||||
}
|
||||
|
||||
void* ptr = (void*)((uintptr_t)(memory_) + height_);
|
||||
height_ += aligned_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void LinearMemory::reset() noexcept
|
||||
{
|
||||
height_ = 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static LinearMemory g_frame_memory {4 * 1024 * 1024};
|
||||
|
||||
void* Z_Frame_Alloc(size_t size)
|
||||
{
|
||||
return g_frame_memory.allocate(size);
|
||||
}
|
||||
|
||||
void Z_Frame_Reset()
|
||||
{
|
||||
g_frame_memory.reset();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_MEMORY_H__
|
||||
#define __SRB2_CORE_MEMORY_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cpluspplus
|
||||
|
||||
/// @brief Allocate a block of memory with a lifespan of the current main-thread frame.
|
||||
/// This function is NOT thread-safe, but the allocated memory may be used across threads.
|
||||
/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails
|
||||
void* Z_Frame_Alloc(size_t size);
|
||||
|
||||
/// @brief Resets per-frame memory. Not thread safe.
|
||||
void Z_Frame_Reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SRB2_CORE_MEMORY_H__
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// This class is derived from Conor Williams' implementation of a concurrent deque
|
||||
// https://github.com/ConorWilliams/ConcurrentDeque
|
||||
// Copyright (C) 2021 Conor Williams
|
||||
|
||||
// The original version was for C++23. This one has been shrunk slightly and adapted to our conventions.
|
||||
|
||||
#ifndef __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
#define __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class SpMcQueue
|
||||
{
|
||||
struct RingBuff {
|
||||
public:
|
||||
explicit RingBuff(int64_t cap) : _cap{cap}, _mask{cap - 1}
|
||||
{
|
||||
SRB2_ASSERT(cap && (!(cap & (cap - 1))) && "Capacity must be buf power of 2!");
|
||||
_buff = std::unique_ptr<T[]>(new T[_cap]);
|
||||
}
|
||||
|
||||
std::int64_t capacity() const noexcept { return _cap; }
|
||||
|
||||
// Store (copy) at modulo index
|
||||
void store(int64_t i, T&& x) noexcept
|
||||
{
|
||||
_buff[i & _mask] = std::move(x);
|
||||
}
|
||||
|
||||
// Load (copy) at modulo index
|
||||
T load(int64_t i) const noexcept
|
||||
{
|
||||
return _buff[i & _mask];
|
||||
}
|
||||
|
||||
// Allocates and returns a new ring buffer, copies elements in range [b, t) into the new buffer.
|
||||
RingBuff* resize(std::int64_t b, std::int64_t t) const
|
||||
{
|
||||
//ZoneScoped;
|
||||
RingBuff* ptr = new RingBuff{2 * _cap};
|
||||
for (std::int64_t i = t; i != b; ++i) {
|
||||
ptr->store(i, load(i));
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t _cap; // Capacity of the buffer
|
||||
int64_t _mask; // Bit mask to perform modulo capacity operations
|
||||
|
||||
std::unique_ptr<T[]> _buff;
|
||||
};
|
||||
|
||||
alignas(64) std::atomic<int64_t> bottom_;
|
||||
alignas(64) std::atomic<int64_t> top_;
|
||||
alignas(64) std::atomic<RingBuff*> buffer_;
|
||||
|
||||
std::vector<std::unique_ptr<RingBuff>> garbage_;
|
||||
|
||||
public:
|
||||
SpMcQueue(size_t capacity) : bottom_(0), top_(0), buffer_(new RingBuff(capacity))
|
||||
{
|
||||
garbage_.reserve(32);
|
||||
}
|
||||
~SpMcQueue() noexcept
|
||||
{
|
||||
delete buffer_.load(std::memory_order_relaxed);
|
||||
};
|
||||
|
||||
size_t size() const noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
return static_cast<size_t>(bottom >= top ? bottom - top : 0);
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
void push(T&& v) noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
if (buf->capacity() < (bottom - top) + 1)
|
||||
{
|
||||
// Queue is full, build a new one
|
||||
RingBuff* newbuf = buf->resize(bottom, top);
|
||||
garbage_.emplace_back(buf);
|
||||
buffer_.store(newbuf, std::memory_order_relaxed);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
// Construct new object, this does not have to be atomic as no one can steal this item until after we
|
||||
// store the new value of bottom, ordering is maintained by surrounding atomics.
|
||||
buf->store(bottom, std::move(v));
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::optional<T> pop() noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed) - 1;
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
bottom_.store(bottom, std::memory_order_relaxed); // Stealers can no longer steal
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
|
||||
if (top <= bottom)
|
||||
{
|
||||
// Non-empty deque
|
||||
if (top == bottom)
|
||||
{
|
||||
// The last item could get stolen, by a stealer that loaded bottom before our write above
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
// Failed race, thief got the last item.
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Can delay load until after acquiring slot as only this thread can push(), this load is not
|
||||
// required to be atomic as we are the exclusive writer.
|
||||
return buf->load(bottom);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<T> steal() noexcept
|
||||
{
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t bottom = bottom_.load(std::memory_order_acquire);
|
||||
|
||||
if (top < bottom)
|
||||
{
|
||||
// Must load *before* acquiring the slot as slot may be overwritten immediately after acquiring.
|
||||
// This load is NOT required to be atomic even-though it may race with an overrite as we only
|
||||
// return the value if we win the race below garanteeing we had no race during our read. If we
|
||||
// loose the race then 'x' could be corrupt due to read-during-write race but as T is trivially
|
||||
// destructible this does not matter.
|
||||
T x = buffer_.load(std::memory_order_consume)->load(top);
|
||||
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
@@ -0,0 +1,255 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_STATIC_VEC_HPP__
|
||||
#define __SRB2_CORE_STATIC_VEC_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec;
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec
|
||||
{
|
||||
std::array<T, Limit> arr_ {{}};
|
||||
size_t size_ = 0;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr StaticVec() {}
|
||||
|
||||
StaticVec(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
}
|
||||
|
||||
StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr StaticVec(std::initializer_list<T> list) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
size_ = list.size();
|
||||
size_t i = 0;
|
||||
for (auto itr = list.begin(); itr != list.end(); itr++)
|
||||
{
|
||||
arr_[i] = *itr;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
~StaticVec() = default;
|
||||
|
||||
StaticVec& operator=(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_back(const T& value) { arr_[size_++] = value; }
|
||||
|
||||
void pop_back() { arr_[--size_] = T(); }
|
||||
|
||||
void resize(size_t size, T value = T())
|
||||
{
|
||||
if (size >= Limit)
|
||||
{
|
||||
throw std::length_error("new size >= Capacity");
|
||||
}
|
||||
|
||||
if (size == size_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (size < size_)
|
||||
{
|
||||
while (size_ > size)
|
||||
{
|
||||
pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (size_ < size)
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
arr_ = {{}};
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
using iterator = typename std::array<T, Limit>::iterator;
|
||||
using const_iterator = typename std::array<T, Limit>::const_iterator;
|
||||
|
||||
constexpr iterator begin() noexcept { return arr_.begin(); }
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr iterator end() noexcept { return std::next(arr_.begin(), size_); }
|
||||
|
||||
constexpr const_iterator end() const noexcept { return cend(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept { return std::next(arr_.cbegin(), size_); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rbegin() noexcept { return std::reverse_iterator(this->end()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crbegin() const noexcept { return std::reverse_iterator(this->cend()); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rend() noexcept { return std::reverse_iterator(this->begin()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crend() const noexcept { return std::reverse_iterator(this->cbegin()); }
|
||||
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
|
||||
constexpr size_t size() const noexcept { return size_; }
|
||||
|
||||
constexpr size_t capacity() const noexcept { return Limit; }
|
||||
|
||||
constexpr size_t max_size() const noexcept { return Limit; }
|
||||
|
||||
constexpr T& operator[](size_t index) noexcept { return arr_[index]; }
|
||||
|
||||
T& at(size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; }
|
||||
|
||||
const T& at(size_t index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
T& front() { return *arr_[0]; }
|
||||
|
||||
T& back() { return *arr_[size_ - 1]; }
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator==(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
const size_t size = lhs.size();
|
||||
if (size != rhs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < lhs; i++)
|
||||
{
|
||||
if (rhs[i] != lhs[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator!=(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
struct std::hash<srb2::StaticVec<T, Limit>>
|
||||
{
|
||||
size_t operator()(const srb2::StaticVec<T, Limit>& input) const
|
||||
{
|
||||
constexpr size_t prime = sizeof(size_t) == 8 ? 0x00000100000001B3 : 0x01000193;
|
||||
constexpr size_t basis = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5;
|
||||
|
||||
size_t ret = basis;
|
||||
for (auto itr = input.begin(); itr != input.end(); itr++)
|
||||
{
|
||||
ret = (ret * prime) ^ std::hash<T>(*itr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __SRB2_CORE_STATIC_VEC_HPP__
|
||||
@@ -0,0 +1,346 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "thread_pool.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
//#include <fmt/format.h>
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
#include "../m_argv.h"
|
||||
|
||||
using namespace srb2;
|
||||
|
||||
static void do_work(ThreadPool::Task& work)
|
||||
{
|
||||
try
|
||||
{
|
||||
//ZoneScoped;
|
||||
(work.thunk)(work.raw.data());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// can't do anything
|
||||
}
|
||||
|
||||
(work.deleter)(work.raw.data());
|
||||
if (work.pseudosema)
|
||||
{
|
||||
work.pseudosema->fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
static void pool_executor(
|
||||
//int thread_index,
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive,
|
||||
std::shared_ptr<std::mutex> worker_ready_mutex,
|
||||
std::shared_ptr<std::condition_variable> worker_ready_condvar,
|
||||
std::shared_ptr<ThreadPool::Queue> my_wq,
|
||||
std::vector<std::shared_ptr<ThreadPool::Queue>> other_wqs
|
||||
)
|
||||
{
|
||||
{
|
||||
//std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index);
|
||||
//tracy::SetThreadName(thread_name.c_str());
|
||||
}
|
||||
|
||||
int spins = 0;
|
||||
while (true)
|
||||
{
|
||||
std::optional<ThreadPool::Task> work = my_wq->steal();
|
||||
bool did_work = false;
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& q : other_wqs)
|
||||
{
|
||||
work = q->steal();
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
|
||||
// We only want to steal one work item at a time, to prioritize our own queue
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!did_work)
|
||||
{
|
||||
// Spin a few loops to avoid yielding, then wait for the ready lock
|
||||
spins += 1;
|
||||
if (spins > 100)
|
||||
{
|
||||
std::unique_lock<std::mutex> ready_lock {*worker_ready_mutex};
|
||||
while (my_wq->empty() && pool_alive->load())
|
||||
{
|
||||
worker_ready_condvar->wait(ready_lock);
|
||||
}
|
||||
|
||||
if (!pool_alive->load())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool()
|
||||
{
|
||||
immediate_mode_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(size_t threads)
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
pool_alive_ = std::make_shared<std::atomic<bool>>(true);
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> wsq = std::make_shared<Queue>(2048);
|
||||
work_queues_.push_back(wsq);
|
||||
|
||||
std::shared_ptr<std::mutex> mutex = std::make_shared<std::mutex>();
|
||||
worker_ready_mutexes_.push_back(std::move(mutex));
|
||||
std::shared_ptr<std::condition_variable> condvar = std::make_shared<std::condition_variable>();
|
||||
worker_ready_condvars_.push_back(std::move(condvar));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> my_queue = work_queues_[i];
|
||||
std::vector<std::shared_ptr<Queue>> other_queues;
|
||||
for (size_t j = 0; j < threads; j++)
|
||||
{
|
||||
// Order the other queues starting from the next adjacent worker
|
||||
// i.e. if this is worker 2 of 8, then other queues is 3, 4, 5, 6, 7, 0, 1
|
||||
// This tries to balance out work stealing behavior
|
||||
|
||||
size_t other_index = j + i;
|
||||
if (other_index >= threads)
|
||||
{
|
||||
other_index -= threads;
|
||||
}
|
||||
|
||||
if (other_index != i)
|
||||
{
|
||||
other_queues.push_back(work_queues_[other_index]);
|
||||
}
|
||||
}
|
||||
|
||||
std::thread thread;
|
||||
try
|
||||
{
|
||||
thread = std::thread
|
||||
{
|
||||
pool_executor,
|
||||
//i,
|
||||
pool_alive_,
|
||||
worker_ready_mutexes_[i],
|
||||
worker_ready_condvars_[i],
|
||||
my_queue,
|
||||
other_queues
|
||||
};
|
||||
}
|
||||
catch (const std::system_error& error)
|
||||
{
|
||||
// Safe shutdown and rethrow
|
||||
pool_alive_->store(false);
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
threads_.push_back(std::move(thread));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(ThreadPool&&) = default;
|
||||
ThreadPool::~ThreadPool() = default;
|
||||
|
||||
ThreadPool& ThreadPool::operator=(ThreadPool&&) = default;
|
||||
|
||||
void ThreadPool::begin_sema()
|
||||
{
|
||||
sema_begun_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::Sema ThreadPool::end_sema()
|
||||
{
|
||||
Sema ret = Sema(std::move(cur_sema_));
|
||||
cur_sema_ = nullptr;
|
||||
sema_begun_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThreadPool::notify()
|
||||
{
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
size_t count = q->size();
|
||||
if (count > 0)
|
||||
{
|
||||
worker_ready_condvars_[i]->notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::notify_sema(const ThreadPool::Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
notify();
|
||||
}
|
||||
|
||||
void ThreadPool::wait_idle()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
while ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::wait_sema(const Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
while (sema.pseudosema_->load(std::memory_order_seq_cst) > 0)
|
||||
{
|
||||
// spin to win
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
if ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sema.pseudosema_->load(std::memory_order_seq_cst) != 0)
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::shutdown()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_idle();
|
||||
|
||||
pool_alive_->store(false);
|
||||
|
||||
for (auto& condvar : worker_ready_condvars_)
|
||||
{
|
||||
condvar->notify_all();
|
||||
}
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ThreadPool> srb2::g_main_threadpool;
|
||||
|
||||
void I_ThreadPoolInit(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool == nullptr);
|
||||
size_t thread_count = std::min(static_cast<unsigned int>(9), std::thread::hardware_concurrency());
|
||||
if (thread_count > 1)
|
||||
{
|
||||
// The main thread will act as a worker when waiting for pool idle
|
||||
// Make one less worker thread to avoid unnecessary context switching
|
||||
thread_count -= 1;
|
||||
}
|
||||
|
||||
if (M_CheckParm("-singlethreaded"))
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>(thread_count);
|
||||
}
|
||||
}
|
||||
|
||||
void I_ThreadPoolShutdown(void)
|
||||
{
|
||||
if (!g_main_threadpool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_main_threadpool->shutdown();
|
||||
g_main_threadpool = nullptr;
|
||||
}
|
||||
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->schedule([=]() {
|
||||
(thunk)(data);
|
||||
});
|
||||
g_main_threadpool->notify();
|
||||
}
|
||||
|
||||
void I_ThreadPoolWaitIdle(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->wait_idle();
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_THREAD_POOL_H__
|
||||
#define __SRB2_CORE_THREAD_POOL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "spmc_queue.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
struct Task
|
||||
{
|
||||
void (*thunk)(void*);
|
||||
void (*deleter)(void*);
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema;
|
||||
std::array<std::byte, 512 - sizeof(void(*)(void*)) * 2 - sizeof(std::shared_ptr<std::atomic<uint32_t>>)> raw;
|
||||
};
|
||||
|
||||
using Queue = SpMcQueue<Task>;
|
||||
|
||||
class Sema
|
||||
{
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema_;
|
||||
|
||||
explicit Sema(std::shared_ptr<std::atomic<uint32_t>> sema) : pseudosema_(sema) {}
|
||||
|
||||
friend class ThreadPool;
|
||||
public:
|
||||
Sema() = default;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive_;
|
||||
std::vector<std::shared_ptr<std::mutex>> worker_ready_mutexes_;
|
||||
std::vector<std::shared_ptr<std::condition_variable>> worker_ready_condvars_;
|
||||
std::vector<std::shared_ptr<Queue>> work_queues_;
|
||||
std::vector<std::thread> threads_;
|
||||
size_t next_queue_index_ = 0;
|
||||
std::shared_ptr<std::atomic<uint32_t>> cur_sema_;
|
||||
|
||||
bool immediate_mode_ = false;
|
||||
bool sema_begun_ = false;
|
||||
|
||||
public:
|
||||
ThreadPool();
|
||||
explicit ThreadPool(size_t threads);
|
||||
ThreadPool(const ThreadPool&) = delete;
|
||||
ThreadPool(ThreadPool&&);
|
||||
~ThreadPool();
|
||||
|
||||
ThreadPool& operator=(const ThreadPool&) = delete;
|
||||
ThreadPool& operator=(ThreadPool&&);
|
||||
|
||||
void begin_sema();
|
||||
ThreadPool::Sema end_sema();
|
||||
|
||||
/// Enqueue but don't notify
|
||||
template <typename T> void schedule(T&& thunk);
|
||||
/// Notify threads after several schedules
|
||||
void notify();
|
||||
void notify_sema(const Sema& sema);
|
||||
void wait_idle();
|
||||
void wait_sema(const Sema& sema);
|
||||
void shutdown();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<ThreadPool> g_main_threadpool;
|
||||
|
||||
template <typename F>
|
||||
void callable_caller(F* f)
|
||||
{
|
||||
(*f)();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void callable_destroyer(F* f)
|
||||
{
|
||||
f->~F();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ThreadPool::schedule(T&& thunk)
|
||||
{
|
||||
static_assert(sizeof(T) <= sizeof(std::declval<Task>().raw));
|
||||
|
||||
if (immediate_mode_)
|
||||
{
|
||||
(thunk)();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sema_begun_)
|
||||
{
|
||||
if (cur_sema_ == nullptr)
|
||||
{
|
||||
cur_sema_ = std::make_shared<std::atomic<uint32_t>>(0);
|
||||
}
|
||||
cur_sema_->fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
size_t qi = next_queue_index_;
|
||||
|
||||
{
|
||||
std::shared_ptr<Queue> q = work_queues_[qi];
|
||||
Task task;
|
||||
task.thunk = reinterpret_cast<void(*)(void*)>(callable_caller<T>);
|
||||
task.deleter = reinterpret_cast<void(*)(void*)>(callable_destroyer<T>);
|
||||
task.pseudosema = cur_sema_;
|
||||
new (reinterpret_cast<T*>(task.raw.data())) T(std::move(thunk));
|
||||
|
||||
q->push(std::move(task));
|
||||
}
|
||||
// worker_ready_condvars_[qi]->notify_one();
|
||||
|
||||
next_queue_index_ += 1;
|
||||
if (next_queue_index_ >= threads_.size())
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
extern "C" {
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef void (*srb2cthunk_t)(void*);
|
||||
|
||||
void I_ThreadPoolInit(void);
|
||||
void I_ThreadPoolShutdown(void);
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data);
|
||||
void I_ThreadPoolWaitIdle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __SRB2_CORE_THREAD_POOL_H__
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#ifndef __SRB2_CXXUTIL_HPP__
|
||||
#define __SRB2_CXXUTIL_HPP__
|
||||
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
namespace srb2 {
|
||||
|
||||
template <class F>
|
||||
class Finally {
|
||||
public:
|
||||
explicit Finally(const F& f) noexcept : f_(f) {}
|
||||
explicit Finally(F&& f) noexcept : f_(f) {}
|
||||
|
||||
Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {}
|
||||
|
||||
Finally(const Finally& from) = delete;
|
||||
void operator=(const Finally& from) = delete;
|
||||
void operator=(Finally&& from) = delete;
|
||||
|
||||
~Finally() noexcept {
|
||||
if (call_)
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
bool call_ = true;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
Finally<std::decay_t<F>> finally(F&& f) noexcept {
|
||||
return Finally {std::forward<F>(f)};
|
||||
}
|
||||
|
||||
struct SourceLocation {
|
||||
const char* file_name;
|
||||
unsigned int line_number;
|
||||
};
|
||||
|
||||
#define SRB2_SOURCE_LOCATION \
|
||||
srb2::SourceLocation { __FILE__, __LINE__ }
|
||||
|
||||
#ifndef SRB2_ASSERT_HANDLER
|
||||
#define SRB2_ASSERT_HANDLER srb2::IErrorAssertHandler
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG) || defined(PARANOIA)
|
||||
// An assertion level of 2 will activate all invocations of the SRB2_ASSERT macro
|
||||
#define SRB2_ASSERTION_LEVEL 2
|
||||
#else
|
||||
// The minimum assertion level is 1
|
||||
#define SRB2_ASSERTION_LEVEL 1
|
||||
#endif
|
||||
|
||||
/// Assert a precondition expression in debug builds.
|
||||
#define SRB2_ASSERT(expr) srb2::do_assert<2, SRB2_ASSERT_HANDLER>([&] { return (expr); }, SRB2_SOURCE_LOCATION, #expr)
|
||||
|
||||
class IErrorAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {
|
||||
I_Error("Assertion failed at %s:%u: %s != true",
|
||||
source_location.file_name,
|
||||
source_location.line_number,
|
||||
expression);
|
||||
}
|
||||
};
|
||||
|
||||
class NoOpAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {(void)source_location; (void)expression;}
|
||||
};
|
||||
|
||||
/// @brief Assert a precondition expression, aborting the application if it fails.
|
||||
/// @tparam Expr
|
||||
/// @tparam Level the level of this assertion; if it is less than or equal to SRB2_ASSERTION_LEVEL, this overload will
|
||||
/// activate.
|
||||
/// @param expr a callable which returns a bool
|
||||
/// @param source_location a struct containing the source location of the assertion, e.g. SRB2_SOURCE_LOCATION
|
||||
/// @param expression the expression evaluated in the expression callable
|
||||
/// @param message an optional message to display for the assertion
|
||||
template <unsigned int Level, class Handler, class Expr>
|
||||
std::enable_if_t<(Level <= SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr& expr, const SourceLocation& source_location, const char* expression = "") noexcept {
|
||||
static_assert(Level > 0, "level of an assertion must not be 0");
|
||||
if (!expr()) {
|
||||
Handler::handle(source_location, expression);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned int Level, class, class Expr>
|
||||
std::enable_if_t<(Level > SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr&, const SourceLocation&, const char* = "") noexcept {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class NotNull final {
|
||||
T ptr_;
|
||||
|
||||
public:
|
||||
static_assert(std::is_convertible_v<decltype(std::declval<T>() != nullptr), bool>,
|
||||
"T is not comparable with nullptr_t");
|
||||
|
||||
/// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a
|
||||
/// NotNull<T> from any compatible pointer U, for example with polymorphic classes.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(U&& rhs) : ptr_(std::forward<U>(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Wrap the pointer type T, asserting that the pointer is not null.
|
||||
template <typename = std::enable_if_t<!std::is_same_v<std::nullptr_t, T>>>
|
||||
constexpr NotNull(T rhs) : ptr_(std::move(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Copy construction from NotNull of convertible type U. Only if the incoming pointer is NotNull already.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(const NotNull<U>& rhs) : NotNull(rhs.get()) {
|
||||
// Value is guaranteed to be not null by construction; no assertion necessary
|
||||
}
|
||||
|
||||
NotNull(const NotNull& rhs) = default;
|
||||
NotNull& operator=(const NotNull& rhs) = default;
|
||||
|
||||
/// @brief Get the stored pointer.
|
||||
constexpr T get() const { return ptr_; }
|
||||
|
||||
/// @brief Convert to T (the pointer type).
|
||||
constexpr operator T() const { return get(); }
|
||||
|
||||
/// @brief Arrow-dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator->() const { return get(); }
|
||||
|
||||
/// @brief Dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator*() const { return *get(); }
|
||||
|
||||
// It is not allowed to construct NotNull<T> with nullptr regardless of T.
|
||||
NotNull(std::nullptr_t) = delete;
|
||||
NotNull& operator=(std::nullptr_t) = delete;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
NotNull(T) -> NotNull<T>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CXXUTIL_HPP__
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_CLISRV__
|
||||
#define __D_CLISRV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netcmd.h"
|
||||
@@ -694,4 +698,9 @@ typedef struct rewind_s {
|
||||
void CL_ClearRewinds(void);
|
||||
rewind_t *CL_SaveRewindPoint(size_t demopos);
|
||||
rewind_t *CL_RewindToTime(tic_t time);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+39
-13
@@ -73,6 +73,8 @@
|
||||
#include "m_perfstats.h"
|
||||
#include "k_kart.h"
|
||||
|
||||
#include "core/memory.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
@@ -325,6 +327,39 @@ static void D_Renderview(void)
|
||||
|
||||
R_ApplyLevelInterpolators(rendertimefrac);
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// if this is display player 1
|
||||
if (cv_homremoval.value)
|
||||
{
|
||||
if (cv_homremoval.value == 1)
|
||||
{
|
||||
// Clear the software screen buffer to remove HOM
|
||||
memset(vid.screens[0], 31, vid.width * vid.height);
|
||||
}
|
||||
else if (cv_homremoval.value == 2)
|
||||
{
|
||||
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
|
||||
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw over the fourth screen so you don't have to stare at a HOM :V
|
||||
if (splitscreen == 2)
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
|
||||
|
||||
for (x = vid.width>>1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height>>1; y < vid.height; y += ph)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
const boolean issplitscreen = (i > 0);
|
||||
@@ -336,7 +371,6 @@ static void D_Renderview(void)
|
||||
if (!issplitscreen) // Initialize for P1
|
||||
{
|
||||
viewwindowy = viewwindowx = 0;
|
||||
topleft = screens[0];
|
||||
objectsdrawn = 0;
|
||||
}
|
||||
|
||||
@@ -350,8 +384,6 @@ static void D_Renderview(void)
|
||||
#endif
|
||||
if (issplitscreen) // Splitscreen-specific
|
||||
{
|
||||
const INT32 len = viewheight*sizeof(ylookup[0]);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
@@ -365,28 +397,20 @@ static void D_Renderview(void)
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
}
|
||||
M_Memcpy(ylookup, ylookup2, len);
|
||||
break;
|
||||
case 2:
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup3, len);
|
||||
break;
|
||||
case 3:
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup4, len);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
}
|
||||
|
||||
R_RenderPlayerView(&players[displayplayers[i]]);
|
||||
|
||||
if (issplitscreen)
|
||||
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
|
||||
}
|
||||
|
||||
if (!issplitscreen)
|
||||
@@ -584,7 +608,7 @@ static boolean D_Display(void)
|
||||
{
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
|
||||
VID_BlitLinearScreen(vid.screens[0], vid.screens[1], vid.width, vid.height, vid.width, vid.rowbytes);
|
||||
}
|
||||
|
||||
lastdraw = false;
|
||||
@@ -618,7 +642,7 @@ static boolean D_Display(void)
|
||||
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
|
||||
|
||||
// vid size change is now finished if it was on...
|
||||
vid.recalc = 0;
|
||||
vid.recalc = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
@@ -750,6 +774,8 @@ void D_SRB2Loop(void)
|
||||
precise_t enterprecise = I_GetPreciseTime();
|
||||
precise_t finishprecise = enterprecise;
|
||||
|
||||
Z_Frame_Reset();
|
||||
|
||||
// Casting the return value of a function is bad practice (apparently)
|
||||
double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision()));
|
||||
capbudget = (precise_t)budget;
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __D_MAIN__
|
||||
#define __D_MAIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h" // for MAX_WADFILES
|
||||
|
||||
@@ -90,4 +94,8 @@ const char *D_Home(void);
|
||||
//
|
||||
void D_StartTitle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__D_MAIN__
|
||||
+8
-2
@@ -18,6 +18,10 @@
|
||||
#ifndef __D_NET__
|
||||
#define __D_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Max computers in a game
|
||||
// 127 is probably as high as this can go, because
|
||||
// SINT8 is used for nodes sometimes >:(
|
||||
@@ -43,8 +47,6 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
|
||||
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
|
||||
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
|
||||
|
||||
extern boolean serverrunning;
|
||||
|
||||
void Net_AckTicker(void);
|
||||
|
||||
// If reliable return true if packet sent, 0 else
|
||||
@@ -65,4 +67,8 @@ void Net_SendAcks(INT32 node);
|
||||
void Net_WaitAllAckReceived(UINT32 timeout);
|
||||
const char *Net_GetPacketName(UINT8 packettype);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+2
-5
@@ -204,11 +204,6 @@ static void Command_Archivetest_f(void);
|
||||
// CLIENT VARIABLES
|
||||
// =========================================================================
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
|
||||
@@ -1030,6 +1025,8 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_scr_width);
|
||||
CV_RegisterVar(&cv_scr_height);
|
||||
|
||||
CV_RegisterVar(&cv_parallelsoftware);
|
||||
|
||||
CV_RegisterVar(&cv_soundtest);
|
||||
|
||||
CV_RegisterVar(&cv_perfstats);
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
#ifndef __D_NETCMD__
|
||||
#define __D_NETCMD__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "command.h"
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
// console vars
|
||||
extern consvar_t cv_playername;
|
||||
extern consvar_t cv_playercolor;
|
||||
@@ -318,4 +327,8 @@ void D_SetPassword(const char *pw);
|
||||
// used for the player setup menu
|
||||
UINT8 CanChangeSkin(INT32 playernum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -111,7 +111,9 @@ static fileused_t transferFiles[UINT8_MAX + 1];
|
||||
// Receiver structure
|
||||
INT32 fileneedednum; // Number of files needed to join the server
|
||||
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex downloadmutex;
|
||||
#endif
|
||||
char downloaddir[512] = "DOWNLOAD";
|
||||
|
||||
file_download_t filedownload;
|
||||
@@ -1351,14 +1353,18 @@ void CURLAbortFile(void)
|
||||
{
|
||||
filedownload.http_running = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
// lock and unlock to wait for the download thread to exit
|
||||
I_lock_mutex(&downloadmutex);
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CURLGetFile(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&downloadmutex);
|
||||
#endif
|
||||
CURLMcode mc; /* return code used by curl_multi_wait() */
|
||||
CURLcode easyres; /* Return from easy interface */
|
||||
CURLMsg *m; /* for picking up messages with the transfer status */
|
||||
@@ -1453,7 +1459,9 @@ void CURLGetFile(void)
|
||||
}
|
||||
|
||||
filedownload.http_running = false;
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_NETFIL__
|
||||
#define __D_NETFIL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
@@ -125,4 +129,8 @@ HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __D_NETFIL__
|
||||
@@ -58,6 +58,9 @@
|
||||
// warning C4152: nonstandard extension, function/data pointer conversion in expression
|
||||
// warning C4213: nonstandard extension used : cast on l-value
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
@@ -524,12 +527,15 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef min // Double-Check with WATTCP-32's cdefs.h
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef max // Double-Check with WATTCP-32's cdefs.h
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
|
||||
#endif
|
||||
@@ -560,6 +566,14 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
#define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// An assert-type mechanism.
|
||||
#ifdef PARANOIA
|
||||
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
|
||||
@@ -657,4 +671,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||
#undef UPDATE_ALERT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __DOOMDEF__
|
||||
+1
-1
@@ -125,7 +125,7 @@ extern boolean lastdraw;
|
||||
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
extern INT32 viewwindowx, viewwindowy;
|
||||
extern INT32 viewwidth, scaledviewwidth;
|
||||
extern INT32 viewwidth;
|
||||
|
||||
extern boolean gamedataloaded;
|
||||
|
||||
|
||||
+23
-16
@@ -17,6 +17,10 @@
|
||||
#ifndef __DOOMTYPE__
|
||||
#define __DOOMTYPE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32)
|
||||
//#define WIN32_LEAN_AND_MEAN
|
||||
#define RPC_NO_WINDOWS_H
|
||||
@@ -100,8 +104,10 @@ typedef long ssize_t;
|
||||
#define strnicmp(x,y,n) strncasecmp(x,y,n)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
char *strcasestr(const char *in, const char *what);
|
||||
#define stristr strcasestr
|
||||
#endif
|
||||
|
||||
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
|
||||
#define true 1
|
||||
@@ -156,22 +162,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
/* Boolean type definition */
|
||||
|
||||
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
|
||||
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
|
||||
#ifndef __BYTEBOOL__
|
||||
#define __BYTEBOOL__
|
||||
|
||||
//faB: clean that up !!
|
||||
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
|
||||
#include "stdbool.h"
|
||||
#elif defined (_WIN32)
|
||||
#define false FALSE // use windows types
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#else
|
||||
typedef enum {false, true} boolean;
|
||||
#endif
|
||||
#endif // __BYTEBOOL__
|
||||
#ifndef _WIN32
|
||||
#include <stdbool.h>
|
||||
// dont use stdbools _BOOL type
|
||||
// its smaller (1 byte) than the old interger bool (4 bytes)
|
||||
// which results in packed struct sizes being mismatched between vanilla and this
|
||||
// however we gotta still include stdbool cause since c23 true and false are keywords
|
||||
// which we cant use as enumeration constants
|
||||
typedef int32_t boolean;
|
||||
#else
|
||||
#define false FALSE
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#endif
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#ifndef INT8_MIN
|
||||
@@ -385,4 +388,8 @@ unset_bit_array (bitarray_t * const array, const int value)
|
||||
|
||||
typedef UINT64 precise_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__DOOMTYPE__
|
||||
+3
-3
@@ -313,7 +313,7 @@ void F_WipeStartScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_start = screens[3];
|
||||
wipe_scr_start = vid.screens[3];
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
#endif
|
||||
}
|
||||
@@ -330,7 +330,7 @@ void F_WipeEndScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_end = screens[4];
|
||||
wipe_scr_end = vid.screens[4];
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
|
||||
#endif
|
||||
@@ -353,7 +353,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
wipe_scr = screens[0];
|
||||
wipe_scr = vid.screens[0];
|
||||
|
||||
// lastwipetic should either be 0 or the tic we last wiped
|
||||
// on for fade-to-black
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
#ifndef __FILESRCH_H__
|
||||
#define __FILESRCH_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
@@ -96,4 +100,8 @@ void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth, boolean replayhut);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __G_GAME__
|
||||
#define __G_GAME__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
@@ -484,4 +488,8 @@ void G_AddMapToBuffer(INT16 map);
|
||||
|
||||
void G_FixCamera(UINT8 view);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -129,7 +129,6 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int comparePolygons(const void *p1, const void *p2)
|
||||
{
|
||||
const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
@@ -378,8 +377,8 @@ void HWR_RenderBatches(void)
|
||||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
|
||||
{
|
||||
changeState = true;
|
||||
|
||||
@@ -96,12 +96,12 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
||||
pdupx = pdupy = 2.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.smalldupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.smalldupy*FRACUNIT);
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+11
-29
@@ -548,7 +548,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
size_t len;
|
||||
|
||||
float tempxsow, tempytow;
|
||||
float scrollx = 0.0f, scrolly = 0.0f;
|
||||
float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f;
|
||||
angle_t angle = 0;
|
||||
|
||||
static FOutVector *planeVerts = NULL;
|
||||
@@ -668,14 +668,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
|
||||
if (angle) // Only needs to be done if there's an altered angle
|
||||
{
|
||||
angle = InvAngle(angle)>>ANGLETOFINESHIFT;
|
||||
|
||||
// This needs to be done so everything aligns after rotation
|
||||
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
|
||||
tempxsow = FloatToFixed(flatxref);
|
||||
tempytow = FloatToFixed(flatyref);
|
||||
flatxref = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
|
||||
flatyref = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
|
||||
tempxsow = flatxref;
|
||||
tempytow = flatyref;
|
||||
anglef = ANG2RAD(InvAngle(angle));
|
||||
flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
|
||||
flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
|
||||
}
|
||||
|
||||
#define SETUP3DVERT(vert, vx, vy) {\
|
||||
@@ -686,10 +683,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
||||
/* Need to rotate before translate */\
|
||||
if (angle) /* Only needs to be done if there's an altered angle */\
|
||||
{\
|
||||
tempxsow = FloatToFixed(vert->s);\
|
||||
tempytow = FloatToFixed(vert->t);\
|
||||
vert->s = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
|
||||
vert->t = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
|
||||
tempxsow = vert->s;\
|
||||
tempytow = vert->t;\
|
||||
vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\
|
||||
vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\
|
||||
}\
|
||||
\
|
||||
vert->x = (vx);\
|
||||
@@ -5567,28 +5564,12 @@ static void HWR_RenderFrame(player_t *player, boolean skybox)
|
||||
gl_viewwindowx += gl_viewwidth;
|
||||
}
|
||||
|
||||
if (splitscreen == 2 && player == &players[displayplayers[2]])
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *gpatch = W_CachePatchName("SRB2BACK", PU_PATCH);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = (gpatch->width * dupz), ph = (gpatch->height * dupz);
|
||||
|
||||
for (x = vid.width >> 1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height >> 1; y < vid.height; y += ph)
|
||||
HWR_DrawStretchyFixedPatch(gpatch, (x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, FRACUNIT, V_NOSCALESTART, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// Clear view, set viewport (glViewport), set perspective...
|
||||
HWR_ClearView();
|
||||
|
||||
ST_doPaletteStuff();
|
||||
|
||||
// Draw the sky background.
|
||||
HWR_DrawSkyBackground();
|
||||
if (skybox)
|
||||
@@ -5745,6 +5726,7 @@ void HWR_LoadLevel(boolean reloadinggamestate)
|
||||
static void HWR_TogglePaletteRendering(void)
|
||||
{
|
||||
V_ResetPaletteCVars(); // dont carry over changed palettes
|
||||
ST_ResetPaletteStuff();
|
||||
|
||||
// which state should we go to?
|
||||
if (HWR_ShouldUsePaletteRendering())
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
|
||||
#define GLENCORE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Startup & Shutdown the hardware mode renderer
|
||||
void HWR_Startup(void);
|
||||
void HWR_Shutdown(void);
|
||||
@@ -228,4 +232,8 @@ FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void)
|
||||
return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering());
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}// extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef _HW_MD2_H_
|
||||
#define _HW_MD2_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_model.h"
|
||||
|
||||
@@ -46,4 +50,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr);
|
||||
void HWR_AddPlayerMD2(INT32 skin, boolean local);
|
||||
void HWR_AddSpriteMD2(size_t spritenum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _HW_MD2_H_
|
||||
@@ -66,6 +66,7 @@ void HWR_FreePortalList(gl_portallist_t freelist)
|
||||
|
||||
// free memory from portal list allocated by calls to Add2Lines
|
||||
gl_portal_t *gl_portal_temp = freelist.base;
|
||||
|
||||
while (gl_portal_temp)
|
||||
{
|
||||
gl_portal_t *nextportal = gl_portal_temp->next;
|
||||
@@ -125,8 +126,7 @@ void HWR_PortalFrame(gl_portal_t* portal)
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
portalclipline = &lines[portal->clipline];
|
||||
portalcullsector = portalclipline->frontsector;
|
||||
viewsector = portalclipline->frontsector;
|
||||
portalcullsector = viewsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_JOY_H__
|
||||
#define __I_JOY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "g_input.h"
|
||||
|
||||
/*!
|
||||
@@ -55,4 +59,8 @@ typedef struct JoyType_s JoyType_t;
|
||||
|
||||
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_JOY_H__
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_NET__
|
||||
#define __I_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
@@ -180,4 +184,8 @@ extern bannednode_t *bannednode;
|
||||
/// \brief Called by D_SRB2Main to be defined by extern network driver
|
||||
boolean I_InitNetwork(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_SOUND__
|
||||
#define __I_SOUND__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "sounds.h"
|
||||
#include "command.h"
|
||||
@@ -241,4 +245,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeOutStopSong(UINT32 ms);
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_SYSTEM__
|
||||
#define __I_SYSTEM__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_event.h"
|
||||
|
||||
@@ -256,4 +260,8 @@ const char *I_ClipboardPaste(void);
|
||||
|
||||
void I_RegisterSysCommands(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef I_THREADS_H
|
||||
#define I_THREADS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*I_thread_fn)(void *userdata);
|
||||
|
||||
typedef void * I_mutex;
|
||||
@@ -35,5 +39,9 @@ void I_hold_cond (I_cond *, I_mutex);
|
||||
void I_wake_one_cond (I_cond *);
|
||||
void I_wake_all_cond (I_cond *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif/*I_THREADS_H*/
|
||||
#endif/*HAVE_THREADS*/
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_VIDEO__
|
||||
#define __I_VIDEO__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
@@ -149,4 +153,8 @@ boolean UseScreenFBO(void);
|
||||
extern boolean downsample;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,10 @@
|
||||
#ifndef __K_KART__
|
||||
#define __K_KART__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h" // Need for player_t
|
||||
|
||||
@@ -132,5 +136,9 @@ INT32 K_getMinimapTrans(void);
|
||||
void K_getLapsDrawinfo(drawinfo_t *out);
|
||||
void K_getMinimapDrawinfo(drawinfo_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// =========================================================================
|
||||
#endif // __K_KART__
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "p_slopes.h" // P_GetZAt
|
||||
#include "z_zone.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "doomstat.h"
|
||||
#include "p_mobj.h"
|
||||
#include "g_game.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "b_bot.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_main.h"
|
||||
#include "p_local.h"
|
||||
#include "g_game.h"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "p_mobj.h"
|
||||
#include "d_player.h"
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "sounds.h"
|
||||
|
||||
@@ -277,4 +278,4 @@ int LUA_SkinLib(lua_State *L)
|
||||
lua_setglobal(L, "skins");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -495,7 +495,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
||||
static void GIF_framewrite(void)
|
||||
{
|
||||
UINT8 *p;
|
||||
UINT8 *movie_screen = screens[2];
|
||||
UINT8 *movie_screen = vid.screens[2];
|
||||
INT32 blitx, blity, blitw, blith;
|
||||
|
||||
if (!gifframe_data)
|
||||
@@ -509,7 +509,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_optimize && gif_frames > 0)
|
||||
{
|
||||
// before blit movie_screen points to last frame, cur_screen points to this frame
|
||||
UINT8 *cur_screen = screens[0];
|
||||
UINT8 *cur_screen = vid.screens[0];
|
||||
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
|
||||
|
||||
// blit to temp screen
|
||||
@@ -535,7 +535,7 @@ static void GIF_framewrite(void)
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
GIF_rgbconvert(linear, screens[0]);
|
||||
GIF_rgbconvert(linear, vid.screens[0]);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
@@ -545,7 +545,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_frames == 0 && rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen);
|
||||
|
||||
movie_screen = screens[0];
|
||||
movie_screen = vid.screens[0];
|
||||
}
|
||||
|
||||
// screen regions are handled in GIF_lzw
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __M_ARGV__
|
||||
#define __M_ARGV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
@@ -42,4 +46,8 @@ const char *M_GetNextParm(void);
|
||||
// Finds and loads a response file (@moreargs.txt)
|
||||
void M_FindResponseFile(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__M_ARGV__
|
||||
@@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief convert fixed_t into double-precision floating number
|
||||
*/
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x)
|
||||
{
|
||||
return x / (double)FRACUNIT;
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f)
|
||||
{
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
// for backwards compat
|
||||
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
|
||||
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#ifndef __X_MENU__
|
||||
#define __X_MENU__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_skins.h"
|
||||
#include "d_event.h"
|
||||
#include "command.h"
|
||||
#include "i_threads.h"
|
||||
@@ -433,4 +438,8 @@ if (currentMenu == &menu)\
|
||||
}\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__X_MENU__
|
||||
+13
-4
@@ -14,6 +14,10 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
// Ignore "argument might be clobbered by longjmp" warning in GCC
|
||||
// (if libpng is compiled with setjmp error handling)
|
||||
@@ -1060,7 +1064,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
||||
png_init_io(apng_ptr, apng_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(apng_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(apng_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(apng_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1237,7 +1241,7 @@ void M_SaveFrame(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
@@ -1375,7 +1379,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
|
||||
png_init_io(png_ptr, png_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(png_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(png_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1539,7 +1543,7 @@ void M_DoScreenShot(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
|
||||
@@ -2210,3 +2214,8 @@ void M_MkdirEach(const char *path, int start, int mode)
|
||||
{
|
||||
M_MkdirEachUntil(path, start, -1, mode);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __M_MISC__
|
||||
#define __M_MISC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "tables.h"
|
||||
|
||||
@@ -116,4 +120,8 @@ FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
#include "w_wad.h"
|
||||
extern char configfile[MAX_WADPATH];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "p_setup.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_splats.h"
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_MOBJ__
|
||||
#define __P_MOBJ__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Basics.
|
||||
#include "tables.h"
|
||||
#include "m_fixed.h"
|
||||
@@ -536,4 +540,9 @@ extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
|
||||
extern INT32 numhuntemeralds;
|
||||
extern boolean runemeraldmanager;
|
||||
extern INT32 numstarposts;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_state.h"
|
||||
#include "r_skins.h"
|
||||
#include "w_wad.h"
|
||||
#include "y_inter.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
+30
-3
@@ -580,9 +580,6 @@ static void P_LoadRawSegs(UINT8 *data)
|
||||
else
|
||||
li->backsector = 0;
|
||||
|
||||
li->numlights = 0;
|
||||
li->rlights = NULL;
|
||||
|
||||
P_UpdateSegLightOffset(li);
|
||||
}
|
||||
}
|
||||
@@ -675,6 +672,21 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
@@ -720,6 +732,21 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_SETUP__
|
||||
#define __P_SETUP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_defs.h"
|
||||
@@ -48,6 +52,7 @@ typedef struct
|
||||
INT32 animseq; // start pos. in the anim sequence
|
||||
INT32 numpics;
|
||||
INT32 speed;
|
||||
boolean cyan;
|
||||
} levelflat_t;
|
||||
|
||||
extern size_t numlevelflats;
|
||||
@@ -116,4 +121,8 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
|
||||
UINT8 P_HasGrades(INT16 map, UINT8 mare);
|
||||
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,15 @@
|
||||
|
||||
#ifndef __QS22J__
|
||||
#define __QS22J__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void qs22j(void *base, size_t nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif
|
||||
+123
-189
@@ -35,6 +35,7 @@ sector_t *backsector;
|
||||
// very ugly realloc() of drawsegs at run-time, I upped it to 512
|
||||
// instead of 256.. and someone managed to send me a level with
|
||||
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
|
||||
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
|
||||
drawseg_t *drawsegs = NULL;
|
||||
drawseg_t *ds_p = NULL;
|
||||
|
||||
@@ -73,165 +74,96 @@ void R_ClearDrawSegs(void)
|
||||
ds_p = drawsegs;
|
||||
}
|
||||
|
||||
// Fix from boom.
|
||||
#define MAXSEGS (MAXVIDWIDTH/2+1)
|
||||
// CPhipps -
|
||||
// Instead of clipsegs, let's try using an array with one entry for each column,
|
||||
// indicating whether it's blocked by a solid wall yet or not.
|
||||
UINT8 *solidcol;
|
||||
|
||||
// newend is one past the last valid seg
|
||||
static cliprange_t *newend;
|
||||
static cliprange_t solidsegs[MAXSEGS];
|
||||
|
||||
//
|
||||
// R_ClipSolidWallSegment
|
||||
// Does handle solid walls,
|
||||
// e.g. single sided LineDefs (middle texture)
|
||||
// that entirely block the view.
|
||||
//
|
||||
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
|
||||
void R_AllocClipSegMemory(void)
|
||||
{
|
||||
cliprange_t *next;
|
||||
cliprange_t *start;
|
||||
solidcol = static_cast<UINT8*>(Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL));
|
||||
}
|
||||
|
||||
// Find the first range that touches the range (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
namespace
|
||||
{
|
||||
|
||||
if (first < start->first)
|
||||
enum class ClipType
|
||||
{
|
||||
// Does handle solid walls,
|
||||
// e.g. single sided LineDefs (middle texture)
|
||||
// that entirely block the view.
|
||||
kSolid,
|
||||
kSolidDontRender,
|
||||
|
||||
// Clips the given range of columns, but does not include it in the clip list.
|
||||
// Does handle windows, e.g. LineDefs with upper and lower texture.
|
||||
kPass,
|
||||
};
|
||||
|
||||
// CPhipps -
|
||||
// R_ClipWallSegment
|
||||
//
|
||||
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
|
||||
// columns which aren't solid, and updates the solidcol[] array appropriately
|
||||
template <ClipType Type>
|
||||
static void R_ClipWallSegment(int first, int last)
|
||||
{
|
||||
while (first < last)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start), so insert a new clippost.
|
||||
R_StoreWallRange(first, last);
|
||||
next = newend;
|
||||
newend++;
|
||||
// NO MORE CRASHING!
|
||||
if (newend - solidsegs > MAXSEGS)
|
||||
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
|
||||
UINT8 *p;
|
||||
|
||||
while (next != start)
|
||||
if (solidcol[first])
|
||||
{
|
||||
p = static_cast<UINT8*>(memchr(solidcol+first, 0, last-first));
|
||||
if (!p)
|
||||
return; // All solid
|
||||
|
||||
first = p - solidcol;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = static_cast<UINT8*>(memchr(solidcol+first, 1, last-first));
|
||||
|
||||
int to;
|
||||
if (!p)
|
||||
to = last;
|
||||
else
|
||||
to = p - solidcol;
|
||||
|
||||
if constexpr (Type != ClipType::kSolidDontRender)
|
||||
{
|
||||
*next = *(next-1);
|
||||
next--;
|
||||
R_StoreWallRange(first, to-1);
|
||||
}
|
||||
next->first = first;
|
||||
next->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
// Now adjust the clip size.
|
||||
start->first = first;
|
||||
}
|
||||
if constexpr (Type != ClipType::kPass)
|
||||
{
|
||||
memset(solidcol+first, 1, to-first);
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
next = start;
|
||||
while (last >= (next+1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
R_StoreWallRange(next->last + 1, (next+1)->first - 1);
|
||||
next++;
|
||||
|
||||
if (last <= next->last)
|
||||
{
|
||||
// Bottom is contained in next.
|
||||
// Adjust the clip size.
|
||||
start->last = next->last;
|
||||
goto crunch;
|
||||
first = to;
|
||||
}
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
R_StoreWallRange(next->last + 1, last);
|
||||
// Adjust the clip size.
|
||||
start->last = last;
|
||||
|
||||
// Remove start+1 to next from the clip list, because start now covers their area.
|
||||
crunch:
|
||||
if (next == start)
|
||||
return; // Post just extended past the bottom of one post.
|
||||
|
||||
while (next++ != newend)
|
||||
*++start = *next; // Remove a post.
|
||||
|
||||
newend = start + 1;
|
||||
|
||||
// NO MORE CRASHING!
|
||||
if (newend - solidsegs > MAXSEGS)
|
||||
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
|
||||
}
|
||||
|
||||
//
|
||||
// R_ClipPassWallSegment
|
||||
// Clips the given range of columns, but does not include it in the clip list.
|
||||
// Does handle windows, e.g. LineDefs with upper and lower texture.
|
||||
//
|
||||
static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender)
|
||||
{
|
||||
cliprange_t *start;
|
||||
|
||||
// Find the first range that touches the range
|
||||
// (adjacent pixels are touching).
|
||||
start = solidsegs;
|
||||
while (start->last < first - 1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first - 1)
|
||||
{
|
||||
// Post is entirely visible (above start).
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(first, start->first - 1);
|
||||
}
|
||||
|
||||
// Bottom contained in start?
|
||||
if (last <= start->last)
|
||||
return;
|
||||
|
||||
while (last >= (start+1)->first - 1)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(start->last + 1, (start+1)->first - 1);
|
||||
start++;
|
||||
|
||||
if (last <= start->last)
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
if (!soliddontrender)
|
||||
R_StoreWallRange(start->last + 1, last);
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
//
|
||||
// R_ClearClipSegs
|
||||
//
|
||||
void R_ClearClipSegs(void)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = -1;
|
||||
solidsegs[1].first = viewwidth;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs + 2;
|
||||
memset(solidcol, 0, viewwidth);
|
||||
}
|
||||
|
||||
void R_PortalClearClipSegs(INT32 start, INT32 end)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = start-1;
|
||||
solidsegs[1].first = end;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs + 2;
|
||||
R_ClearClipSegs();
|
||||
|
||||
if (start > 0)
|
||||
memset(solidcol, 1, start);
|
||||
|
||||
if (end < viewwidth)
|
||||
memset(solidcol + end, 1, viewwidth - end);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -389,6 +321,7 @@ static void R_AddLine(seg_t *line)
|
||||
INT32 x1, x2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
static sector_t tempsec;
|
||||
boolean bothfloorssky = false;
|
||||
|
||||
g_portal = NULL;
|
||||
|
||||
@@ -405,7 +338,7 @@ static void R_AddLine(seg_t *line)
|
||||
span = angle1 - angle2;
|
||||
|
||||
// Back side? i.e. backface culling?
|
||||
if (span >= ANGLE_180 || !line->linedef)
|
||||
if (span >= ANGLE_180)
|
||||
return;
|
||||
|
||||
// Global angle needed by segcalc.
|
||||
@@ -424,6 +357,7 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
angle1 = clipangle;
|
||||
}
|
||||
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > doubleclipangle)
|
||||
{
|
||||
@@ -439,6 +373,8 @@ static void R_AddLine(seg_t *line)
|
||||
// The seg is in the view range, but not necessarily visible.
|
||||
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
|
||||
// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
|
||||
x1 = viewangletox[angle1];
|
||||
x2 = viewangletox[angle2];
|
||||
|
||||
@@ -455,8 +391,10 @@ static void R_AddLine(seg_t *line)
|
||||
{
|
||||
// Find the other side!
|
||||
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1);
|
||||
|
||||
if (line->linedef == &lines[line2])
|
||||
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
|
||||
|
||||
if (line2 >= 0) // found it!
|
||||
{
|
||||
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
|
||||
@@ -476,6 +414,10 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
doorclosed = 0;
|
||||
|
||||
// likewise, but for floors and upper textures
|
||||
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum)
|
||||
bothfloorssky = true;
|
||||
|
||||
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
|
||||
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
|
||||
|
||||
@@ -503,19 +445,19 @@ static void R_AddLine(seg_t *line)
|
||||
if (viewsector != backsector && viewsector != frontsector)
|
||||
{
|
||||
// here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother.
|
||||
if (backc1 <= frontf1 && backc2 <= frontf2)
|
||||
const boolean ceillow = (backc1 <= frontf1 && backc2 <= frontf2);
|
||||
|
||||
// this tries to fix some skyboxes drawing a black void as a midtexture lel
|
||||
if (ceillow && (!bothfloorssky && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) // double sided with back ceiling sky but not front ceiling sky
|
||||
&& !line->sidedef->midtexture && !line->sidedef->bottomtexture && !line->sidedef->toptexture && !line->polyseg) // effectively empty
|
||||
{
|
||||
goto clipsolid;
|
||||
}
|
||||
|
||||
// here we're talking about floors higher than ceilings, don't even bother either.
|
||||
if (backf1 >= frontc1 && backf2 >= frontc2)
|
||||
{
|
||||
goto clipsolid;
|
||||
goto clippass;
|
||||
}
|
||||
|
||||
doorclosed = ceillow
|
||||
|| (backf1 >= frontc1 && backf2 >= frontc2)
|
||||
// Check for automap fix. Store in doorclosed for r_segs.c
|
||||
doorclosed = (backc1 <= backf1 && backc2 <= backf2
|
||||
|| (backc1 <= backf1 && backc2 <= backf2
|
||||
&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture)
|
||||
&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)
|
||||
&& (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum));
|
||||
@@ -540,15 +482,15 @@ static void R_AddLine(seg_t *line)
|
||||
|
||||
clippass:
|
||||
g_walloffscreen = false;
|
||||
R_ClipPassWallSegment(x1, x2 - 1, false);
|
||||
R_ClipWallSegment<ClipType::kPass>(x1, x2);
|
||||
|
||||
if (g_walloffscreen)
|
||||
R_ClipPassWallSegment(x1, x2 - 1, true);
|
||||
R_ClipWallSegment<ClipType::kSolidDontRender>(x1, x2);
|
||||
return;
|
||||
|
||||
clipsolid:
|
||||
g_walloffscreen = false;
|
||||
R_ClipSolidWallSegment(x1, x2 - 1);
|
||||
R_ClipWallSegment<ClipType::kSolid>(x1, x2);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -581,22 +523,11 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
angle_t angle1, angle2;
|
||||
INT32 sx1, sx2, boxpos;
|
||||
const INT32* check;
|
||||
cliprange_t *start;
|
||||
|
||||
// Find the corners of the box that define the edges from current viewpoint.
|
||||
if (viewx <= bspcoord[BOXLEFT])
|
||||
boxpos = 0;
|
||||
else if (viewx < bspcoord[BOXRIGHT])
|
||||
boxpos = 1;
|
||||
else
|
||||
boxpos = 2;
|
||||
|
||||
if (viewy >= bspcoord[BOXTOP])
|
||||
boxpos |= 0;
|
||||
else if (viewy > bspcoord[BOXBOTTOM])
|
||||
boxpos |= 1<<2;
|
||||
else
|
||||
boxpos |= 2<<2;
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) +
|
||||
(viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8);
|
||||
|
||||
if (boxpos == 5)
|
||||
return true;
|
||||
@@ -607,18 +538,23 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
angle1 = R_PointToAngle64(bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
|
||||
angle2 = R_PointToAngle64(bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
|
||||
|
||||
if ((signed)angle1 < (signed)angle2)
|
||||
// cph - replaced old code, which was unclear and badly commented
|
||||
// Much more efficient code now
|
||||
if ((signed)angle1 < (signed)angle2) /* it's "behind" us */
|
||||
{
|
||||
/* Either angle1 or angle2 is behind us, so it doesn't matter if we
|
||||
* change it to the corect sign
|
||||
*/
|
||||
if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
|
||||
angle1 = ANGLE_180-1;
|
||||
else
|
||||
angle2 = ANGLE_180;
|
||||
}
|
||||
|
||||
if ((signed)angle2 >= (signed)clipangle) return false;
|
||||
if ((signed)angle1 <= -(signed)clipangle) return false;
|
||||
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
|
||||
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
|
||||
if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge
|
||||
if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge
|
||||
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge
|
||||
if ((signed)angle2 <= -(signed)clipangle) angle2 = -(signed)clipangle; // Clip at right edge
|
||||
|
||||
// Find the first clippost that touches the source post (adjacent pixels are touching).
|
||||
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
|
||||
@@ -630,20 +566,18 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||
if (sx1 >= sx2)
|
||||
return false;
|
||||
|
||||
start = solidsegs;
|
||||
while (start->last < sx2)
|
||||
start++;
|
||||
|
||||
if (sx1 >= start->first && sx2 <= start->last)
|
||||
return false; // The clippost contains the new span.
|
||||
if (!memchr(solidcol+sx1, 0, sx2-sx1))
|
||||
{
|
||||
// All columns it covers are already solidly covered
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t numpolys; // number of polyobjects in current subsector
|
||||
size_t num_po_ptrs; // number of polyobject pointers allocated
|
||||
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
|
||||
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
|
||||
|
||||
//
|
||||
// R_PolyobjCompare
|
||||
@@ -681,8 +615,7 @@ void R_SortPolyObjects(subsector_t *sub)
|
||||
{
|
||||
// use free instead realloc since faster (thanks Lee ^_^)
|
||||
free(po_ptrs);
|
||||
po_ptrs = malloc((num_po_ptrs = numpolys*2)
|
||||
* sizeof(*po_ptrs));
|
||||
po_ptrs = static_cast<polyobj_t**>(malloc((num_po_ptrs = numpolys*2)* sizeof(*po_ptrs)));
|
||||
}
|
||||
|
||||
po = sub->polyList;
|
||||
@@ -699,8 +632,7 @@ void R_SortPolyObjects(subsector_t *sub)
|
||||
// 03/10/06: only bother if there are actually polys to sort
|
||||
if (numpolys >= 2)
|
||||
{
|
||||
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *),
|
||||
R_PolyobjCompare);
|
||||
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *), R_PolyobjCompare);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -726,8 +658,8 @@ static int R_PolysegCompare(const void *p1, const void *p2)
|
||||
dist2v1 = vxdist(seg2->v1);
|
||||
dist2v2 = vxdist(seg2->v2);
|
||||
|
||||
if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
|
||||
return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);
|
||||
if (std::min(dist1v1, dist1v2) != std::min(dist2v1, dist2v2))
|
||||
return std::min(dist1v1, dist1v2) - std::min(dist2v1, dist2v2);
|
||||
|
||||
{ // That didn't work, so now let's try this.......
|
||||
fixed_t delta1, delta2, x1, y1, x2, y2;
|
||||
@@ -828,14 +760,15 @@ static void R_Subsector(size_t num)
|
||||
fixed_t floorcenterz, ceilingcenterz;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
|
||||
#endif
|
||||
|
||||
// subsectors added at run-time
|
||||
if (num >= numsubsectors)
|
||||
{
|
||||
#ifdef RANGECHECK
|
||||
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
sub = &subsectors[num];
|
||||
frontsector = sub->sector;
|
||||
@@ -1144,7 +1077,7 @@ void R_Prep3DFloors(sector_t *sector)
|
||||
if (count != sector->numlights)
|
||||
{
|
||||
Z_Free(sector->lightlist);
|
||||
sector->lightlist = Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL);
|
||||
sector->lightlist = static_cast<lightlist_t*>(Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL));
|
||||
sector->numlights = count;
|
||||
}
|
||||
else
|
||||
@@ -1194,6 +1127,7 @@ void R_Prep3DFloors(sector_t *sector)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!best)
|
||||
{
|
||||
sector->numlights = i;
|
||||
+12
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_BSP__
|
||||
#define __R_BSP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
@@ -32,14 +36,17 @@ extern portal_t *g_portal; // is curline a portal seg?
|
||||
|
||||
extern INT32 checkcoord[12][4];
|
||||
|
||||
extern drawseg_t *curdrawsegs;
|
||||
extern drawseg_t *drawsegs;
|
||||
extern drawseg_t *ds_p;
|
||||
extern INT32 doorclosed;
|
||||
extern UINT8 *solidcol;
|
||||
extern boolean g_walloffscreen;
|
||||
|
||||
// BSP?
|
||||
void R_ClearClipSegs(void);
|
||||
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
||||
void R_AllocClipSegMemory(void);
|
||||
void R_ClearDrawSegs(void);
|
||||
void R_RenderBSPNode(INT32 bspnum);
|
||||
|
||||
@@ -59,4 +66,9 @@ boolean R_IsEmptyLine(seg_t *line, const sector_t *front, const sector_t *back);
|
||||
|
||||
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
|
||||
void R_Prep3DFloors(sector_t *sector);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+7
-3
@@ -100,7 +100,7 @@ INT32 numtextures = 0; // total number of textures found,
|
||||
|
||||
texture_t **textures = NULL;
|
||||
static UINT32 **texturecolumnofs; // column offset lookup table for each texture
|
||||
static UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
|
||||
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
|
||||
INT32 *texturewidthmask;
|
||||
@@ -296,7 +296,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
|
||||
// This is not optimised, but it's supposed to be executed only once
|
||||
// per level, when enough memory is available.
|
||||
//
|
||||
static UINT8 *R_GenerateTexture(size_t texnum)
|
||||
UINT8 *R_GenerateTexture(size_t texnum)
|
||||
{
|
||||
UINT8 *block;
|
||||
UINT8 *blocktex;
|
||||
@@ -649,6 +649,7 @@ void R_LoadTextures(void)
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
texture->type = TEXTURETYPE_SINGLEPATCH;
|
||||
texture->patchcount = 1;
|
||||
texture->holes = false;
|
||||
|
||||
@@ -915,19 +916,22 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
|
||||
|
||||
// Left Curly Brace
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
if (texturesToken == NULL)
|
||||
{
|
||||
I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName);
|
||||
}
|
||||
|
||||
if (strcmp(texturesToken,"{")==0)
|
||||
{
|
||||
if (actuallyLoadTexture)
|
||||
{
|
||||
// Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily.
|
||||
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL);
|
||||
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t), PU_STATIC, NULL);
|
||||
M_Memcpy(resultTexture->name, newTextureName, 8);
|
||||
resultTexture->width = newTextureWidth;
|
||||
resultTexture->height = newTextureHeight;
|
||||
resultTexture->type = TEXTURETYPE_COMPOSITE;
|
||||
}
|
||||
Z_Free(texturesToken);
|
||||
texturesToken = M_GetToken(NULL);
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_DATA__
|
||||
#define __R_DATA__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
|
||||
@@ -33,6 +37,14 @@ typedef struct
|
||||
UINT16 wad, lump;
|
||||
} texpatch_t;
|
||||
|
||||
// texture type
|
||||
enum
|
||||
{
|
||||
TEXTURETYPE_UNKNOWN,
|
||||
TEXTURETYPE_SINGLEPATCH,
|
||||
TEXTURETYPE_COMPOSITE,
|
||||
};
|
||||
|
||||
// A maptexturedef_t describes a rectangular texture,
|
||||
// which is composed of one or more mappatch_t structures
|
||||
// that arrange graphic patches.
|
||||
@@ -40,6 +52,7 @@ typedef struct
|
||||
{
|
||||
// Keep name for switch changing, etc.
|
||||
char name[8];
|
||||
UINT8 type; // TEXTURETYPE_
|
||||
INT16 width, height;
|
||||
boolean holes;
|
||||
|
||||
@@ -50,6 +63,7 @@ typedef struct
|
||||
|
||||
// all loaded and prepared textures from the start of the game
|
||||
extern texture_t **textures;
|
||||
extern UINT8 **texturecache; // graphics data for each generated full-size texture
|
||||
|
||||
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
|
||||
extern INT32 *texturewidthmask;
|
||||
@@ -68,6 +82,8 @@ extern CV_PossibleValue_t Color_cons_t[];
|
||||
void R_LoadTextures(void);
|
||||
void R_FlushTextureCache(void);
|
||||
|
||||
UINT8 *R_GenerateTexture(size_t texnum);
|
||||
|
||||
INT32 R_GetTextureNum(INT32 texnum);
|
||||
void R_CheckTextureCache(INT32 tex);
|
||||
|
||||
@@ -108,4 +124,8 @@ UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
|
||||
|
||||
extern INT32 numtextures;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+33
-5
@@ -68,6 +68,37 @@ typedef struct
|
||||
#endif
|
||||
} extracolormap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lighttable_t* colormap;
|
||||
|
||||
INT32 x;
|
||||
INT32 yl;
|
||||
INT32 yh;
|
||||
fixed_t iscale;
|
||||
fixed_t texturemid;
|
||||
|
||||
UINT8* source; // first pixel in a column
|
||||
UINT8* lightmap; // lighting only
|
||||
|
||||
// translucency stuff here
|
||||
UINT8* transmap;
|
||||
|
||||
// translation stuff here
|
||||
UINT8* translation;
|
||||
|
||||
struct r_lightlist_s* lightlist;
|
||||
|
||||
INT32 numlights;
|
||||
INT32 maxlights;
|
||||
|
||||
//Fix TUTIFRUTI
|
||||
INT32 texheight;
|
||||
INT32 sourcelength;
|
||||
} drawcolumndata_t;
|
||||
|
||||
extern drawcolumndata_t g_dc;
|
||||
|
||||
//
|
||||
// INTERNAL MAP TYPES used by play and refresh
|
||||
//
|
||||
@@ -527,9 +558,6 @@ typedef struct seg_s
|
||||
float flength; // length of the seg, used by hardware renderer
|
||||
#endif
|
||||
|
||||
// Why slow things down by calculating lightlists for every thick side?
|
||||
size_t numlights;
|
||||
r_lightlist_t *rlights;
|
||||
polyobj_t *polyseg;
|
||||
boolean dontrenderme;
|
||||
|
||||
@@ -610,11 +638,11 @@ typedef struct drawseg_s
|
||||
struct ffloor_s *thicksides[MAXFFLOORS];
|
||||
INT16 *thicksidecol;
|
||||
INT32 numthicksides;
|
||||
fixed_t frontscale[MAXVIDWIDTH];
|
||||
fixed_t *frontscale;
|
||||
|
||||
UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping
|
||||
|
||||
fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures
|
||||
fixed_t *maskedtextureheight; // For handling sloped midtextures
|
||||
|
||||
vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes
|
||||
} drawseg_t;
|
||||
|
||||
+89
-200
@@ -15,6 +15,8 @@
|
||||
/// not the architecture of the frame buffer.
|
||||
/// The frame buffer is a linear one, and we need only the base address.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_local.h"
|
||||
@@ -38,47 +40,14 @@
|
||||
|
||||
/** \brief view info
|
||||
*/
|
||||
INT32 viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
|
||||
/** \brief pointer to the start of each line of the screen,
|
||||
*/
|
||||
UINT8 *ylookup[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view1 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup1[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view2 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup2[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view3 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup3[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief pointer to the start of each line of the screen, for view4 (splitscreen)
|
||||
*/
|
||||
UINT8 *ylookup4[MAXVIDHEIGHT*4];
|
||||
|
||||
/** \brief x byte offset for columns inside the viewwindow,
|
||||
so the first column starts at (SCRWIDTH - VIEWWIDTH)/2
|
||||
*/
|
||||
INT32 columnofs[MAXVIDWIDTH*4];
|
||||
|
||||
UINT8 *topleft;
|
||||
INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
UINT8 *renderscreen; // haleyjd
|
||||
|
||||
// =========================================================================
|
||||
// COLUMN DRAWING CODE STUFF
|
||||
// =========================================================================
|
||||
|
||||
lighttable_t *dc_colormap;
|
||||
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
|
||||
|
||||
fixed_t dc_iscale, dc_texturemid;
|
||||
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
|
||||
// soo lets make it a byte on all system for the ASM code
|
||||
UINT8 *dc_source;
|
||||
INT32 dc_sourcelength;
|
||||
drawcolumndata_t g_dc;
|
||||
|
||||
// -----------------------
|
||||
// translucency stuff here
|
||||
@@ -88,42 +57,34 @@ INT32 dc_sourcelength;
|
||||
UINT8 *transtables; // translucency tables
|
||||
UINT8 *blendtables[NUMBLENDMAPS];
|
||||
|
||||
/** \brief R_DrawTransColumn uses this
|
||||
*/
|
||||
UINT8 *dc_transmap; // one of the translucency tables
|
||||
// --------------------------------------------
|
||||
// c drawer routines
|
||||
// --------------------------------------------
|
||||
|
||||
// ----------------------
|
||||
// translation stuff here
|
||||
// ----------------------
|
||||
|
||||
|
||||
/** \brief R_DrawTranslatedColumn uses this
|
||||
*/
|
||||
UINT8 *dc_translation;
|
||||
|
||||
struct r_lightlist_s *dc_lightlist = NULL;
|
||||
INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
|
||||
coldrawfunc_t *colfunc;
|
||||
coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
|
||||
int colfunctype;
|
||||
|
||||
// =========================================================================
|
||||
// SPAN DRAWING CODE STUFF
|
||||
// =========================================================================
|
||||
|
||||
INT32 ds_y, ds_x1, ds_x2;
|
||||
lighttable_t *ds_colormap;
|
||||
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
|
||||
UINT8 *ds_source; // points to the start of a flat
|
||||
UINT8 *ds_transmap; // one of the translucency tables
|
||||
drawspandata_t g_ds;
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
floatv3_t *ds_su, *ds_sv, *ds_sz;
|
||||
floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
||||
float focallengthf, zeroheight;
|
||||
|
||||
/** \brief Variable flat sizes
|
||||
*/
|
||||
float focallengthf;
|
||||
|
||||
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
||||
// For, uh, tilted lighting, duh.
|
||||
//static INT32 *tiltlighting;
|
||||
|
||||
// --------------------------------------------
|
||||
// c drawer routines
|
||||
// --------------------------------------------
|
||||
|
||||
spandrawfunc_t *spanfunc;
|
||||
spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
|
||||
|
||||
// ==========================================================================
|
||||
// OLD DOOM FUZZY EFFECT
|
||||
@@ -147,73 +108,10 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
||||
static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL};
|
||||
static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL};
|
||||
|
||||
|
||||
// See also the enum skincolors_t
|
||||
// TODO Callum: Can this be translated?
|
||||
/*
|
||||
const char *Color_Names[MAXSKINCOLORS] =
|
||||
{
|
||||
"None", // SKINCOLOR_NONE
|
||||
"White", // SKINCOLOR_WHITE
|
||||
"Silver", // SKINCOLOR_SILVER
|
||||
"Grey", // SKINCOLOR_GREY
|
||||
"Black", // SKINCOLOR_BLACK
|
||||
"Cyan", // SKINCOLOR_CYAN
|
||||
"Teal", // SKINCOLOR_TEAL
|
||||
"Steel_Blue",// SKINCOLOR_STEEL
|
||||
"Blue", // SKINCOLOR_BLUE
|
||||
"Peach", // SKINCOLOR_PEACH
|
||||
"Tan", // SKINCOLOR_TAN
|
||||
"Pink", // SKINCOLOR_PINK
|
||||
"Lavender", // SKINCOLOR_LAVENDER
|
||||
"Purple", // SKINCOLOR_PURPLE
|
||||
"Orange", // SKINCOLOR_ORANGE
|
||||
"Rosewood", // SKINCOLOR_ROSEWOOD
|
||||
"Beige", // SKINCOLOR_BEIGE
|
||||
"Brown", // SKINCOLOR_BROWN
|
||||
"Red", // SKINCOLOR_RED
|
||||
"Dark_Red", // SKINCOLOR_DARKRED
|
||||
"Neon_Green",// SKINCOLOR_NEONGREEN
|
||||
"Green", // SKINCOLOR_GREEN
|
||||
"Zim", // SKINCOLOR_ZIM
|
||||
"Olive", // SKINCOLOR_OLIVE
|
||||
"Yellow", // SKINCOLOR_YELLOW
|
||||
"Gold" // SKINCOLOR_GOLD
|
||||
};
|
||||
|
||||
const UINT8 Color_Opposite[MAXSKINCOLORS*2] =
|
||||
{
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_NONE
|
||||
SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE
|
||||
SKINCOLOR_GREY,4, // SKINCOLOR_SILVER
|
||||
SKINCOLOR_SILVER,12,// SKINCOLOR_GREY
|
||||
SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_CYAN
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_TEAL
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_STEEL
|
||||
SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PEACH
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_TAN
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PINK
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_LAVENDER
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_PURPLE
|
||||
SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_ROSEWOOD
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_BEIGE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_BROWN
|
||||
SKINCOLOR_GREEN,5, // SKINCOLOR_RED
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_DARKRED
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_NEONGREEN
|
||||
SKINCOLOR_RED,11, // SKINCOLOR_GREEN
|
||||
SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_OLIVE
|
||||
SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW
|
||||
SKINCOLOR_NONE,8 // SKINCOLOR_GOLD
|
||||
};
|
||||
*/
|
||||
|
||||
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
|
||||
|
||||
static void R_GenerateBlendTables(void);
|
||||
|
||||
/** \brief Initializes the translucency tables used by the Software renderer.
|
||||
*/
|
||||
void R_InitTranslucencyTables(void)
|
||||
@@ -221,8 +119,7 @@ void R_InitTranslucencyTables(void)
|
||||
// Load here the transparency lookup tables 'TRANSx0'
|
||||
// NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm
|
||||
// optimised code (in other words, transtables pointer low word is 0)
|
||||
transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC,
|
||||
NULL, 16);
|
||||
transtables = static_cast<UINT8*>(Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16));
|
||||
|
||||
W_ReadLump(W_GetNumForName("TRANS10"), transtables);
|
||||
W_ReadLump(W_GetNumForName("TRANS20"), transtables+0x10000);
|
||||
@@ -283,10 +180,10 @@ static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt)
|
||||
RGBA_t frontrgba = V_GetColor(fg);
|
||||
RGBA_t result;
|
||||
|
||||
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
|
||||
result.s.red = max(0, result.s.red - blendamt);
|
||||
result.s.green = max(0, result.s.green - blendamt);
|
||||
result.s.blue = max(0, result.s.blue - blendamt);
|
||||
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
|
||||
result.s.red = std::max(0, result.s.red - blendamt);
|
||||
result.s.green = std::max(0, result.s.green - blendamt);
|
||||
result.s.blue = std::max(0, result.s.blue - blendamt);
|
||||
|
||||
table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue);
|
||||
}
|
||||
@@ -339,17 +236,17 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8
|
||||
for (; i < num; i++)
|
||||
{
|
||||
const size_t offs = (0x10000 * i);
|
||||
const UINT16 alpha = min(amtmul * i, 0xFF);
|
||||
const UINT16 alpha = std::fmin(amtmul * i, 0xFF);
|
||||
genfunc(blendtables[tab] + offs, style, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void R_GenerateBlendTables(void)
|
||||
static void R_GenerateBlendTables(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < NUMBLENDMAPS; i++)
|
||||
blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16);
|
||||
blendtables[i] = static_cast<UINT8*>(Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16));
|
||||
|
||||
InitColorLUT(&transtab_lut, pLocalPalette, false);
|
||||
|
||||
@@ -370,8 +267,8 @@ void R_GenerateBlendTables(void)
|
||||
BlendTab_Modulative(blendtables[blendtab_modulate]);
|
||||
}
|
||||
|
||||
#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
|
||||
#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0)
|
||||
#define ClipBlendLevel(style, trans) std::max(std::min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
|
||||
#define ClipTransLevel(trans) std::max(std::min((trans), NUMTRANSMAPS-2), 0)
|
||||
|
||||
UINT8 *R_GetTranslucencyTable(INT32 alphalevel)
|
||||
{
|
||||
@@ -458,7 +355,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
|
||||
{
|
||||
// Allocate table for skin if necessary
|
||||
if (!tt[skintableindex])
|
||||
tt[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL);
|
||||
tt[skintableindex] = static_cast<UINT8**>(Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL));
|
||||
|
||||
// Get colormap
|
||||
ret = tt[skintableindex][color];
|
||||
@@ -468,7 +365,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
|
||||
// Generate the colormap if necessary
|
||||
if (!ret)
|
||||
{
|
||||
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8);
|
||||
ret = static_cast<UINT8*>(Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8));
|
||||
K_GenerateKartColormap(ret, skinnum, color, local); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart
|
||||
|
||||
// Cache the colormap if desired
|
||||
@@ -540,19 +437,6 @@ void R_FlushTranslationColormapCache(void)
|
||||
memset(localtranslationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**));
|
||||
}
|
||||
|
||||
/*
|
||||
UINT8 R_GetColorByName(const char *name)
|
||||
{
|
||||
UINT8 color = (UINT8)atoi(name);
|
||||
if (color > 0 && color < MAXSKINCOLORS)
|
||||
return color;
|
||||
for (color = 1; color < MAXSKINCOLORS; color++)
|
||||
if (!stricmp(Color_Names[color], name))
|
||||
return color;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// ==========================================================================
|
||||
// COMMON DRAWER FOR 8 AND 16 BIT COLOR MODES
|
||||
// ==========================================================================
|
||||
@@ -572,39 +456,44 @@ UINT8 R_GetColorByName(const char *name)
|
||||
\param height hieght of buffer
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
|
||||
static void R_AllocViewMemory(void)
|
||||
{
|
||||
negonearray = static_cast<INT16*>(Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL));
|
||||
screenheightarray = static_cast<INT16*>(Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
floorclip = static_cast<INT16*>(Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL));
|
||||
ceilingclip = static_cast<INT16*>(Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
frontscale = static_cast<fixed_t*>(Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL));
|
||||
|
||||
xtoviewangle = static_cast<angle_t*>(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL));
|
||||
|
||||
R_AllocSegMemory();
|
||||
R_AllocClipSegMemory();
|
||||
R_AllocPlaneMemory();
|
||||
#ifdef FLOORSPLATS
|
||||
R_AllocFloorSpriteTables();
|
||||
#endif
|
||||
R_AllocVisSpriteMemory();
|
||||
}
|
||||
|
||||
|
||||
void R_InitViewBuffer(INT32 width, INT32 height)
|
||||
{
|
||||
INT32 i, bytesperpixel = vid.bpp;
|
||||
|
||||
if (width > MAXVIDWIDTH)
|
||||
width = MAXVIDWIDTH;
|
||||
if (height > MAXVIDHEIGHT)
|
||||
height = MAXVIDHEIGHT;
|
||||
if (bytesperpixel < 1 || bytesperpixel > 4)
|
||||
I_Error("R_InitViewBuffer: wrong bytesperpixel value %d\n", bytesperpixel);
|
||||
|
||||
R_AllocViewMemory();
|
||||
|
||||
viewwindowx = 0;
|
||||
viewwindowy = 0;
|
||||
|
||||
// Column offset for those columns of the view window, but relative to the entire screen
|
||||
for (i = 0; i < width; i++)
|
||||
columnofs[i] = (viewwindowx + i) * bytesperpixel;
|
||||
|
||||
// Precalculate all row offsets.
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
ylookup[i] = ylookup1[i] = screens[0] + i*vid.width*bytesperpixel;
|
||||
if (splitscreen == 1)
|
||||
ylookup2[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
|
||||
else
|
||||
ylookup2[i] = screens[0] + i*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
|
||||
ylookup3[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
|
||||
ylookup4[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
|
||||
}
|
||||
linesize = vid.width; // killough 11/98
|
||||
renderscreen = vid.screens[0]; // haleyjd 07/02/14
|
||||
}
|
||||
|
||||
/** \brief viewborder patches lump numbers
|
||||
@@ -626,6 +515,28 @@ void R_InitViewBorder(void)
|
||||
viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br");
|
||||
}
|
||||
|
||||
/** \brief The R_VideoErase function
|
||||
|
||||
Copy a screen buffer.
|
||||
|
||||
\param ofs offest from buffer
|
||||
\param count bytes to erase
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
void R_VideoErase(size_t ofs, INT32 count)
|
||||
{
|
||||
// LFB copy.
|
||||
// This might not be a good idea if memcpy
|
||||
// is not optimal, e.g. byte by byte on
|
||||
// a 32bit CPU, as GNU GCC/Linux libc did
|
||||
// at one point.
|
||||
M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/** \brief R_FillBackScreen
|
||||
|
||||
@@ -648,7 +559,7 @@ void R_FillBackScreen(void)
|
||||
return;
|
||||
|
||||
src = scr_borderpatch;
|
||||
dest = screens[1];
|
||||
dest = vid.screens[1];
|
||||
|
||||
for (y = 0; y < vid.height; y++)
|
||||
{
|
||||
@@ -699,30 +610,7 @@ void R_FillBackScreen(void)
|
||||
V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1,
|
||||
W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief The R_VideoErase function
|
||||
|
||||
Copy a screen buffer.
|
||||
|
||||
\param ofs offest from buffer
|
||||
\param count bytes to erase
|
||||
|
||||
\return void
|
||||
|
||||
|
||||
*/
|
||||
void R_VideoErase(size_t ofs, INT32 count)
|
||||
{
|
||||
// LFB copy.
|
||||
// This might not be a good idea if memcpy
|
||||
// is not optimal, e.g. byte by byte on
|
||||
// a 32bit CPU, as GNU GCC/Linux libc did
|
||||
// at one point.
|
||||
M_Memcpy(screens[0] + ofs, screens[1] + ofs, count);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** \brief The R_DrawViewBorder
|
||||
|
||||
Draws the border around the view
|
||||
@@ -766,13 +654,14 @@ void R_DrawViewBorder(void)
|
||||
side <<= 1;
|
||||
|
||||
// simpler using our VID_Blit routine
|
||||
VID_BlitLinearScreen(screens[1] + ofs, screens[0] + ofs, side, viewheight - 1,
|
||||
VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1,
|
||||
vid.width, vid.width);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
// INCLUDE 8bpp DRAWING CODE HERE
|
||||
// INCLUDE DRAWING CODE HERE
|
||||
// ==========================================================================
|
||||
|
||||
#include "r_draw8.c"
|
||||
#include "r_draw_column.cpp"
|
||||
#include "r_draw_span.cpp"
|
||||
+155
-74
@@ -14,72 +14,143 @@
|
||||
#ifndef __R_DRAW__
|
||||
#define __R_DRAW__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_defs.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
|
||||
// -------------------------------
|
||||
// COMMON STUFF FOR 8bpp AND 16bpp
|
||||
// -------------------------------
|
||||
extern UINT8 *ylookup[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup1[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup2[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup3[MAXVIDHEIGHT*4];
|
||||
extern UINT8 *ylookup4[MAXVIDHEIGHT*4];
|
||||
extern INT32 columnofs[MAXVIDWIDTH*4];
|
||||
extern UINT8 *topleft;
|
||||
extern UINT8 *renderscreen;
|
||||
extern INT32 linesize;
|
||||
|
||||
// -------------------------
|
||||
// COLUMN DRAWING CODE STUFF
|
||||
// -------------------------
|
||||
FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py)
|
||||
{
|
||||
return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px);
|
||||
}
|
||||
|
||||
extern lighttable_t *dc_colormap;
|
||||
extern INT32 dc_x, dc_yl, dc_yh;
|
||||
extern fixed_t dc_iscale, dc_texturemid;
|
||||
extern UINT8 dc_hires;
|
||||
|
||||
extern UINT8 *dc_source; // first pixel in a column
|
||||
|
||||
// translucency stuff here
|
||||
extern UINT8 *dc_transmap;
|
||||
|
||||
// translation stuff here
|
||||
|
||||
extern UINT8 *dc_translation;
|
||||
|
||||
extern struct r_lightlist_s *dc_lightlist;
|
||||
extern INT32 dc_numlights, dc_maxlights;
|
||||
|
||||
//Fix TUTIFRUTI
|
||||
extern INT32 dc_texheight;
|
||||
|
||||
// -----------------------
|
||||
// SPAN DRAWING CODE STUFF
|
||||
// -----------------------
|
||||
|
||||
extern INT32 ds_y, ds_x1, ds_x2;
|
||||
extern lighttable_t *ds_colormap;
|
||||
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
|
||||
extern INT32 ds_waterofs, ds_bgofs;
|
||||
extern UINT8 *ds_source; // start of a 64*64 tile image
|
||||
extern INT32 dc_sourcelength;
|
||||
extern UINT8 *ds_transmap;
|
||||
|
||||
extern INT32 ds_bgofs;
|
||||
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} floatv3_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT32 y;
|
||||
INT32 x1;
|
||||
INT32 x2;
|
||||
lighttable_t* colormap;
|
||||
lighttable_t* translation;
|
||||
|
||||
fixed_t xfrac;
|
||||
fixed_t yfrac;
|
||||
fixed_t xstep;
|
||||
fixed_t ystep;
|
||||
INT32 waterofs;
|
||||
INT32 bgofs;
|
||||
|
||||
fixed_t xoffs;
|
||||
fixed_t yoffs;
|
||||
|
||||
visplane_t *currentplane;
|
||||
UINT8 *source;
|
||||
UINT8 *transmap;
|
||||
|
||||
float zeroheight;
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
floatv3_t sup;
|
||||
floatv3_t svp;
|
||||
floatv3_t szp;
|
||||
floatv3_t slope_origin;
|
||||
floatv3_t slope_u;
|
||||
floatv3_t slope_v;
|
||||
|
||||
// Variable flat sizes
|
||||
UINT32 nflatxshift;
|
||||
UINT32 nflatyshift;
|
||||
UINT32 nflatshiftup;
|
||||
UINT32 nflatmask;
|
||||
|
||||
fixed_t planeheight;
|
||||
lighttable_t **planezlight;
|
||||
|
||||
//
|
||||
// Water ripple effect
|
||||
// Needs the height of the plane, and the vertical position of the span.
|
||||
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
|
||||
//
|
||||
struct
|
||||
{
|
||||
INT32 offset;
|
||||
fixed_t xfrac, yfrac;
|
||||
boolean active;
|
||||
} planeripple;
|
||||
} drawspandata_t;
|
||||
|
||||
extern drawspandata_t g_ds;
|
||||
|
||||
// Draws a single visplane.
|
||||
void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel);
|
||||
|
||||
// Vectors for Software's tilted slope drawers
|
||||
extern floatv3_t *ds_su, *ds_sv, *ds_sz;
|
||||
extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
||||
extern float focallengthf, zeroheight;
|
||||
|
||||
// Variable flat sizes
|
||||
extern UINT32 nflatxshift;
|
||||
extern UINT32 nflatyshift;
|
||||
extern UINT32 nflatshiftup;
|
||||
extern UINT32 nflatmask;
|
||||
extern float focallengthf;
|
||||
|
||||
|
||||
typedef void (coldrawfunc_t)(drawcolumndata_t*);
|
||||
typedef void (spandrawfunc_t)(drawspandata_t*);
|
||||
|
||||
#define BASEDRAWFUNC 0
|
||||
|
||||
enum
|
||||
{
|
||||
COLDRAWFUNC_BASE = BASEDRAWFUNC,
|
||||
COLDRAWFUNC_FUZZY,
|
||||
COLDRAWFUNC_TRANS,
|
||||
COLDRAWFUNC_SHADOWED,
|
||||
COLDRAWFUNC_TRANSTRANS,
|
||||
COLDRAWFUNC_TWOSMULTIPATCH,
|
||||
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
|
||||
COLDRAWFUNC_FOG,
|
||||
|
||||
COLDRAWFUNC_MAX
|
||||
};
|
||||
|
||||
extern int colfunctype;
|
||||
extern coldrawfunc_t *colfunc;
|
||||
extern coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
|
||||
|
||||
enum
|
||||
{
|
||||
SPANDRAWFUNC_BASE = BASEDRAWFUNC,
|
||||
SPANDRAWFUNC_TRANS,
|
||||
SPANDRAWFUNC_TILTED,
|
||||
SPANDRAWFUNC_TILTEDTRANS,
|
||||
|
||||
SPANDRAWFUNC_SPLAT,
|
||||
SPANDRAWFUNC_TRANSSPLAT,
|
||||
SPANDRAWFUNC_TILTEDSPLAT,
|
||||
SPANDRAWFUNC_TILTEDTRANSSPLAT,
|
||||
|
||||
SPANDRAWFUNC_WATER,
|
||||
SPANDRAWFUNC_TILTEDWATER,
|
||||
|
||||
SPANDRAWFUNC_FOG,
|
||||
SPANDRAWFUNC_TILTEDFOG,
|
||||
|
||||
SPANDRAWFUNC_MAX
|
||||
};
|
||||
|
||||
extern spandrawfunc_t *spanfunc;
|
||||
extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
|
||||
|
||||
void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column);
|
||||
|
||||
/// \brief Top border
|
||||
#define BRDR_T 0
|
||||
@@ -138,7 +209,6 @@ enum
|
||||
extern UINT8 *blendtables[NUMBLENDMAPS];
|
||||
|
||||
void R_InitTranslucencyTables(void);
|
||||
void R_GenerateBlendTables(void);
|
||||
|
||||
UINT8 *R_GetTranslucencyTable(INT32 alphalevel);
|
||||
UINT8 *R_GetBlendTable(int style, INT32 alphalevel);
|
||||
@@ -161,33 +231,44 @@ void R_DrawViewBorder(void);
|
||||
#define TRANSPARENTPIXEL 247
|
||||
|
||||
// -----------------
|
||||
// 8bpp DRAWING CODE
|
||||
// DRAWING CODE
|
||||
// -----------------
|
||||
|
||||
void R_DrawColumn_8(void);
|
||||
#define R_DrawWallColumn_8 R_DrawColumn_8
|
||||
void R_DrawShadeColumn_8(void);
|
||||
void R_DrawTranslucentColumn_8(void);
|
||||
// column drawers
|
||||
void R_DrawColumn(drawcolumndata_t* dc);
|
||||
void R_DrawColumnShadowed(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawTranslatedColumn_8(void);
|
||||
void R_DrawTranslatedTranslucentColumn_8(void);
|
||||
void R_DrawSpan_8(void);
|
||||
void R_CalcTiltedLighting(fixed_t start, fixed_t end);
|
||||
void R_DrawTiltedSpan_8(void);
|
||||
void R_DrawTiltedTranslucentSpan_8(void);
|
||||
#ifndef NOWATER
|
||||
void R_DrawTiltedTranslucentWaterSpan_8(void);
|
||||
void R_DrawTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawTranslatedColumn(drawcolumndata_t* dc);
|
||||
void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc);
|
||||
void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc);
|
||||
|
||||
void R_DrawFogColumn(drawcolumndata_t* dc);
|
||||
|
||||
// span drawers
|
||||
void R_DrawSpan(drawspandata_t* ds);
|
||||
|
||||
void R_DrawSpan_Tilted(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds);
|
||||
void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds);
|
||||
|
||||
void R_DrawTranslucentSpan(drawspandata_t* ds);
|
||||
void R_DrawTranslucentWaterSpan(drawspandata_t* ds);
|
||||
|
||||
void R_DrawFogSpan(drawspandata_t* ds);
|
||||
void R_DrawFogSpan_Tilted(drawspandata_t* ds);
|
||||
|
||||
void R_DrawSplat_Tilted(drawspandata_t* ds);
|
||||
void R_DrawSplat(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSplat(drawspandata_t* ds);
|
||||
void R_DrawTranslucentSplat_Tilted(drawspandata_t* ds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
void R_DrawTiltedSplat_8(void);
|
||||
void R_DrawSplat_8(void);
|
||||
void R_DrawTranslucentSplat_8(void);
|
||||
void R_DrawTranslucentSpan_8(void);
|
||||
void R_DrawTranslucentWaterSpan_8(void);
|
||||
void R_Draw2sMultiPatchColumn_8(void);
|
||||
void R_Draw2sMultiPatchTranslucentColumn_8(void);
|
||||
void R_DrawFogSpan_8(void);
|
||||
void R_DrawFogColumn_8(void);
|
||||
void R_DrawColumnShadowed_8(void);
|
||||
|
||||
// =========================================================================
|
||||
#endif // __R_DRAW__
|
||||
-1814
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,356 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_draw_column.cpp
|
||||
/// \brief column drawer functions
|
||||
/// \note no includes because this is included as part of r_draw.cpp
|
||||
|
||||
// ==========================================================================
|
||||
// COLUMNS
|
||||
// ==========================================================================
|
||||
|
||||
// A column is a vertical slice/span of a wall texture that uses
|
||||
// a has a constant z depth from top to bottom.
|
||||
//
|
||||
|
||||
enum DrawColumnType
|
||||
{
|
||||
DC_BASIC = 0x0000,
|
||||
DC_COLORMAP = 0x0001,
|
||||
DC_TRANSMAP = 0x0002,
|
||||
DC_HOLES = 0x0004,
|
||||
DC_LIGHTLIST = 0x0008,
|
||||
};
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap)
|
||||
{
|
||||
if constexpr (Type & DrawColumnType::DC_COLORMAP)
|
||||
{
|
||||
col = dc->translation[col];
|
||||
}
|
||||
|
||||
return colormap[col];
|
||||
}
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap)
|
||||
{
|
||||
col = R_GetColumnTranslated<Type>(dc, col, colormap);
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_TRANSMAP)
|
||||
{
|
||||
return *(dc->transmap + (col << 8) + (*dest));
|
||||
}
|
||||
else
|
||||
{
|
||||
return col;
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawColumnType Type>
|
||||
static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const restrict UINT8 *source, const restrict UINT8 *colormap)
|
||||
{
|
||||
UINT8 col = source[bit];
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_HOLES)
|
||||
{
|
||||
if (col == TRANSPARENTPIXEL)
|
||||
{
|
||||
return *dest;
|
||||
}
|
||||
}
|
||||
|
||||
return R_GetColumnTranslucent<Type>(dc, dest, col, colormap);
|
||||
}
|
||||
|
||||
/** \brief The R_DrawColumn function
|
||||
Experiment to make software go faster. Taken from the Boom source
|
||||
*/
|
||||
template<DrawColumnType Type>
|
||||
static void R_DrawColumnTemplate(drawcolumndata_t *dc)
|
||||
{
|
||||
INT32 count;
|
||||
|
||||
count = dc->yh - dc->yl;
|
||||
|
||||
if (count < 0) // Zero length, column does not exceed a pixel.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (Type & DrawColumnType::DC_LIGHTLIST)
|
||||
{
|
||||
constexpr DrawColumnType NewType = static_cast<DrawColumnType>(Type & ~DC_LIGHTLIST);
|
||||
INT32 i, height, bheight = 0, solid = 0;
|
||||
drawcolumndata_t dc_copy = *dc;
|
||||
|
||||
const INT32 realyh = dc_copy.yh;
|
||||
|
||||
// This runs through the lightlist from top to bottom and cuts up the column accordingly.
|
||||
for (i = 0; i < dc_copy.numlights; i++)
|
||||
{
|
||||
// If the height of the light is above the column, get the colormap
|
||||
// anyway because the lighting of the top should be affected.
|
||||
solid = dc_copy.lightlist[i].flags & FF_CUTSOLIDS;
|
||||
height = dc_copy.lightlist[i].height >> LIGHTSCALESHIFT;
|
||||
|
||||
if (solid)
|
||||
{
|
||||
bheight = dc_copy.lightlist[i].botheight >> LIGHTSCALESHIFT;
|
||||
|
||||
if (bheight < height)
|
||||
{
|
||||
// confounded slopes sometimes allow partial invertedness,
|
||||
// even including cases where the top and bottom heights
|
||||
// should actually be the same!
|
||||
// swap the height values as a workaround for this quirk
|
||||
INT32 temp = height;
|
||||
height = bheight;
|
||||
bheight = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (height <= dc_copy.yl)
|
||||
{
|
||||
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
|
||||
|
||||
if (encoremap)
|
||||
{
|
||||
dc_copy.colormap += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
if (solid && dc_copy.yl < bheight)
|
||||
{
|
||||
dc_copy.yl = bheight;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a break in the column!
|
||||
dc_copy.yh = height;
|
||||
|
||||
if (dc_copy.yh > realyh)
|
||||
{
|
||||
dc_copy.yh = realyh;
|
||||
}
|
||||
|
||||
R_DrawColumnTemplate<NewType>(&dc_copy);
|
||||
if (solid)
|
||||
{
|
||||
dc_copy.yl = bheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_copy.yl = dc_copy.yh + 1;
|
||||
}
|
||||
|
||||
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
|
||||
|
||||
if (encoremap)
|
||||
{
|
||||
dc_copy.colormap += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
dc_copy.yh = realyh;
|
||||
|
||||
if (dc_copy.yl <= realyh)
|
||||
{
|
||||
R_DrawColumnTemplate<NewType>(&dc_copy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inner loop that does the actual texture mapping,
|
||||
// e.g. a DDA-lile scaling.
|
||||
// This is as fast as it gets. (Yeah, right!!! -- killough)
|
||||
//
|
||||
// killough 2/1/98: more performance tuning
|
||||
|
||||
intptr_t frac;
|
||||
const intptr_t fracstep = dc->iscale;
|
||||
const intptr_t heightmask = dc->sourcelength-1;
|
||||
constexpr INT32 npow2min = -1;
|
||||
const INT32 npow2max = dc->sourcelength;
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
const UINT8 * restrict source = dc->source;
|
||||
const lighttable_t * restrict colormap = dc->colormap;
|
||||
|
||||
// Framebuffer destination address.
|
||||
UINT8 * restrict dest = R_Address(dc->x, dc->yl);
|
||||
|
||||
count++;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep));
|
||||
|
||||
switch (heightmask)
|
||||
{
|
||||
case 255:
|
||||
case 127:
|
||||
{
|
||||
while(count--)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
{
|
||||
if (frac < 0)
|
||||
// adjust in case we underread
|
||||
frac += FRACUNIT;
|
||||
|
||||
// texture has no height, so just go
|
||||
while (--count >= 0)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, frac>>FRACBITS, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (!(dc->sourcelength & heightmask)) // power of 2 -- killough
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2 -- killough
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
dest += stride;
|
||||
frac += fracstep;
|
||||
}
|
||||
|
||||
if (count & 1)
|
||||
{
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const intptr_t fixed_heightmask = dc->texheight << FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
{
|
||||
while ((frac += fixed_heightmask) < 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (frac >= fixed_heightmask)
|
||||
{
|
||||
frac -= fixed_heightmask;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
|
||||
// -1 is the lower clamp bound because column posts have a "safe" byte before the real data
|
||||
// and a few bytes after as well
|
||||
*dest = R_DrawColumnPixel<Type>(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap);
|
||||
|
||||
dest += stride;
|
||||
|
||||
#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
|
||||
// Avoid overflow.
|
||||
if (fracstep > 0x7FFFFFFF - frac)
|
||||
{
|
||||
frac += fracstep - fixed_heightmask;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
frac += fracstep;
|
||||
}
|
||||
|
||||
while (frac >= fixed_heightmask)
|
||||
{
|
||||
frac -= fixed_heightmask;
|
||||
}
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_COLUMN_FUNC(name, flags) \
|
||||
void name(drawcolumndata_t *dc) \
|
||||
{ \
|
||||
constexpr DrawColumnType opt = static_cast<DrawColumnType>(flags); \
|
||||
R_DrawColumnTemplate<opt>(dc); \
|
||||
}
|
||||
|
||||
DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP)
|
||||
DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST)
|
||||
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP)
|
||||
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES)
|
||||
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP)
|
||||
|
||||
/** \brief The R_DrawFogColumn function
|
||||
Fog wall.
|
||||
*/
|
||||
void R_DrawFogColumn(drawcolumndata_t* dc)
|
||||
{
|
||||
INT32 count;
|
||||
UINT8 * restrict dest;
|
||||
|
||||
count = dc->yh - dc->yl;
|
||||
|
||||
// Zero length, column does not exceed a pixel.
|
||||
if (count < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Framebuffer destination address.
|
||||
dest = R_Address(dc->x, dc->yl);
|
||||
|
||||
const INT32 stride = vid.width;
|
||||
const lighttable_t * restrict colormap = dc->colormap;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
do
|
||||
{
|
||||
// Simple. Apply the colormap to what's already on the screen.
|
||||
*dest = colormap[*dest];
|
||||
dest += stride;
|
||||
} while (count--);
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_draw_span.cpp
|
||||
/// \brief span drawer functions
|
||||
/// \note no includes because this is included as part of r_draw.cpp
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define local_for_thread static __thread
|
||||
#else
|
||||
#include <threads.h>
|
||||
#define local_for_thread thread_local static
|
||||
#endif
|
||||
#else
|
||||
#define local_for_thread static
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
// SPANS
|
||||
// ==========================================================================
|
||||
|
||||
#define SPANSIZE 16
|
||||
#define INVSPAN 0.0625f
|
||||
|
||||
// <Callum> 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size)
|
||||
#define MAXFLATBYTES 4194303
|
||||
|
||||
#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / stride / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan))
|
||||
|
||||
enum DrawSpanType
|
||||
{
|
||||
DS_BASIC = 0x0000,
|
||||
DS_COLORMAP = 0x0001,
|
||||
DS_TRANSMAP = 0x0002,
|
||||
DS_HOLES = 0x0004,
|
||||
DS_RIPPLE = 0x0008,
|
||||
};
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col)
|
||||
{
|
||||
col = colormap[col];
|
||||
|
||||
if constexpr (Type & DrawSpanType::DS_TRANSMAP)
|
||||
{
|
||||
return *(ds->transmap + (col << 8) + (*dsrc));
|
||||
}
|
||||
else
|
||||
{
|
||||
return col;
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source)
|
||||
{
|
||||
UINT8 col = source[bit];
|
||||
|
||||
if constexpr (Type & DrawSpanType::DS_HOLES)
|
||||
{
|
||||
if (col == TRANSPARENTPIXEL)
|
||||
{
|
||||
return *dsrc;
|
||||
}
|
||||
}
|
||||
|
||||
return R_GetSpanTranslucent<Type>(ds, dsrc, colormap, col);
|
||||
}
|
||||
|
||||
/** \brief The R_DrawSpan_8 function
|
||||
Draws the actual span.
|
||||
*/
|
||||
template<DrawSpanType Type>
|
||||
static void R_DrawSpanTemplate(drawspandata_t* ds)
|
||||
{
|
||||
UINT32 xposition;
|
||||
UINT32 yposition;
|
||||
UINT32 xstep, ystep;
|
||||
UINT32 bit;
|
||||
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
UINT8 * restrict dsrc;
|
||||
|
||||
const UINT8 * restrict deststop = vid.screens[0] + vid.rowbytes * vid.height;
|
||||
|
||||
if (dest+8 > deststop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
intptr_t count = (ds->x2 - ds->x1 + 1);
|
||||
size_t i;
|
||||
|
||||
xposition = ds->xfrac; yposition = ds->yfrac;
|
||||
xstep = ds->xstep; ystep = ds->ystep;
|
||||
|
||||
const UINT8 * restrict source = ds->source;
|
||||
const UINT8 * restrict colormap = ds->colormap;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
yposition += ds->waterofs;
|
||||
}
|
||||
|
||||
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
|
||||
// can be used for the fraction part. This allows calculation of the memory address in the
|
||||
// texture with two shifts, an OR and one AND. (see below)
|
||||
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
|
||||
// bit per power of two (obviously)
|
||||
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
|
||||
// than the original span renderer. Whodathunkit?
|
||||
xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup;
|
||||
xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsrc = dest;
|
||||
}
|
||||
|
||||
while (count >= 8)
|
||||
{
|
||||
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
|
||||
// have the uber complicated math to calculate it now, so that was a memory write we didn't
|
||||
// need!
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
|
||||
|
||||
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
|
||||
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
|
||||
dest += 8;
|
||||
dsrc += 8;
|
||||
|
||||
count -= 8;
|
||||
}
|
||||
|
||||
while (count-- && dest <= deststop)
|
||||
{
|
||||
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
|
||||
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
|
||||
dest++;
|
||||
dsrc++;
|
||||
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
}
|
||||
|
||||
// R_CalcTiltedLighting
|
||||
// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
|
||||
static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end)
|
||||
{
|
||||
// ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version
|
||||
// of this function. Here's my own.
|
||||
INT32 i, left = x1, right = x2;
|
||||
const fixed_t step = (end-start)/(x2 - x1 + 1);
|
||||
|
||||
// I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once,
|
||||
// but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now...
|
||||
|
||||
for (i = left; i <= right; i++)
|
||||
{
|
||||
lightbuffer[i] = (start += step) >> FRACBITS;
|
||||
|
||||
if (lightbuffer[i] < 0)
|
||||
{
|
||||
lightbuffer[i] = 0;
|
||||
}
|
||||
else if (lightbuffer[i] >= MAXLIGHTSCALE)
|
||||
{
|
||||
lightbuffer[i] = MAXLIGHTSCALE-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawSpanType Type>
|
||||
static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
|
||||
{
|
||||
int width = ds->x2 - ds->x1;
|
||||
float iz, uz, vz;
|
||||
UINT32 u, v;
|
||||
int i;
|
||||
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
UINT8 * restrict dsrc;
|
||||
|
||||
float startz, startu, startv;
|
||||
float izstep, uzstep, vzstep;
|
||||
float endz, endu, endv;
|
||||
UINT32 stepu, stepv;
|
||||
UINT32 bit;
|
||||
local_for_thread INT32 *tiltlighting = NULL;
|
||||
local_for_thread INT32 oldviewwidth = 0;
|
||||
|
||||
// dont realloc every frame pls thx
|
||||
if (tiltlighting == NULL || oldviewwidth != viewwidth)
|
||||
{
|
||||
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
|
||||
oldviewwidth = viewwidth;
|
||||
}
|
||||
|
||||
INT32 x1 = ds->x1;
|
||||
const INT32 nflatxshift = ds->nflatxshift;
|
||||
const INT32 nflatyshift = ds->nflatyshift;
|
||||
const INT32 nflatmask = ds->nflatmask;
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
|
||||
|
||||
// Lighting is simple. It's just linear interpolation from start to end
|
||||
{
|
||||
float planelightfloat = PLANELIGHTFLOAT;
|
||||
float lightstart, lightend;
|
||||
|
||||
lightend = (iz + ds->szp.x*width) * planelightfloat;
|
||||
lightstart = iz * planelightfloat;
|
||||
|
||||
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
|
||||
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
|
||||
}
|
||||
|
||||
uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx);
|
||||
vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx);
|
||||
|
||||
const UINT8 *source = ds->source;
|
||||
const UINT8 *colormap = ds->colormap;
|
||||
|
||||
if constexpr (Type & DS_RIPPLE)
|
||||
{
|
||||
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * stride + ds->x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsrc = dest;
|
||||
}
|
||||
|
||||
#if 0 // The "perfect" reference version of this routine. Pretty slow.
|
||||
// Use it only to see how things are supposed to look.
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
double z = 1.f/iz;
|
||||
u = (INT64)(uz*z);
|
||||
v = (INT64)(vz*z);
|
||||
|
||||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
colormap = planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit);
|
||||
dest++;
|
||||
ds->x1++;
|
||||
dsrc++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
} while (--width >= 0);
|
||||
#else
|
||||
startz = 1.f/iz;
|
||||
startu = uz*startz;
|
||||
startv = vz*startz;
|
||||
|
||||
izstep = ds->szp.x * SPANSIZE;
|
||||
uzstep = ds->sup.x * SPANSIZE;
|
||||
vzstep = ds->svp.x * SPANSIZE;
|
||||
//x1 = 0;
|
||||
width++;
|
||||
|
||||
while (width >= SPANSIZE)
|
||||
{
|
||||
iz += izstep;
|
||||
uz += uzstep;
|
||||
vz += vzstep;
|
||||
|
||||
endz = 1.f/iz;
|
||||
endu = uz*endz;
|
||||
endv = vz*endz;
|
||||
stepu = (INT64)((endu - startu) * INVSPAN);
|
||||
stepv = (INT64)((endv - startv) * INVSPAN);
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
|
||||
x1 = ds->x1;
|
||||
|
||||
for (i = 0; i < SPANSIZE; i++)
|
||||
{
|
||||
bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps);
|
||||
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
|
||||
}
|
||||
|
||||
ds->x1 += SPANSIZE;
|
||||
dest += SPANSIZE;
|
||||
dsrc += SPANSIZE;
|
||||
startu = endu;
|
||||
startv = endv;
|
||||
width -= SPANSIZE;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
ds->x1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
double left = width;
|
||||
iz += ds->szp.x * left;
|
||||
uz += ds->sup.x * left;
|
||||
vz += ds->svp.x * left;
|
||||
|
||||
endz = 1.f/iz;
|
||||
endu = uz*endz;
|
||||
endv = vz*endz;
|
||||
left = 1.f/left;
|
||||
stepu = (INT64)((endu - startu) * left);
|
||||
stepv = (INT64)((endv - startv) * left);
|
||||
u = (INT64)(startu);
|
||||
v = (INT64)(startv);
|
||||
|
||||
for (; width != 0; width--)
|
||||
{
|
||||
bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift);
|
||||
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
|
||||
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
|
||||
dest++;
|
||||
ds->x1++;
|
||||
dsrc++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define DEFINE_SPAN_FUNC(name, flags, template) \
|
||||
void name(drawspandata_t* ds) \
|
||||
{ \
|
||||
constexpr DrawSpanType opt = static_cast<DrawSpanType>(flags); \
|
||||
template<opt>(ds); \
|
||||
}
|
||||
|
||||
#define DEFINE_SPAN_COMBO(name, flags) \
|
||||
DEFINE_SPAN_FUNC(name, flags, R_DrawSpanTemplate) \
|
||||
DEFINE_SPAN_FUNC(name ## _Tilted, flags, R_DrawTiltedSpanTemplate) \
|
||||
|
||||
DEFINE_SPAN_COMBO(R_DrawSpan, DS_BASIC)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentSpan, DS_TRANSMAP)
|
||||
DEFINE_SPAN_COMBO(R_DrawSplat, DS_HOLES)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentSplat, DS_TRANSMAP|DS_HOLES)
|
||||
DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE)
|
||||
|
||||
/** \brief The R_DrawFogSpan function
|
||||
Draws the actual span with fogging.
|
||||
*/
|
||||
void R_DrawFogSpan(drawspandata_t* ds)
|
||||
{
|
||||
const UINT8 * restrict colormap = ds->colormap;
|
||||
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
|
||||
|
||||
intptr_t count = ds->x2 - ds->x1 + 1;
|
||||
|
||||
while (count >= 4)
|
||||
{
|
||||
dest[0] = colormap[dest[0]];
|
||||
dest[1] = colormap[dest[1]];
|
||||
dest[2] = colormap[dest[2]];
|
||||
dest[3] = colormap[dest[3]];
|
||||
|
||||
dest += 4;
|
||||
count -= 4;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = colormap[*dest];
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
void R_DrawFogSpan_Tilted(drawspandata_t* ds)
|
||||
{
|
||||
int width = ds->x2 - ds->x1;
|
||||
float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
|
||||
UINT8 * restrict dest;
|
||||
|
||||
local_for_thread INT32 *tiltlighting = NULL;
|
||||
local_for_thread INT32 oldviewwidth = 0;
|
||||
|
||||
// dont realloc every frame pls thx
|
||||
if (tiltlighting == NULL || oldviewwidth != viewwidth)
|
||||
{
|
||||
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
|
||||
oldviewwidth = viewwidth;
|
||||
}
|
||||
|
||||
dest = R_Address(ds->x1, ds->y);
|
||||
const INT32 stride = vid.width;
|
||||
|
||||
// Lighting is simple. It's just linear interpolation from start to end
|
||||
{
|
||||
float planelightfloat = PLANELIGHTFLOAT;
|
||||
float lightstart, lightend;
|
||||
|
||||
lightend = (iz + ds->szp.x*width) * planelightfloat;
|
||||
lightstart = iz * planelightfloat;
|
||||
|
||||
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
|
||||
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps);
|
||||
*dest = colormap[*dest];
|
||||
dest++;
|
||||
}
|
||||
while (--width >= 0);
|
||||
}
|
||||
+3
-3
@@ -173,7 +173,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Lactozilla for finding this out)
|
||||
static void R_SetupFreelook(void)
|
||||
{
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
@@ -494,8 +494,8 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
|
||||
interp->polyobj.polyobj = polyobj;
|
||||
interp->polyobj.vertices_size = polyobj->numVertices;
|
||||
|
||||
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.oldvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
|
||||
interp->polyobj.bakvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
|
||||
for (size_t i = 0; i < polyobj->numVertices; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __R_FPS_H__
|
||||
#define __R_FPS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
@@ -175,4 +179,8 @@ void R_UpdateMobjInterpolators(void);
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj);
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_LOCAL__
|
||||
#define __R_LOCAL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Screen size related parameters.
|
||||
#include "doomdef.h"
|
||||
|
||||
@@ -38,4 +42,8 @@ extern drawseg_t *firstseg;
|
||||
|
||||
void SplitScreen_OnChange(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __R_LOCAL__
|
||||
+245
-236
@@ -13,6 +13,8 @@
|
||||
/// utility functions (BSP, geometry, trigonometry).
|
||||
/// See tables.c, too.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
@@ -88,7 +90,7 @@ INT32 viewangletox[FINEANGLES/2];
|
||||
// The xtoviewangleangle[] table maps a screen pixel
|
||||
// to the lowest viewangle that maps back to x ranges
|
||||
// from clipangle to -clipangle.
|
||||
angle_t xtoviewangle[MAXVIDWIDTH+1];
|
||||
angle_t *xtoviewangle;
|
||||
|
||||
lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
||||
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
||||
@@ -100,23 +102,23 @@ extracolormap_t extra_colormaps[MAXCOLORMAPS];
|
||||
|
||||
// Performance stats
|
||||
precise_t ps_prevframetime = 0;
|
||||
ps_metric_t ps_rendercalltime = {0};
|
||||
ps_metric_t ps_otherrendertime = {0};
|
||||
ps_metric_t ps_uitime = {0};
|
||||
ps_metric_t ps_swaptime = {0};
|
||||
ps_metric_t ps_rendercalltime = {};
|
||||
ps_metric_t ps_otherrendertime = {};
|
||||
ps_metric_t ps_uitime = {};
|
||||
ps_metric_t ps_swaptime = {};
|
||||
|
||||
ps_metric_t ps_skyboxtime = {0};
|
||||
ps_metric_t ps_bsptime = {0};
|
||||
ps_metric_t ps_skyboxtime = {};
|
||||
ps_metric_t ps_bsptime = {};
|
||||
|
||||
ps_metric_t ps_sw_spritecliptime = {0};
|
||||
ps_metric_t ps_sw_portaltime = {0};
|
||||
ps_metric_t ps_sw_planetime = {0};
|
||||
ps_metric_t ps_sw_maskedtime = {0};
|
||||
ps_metric_t ps_sw_spritecliptime = {};
|
||||
ps_metric_t ps_sw_portaltime = {};
|
||||
ps_metric_t ps_sw_planetime = {};
|
||||
ps_metric_t ps_sw_maskedtime = {};
|
||||
|
||||
ps_metric_t ps_numbspcalls = {0};
|
||||
ps_metric_t ps_numsprites = {0};
|
||||
ps_metric_t ps_numdrawnodes = {0};
|
||||
ps_metric_t ps_numpolyobjects = {0};
|
||||
ps_metric_t ps_numbspcalls = {};
|
||||
ps_metric_t ps_numsprites = {};
|
||||
ps_metric_t ps_numdrawnodes = {};
|
||||
ps_metric_t ps_numpolyobjects = {};
|
||||
|
||||
static CV_PossibleValue_t drawdist_cons_t[] = {
|
||||
/*{256, "256"},*/ {512, "512"}, {768, "768"},
|
||||
@@ -157,10 +159,6 @@ static void FlipCam_OnChange(void);
|
||||
static void FlipCam2_OnChange(void);
|
||||
static void FlipCam3_OnChange(void);
|
||||
static void FlipCam4_OnChange(void);
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
static void DirLight_OnChange(void);
|
||||
|
||||
@@ -185,38 +183,37 @@ consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS] = {
|
||||
{"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_softcyancut = {"softwarecyancut", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE|CV_CALL|CV_NOINIT, drawdist_precip_cons_t, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_mobjscaleprecip = {"scaleprecipmobjscale", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// cap fov, fov too high tears software apart.
|
||||
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Okay, whoever said homremoval causes a performance hit should be shot.
|
||||
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// cap fov, fov too high tears software apart.
|
||||
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// randomized directional lightning
|
||||
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// tells to reset the maplight at next map change
|
||||
static void DirLight_OnChange(void)
|
||||
@@ -494,7 +491,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
|
||||
// Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance.
|
||||
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh)
|
||||
{
|
||||
const angle_t left = viewangle - clipangle;
|
||||
const angle_t left = viewangle - clipangle;
|
||||
const angle_t right = viewangle + clipangle;
|
||||
|
||||
const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left));
|
||||
@@ -504,10 +501,10 @@ void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32
|
||||
const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right));
|
||||
|
||||
// Try to narrow the search to within only the field of view
|
||||
*xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*xl = (unsigned)(std::min(viewx, std::min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*xh = (unsigned)(std::max(viewx, std::max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
*yl = (unsigned)(std::min(viewy, std::min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
*yh = (unsigned)(std::max(viewy, std::max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
|
||||
if (*xh >= bmapwidth)
|
||||
*xh = bmapwidth - 1;
|
||||
@@ -631,7 +628,7 @@ static struct {
|
||||
INT32 scrmapsize;
|
||||
|
||||
INT32 x1; // clip rendering horizontally for efficiency
|
||||
INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];
|
||||
INT16 *ceilingclip, *floorclip;
|
||||
|
||||
boolean use;
|
||||
} viewmorph = {
|
||||
@@ -642,7 +639,7 @@ static struct {
|
||||
0,
|
||||
|
||||
0,
|
||||
{}, {},
|
||||
NULL, NULL,
|
||||
|
||||
false
|
||||
};
|
||||
@@ -660,7 +657,6 @@ void R_CheckViewMorph(void)
|
||||
rollangle >>= ANGLETOFINESHIFT;
|
||||
rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
|
||||
|
||||
|
||||
if (rollangle == viewmorph.rollangle &&
|
||||
viewmorph.scrmapsize == vid.width*vid.height)
|
||||
return; // No change
|
||||
@@ -680,10 +676,10 @@ void R_CheckViewMorph(void)
|
||||
|
||||
if (viewmorph.scrmapsize != vid.width*vid.height)
|
||||
{
|
||||
if (viewmorph.scrmap)
|
||||
free(viewmorph.scrmap);
|
||||
viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32));
|
||||
viewmorph.scrmapsize = vid.width*vid.height;
|
||||
viewmorph.scrmap = static_cast<INT32*>(realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32)));
|
||||
viewmorph.ceilingclip = static_cast<INT16*>(realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16)));
|
||||
viewmorph.floorclip = static_cast<INT16*>(realloc(viewmorph.floorclip, vid.width * sizeof(INT16)));
|
||||
}
|
||||
|
||||
temp = FINECOSINE(rollangle);
|
||||
@@ -695,7 +691,7 @@ void R_CheckViewMorph(void)
|
||||
x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width;
|
||||
y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height;
|
||||
|
||||
temp = max(x1, y1)*FRACUNIT;
|
||||
temp = std::max(x1, y1)*FRACUNIT;
|
||||
if (temp < FRACUNIT)
|
||||
temp = FRACUNIT;
|
||||
else
|
||||
@@ -741,10 +737,10 @@ void R_CheckViewMorph(void)
|
||||
xb = vid.width-1-xa;
|
||||
yb = vid.height-1-ya;
|
||||
|
||||
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
|
||||
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
|
||||
x2 += rollcos;
|
||||
y2 += rollsin;
|
||||
}
|
||||
@@ -758,10 +754,10 @@ void R_CheckViewMorph(void)
|
||||
xb = vid.width-1-xa;
|
||||
yb = vid.height-1-ya;
|
||||
|
||||
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
|
||||
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
|
||||
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
|
||||
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
|
||||
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
|
||||
x2 -= rollsin;
|
||||
y2 += rollcos;
|
||||
}
|
||||
@@ -799,8 +795,8 @@ void R_CheckViewMorph(void)
|
||||
|
||||
void R_ApplyViewMorph(void)
|
||||
{
|
||||
UINT8 *tmpscr = screens[4];
|
||||
UINT8 *srcscr = screens[0];
|
||||
UINT8 *tmpscr = vid.screens[4];
|
||||
UINT8 *srcscr = vid.screens[0];
|
||||
INT32 p, end = vid.width * vid.height;
|
||||
|
||||
if (!viewmorph.use)
|
||||
@@ -835,8 +831,7 @@ void R_ApplyViewMorph(void)
|
||||
for (p = 0; p < end; p++)
|
||||
tmpscr[p] = srcscr[viewmorph.scrmap[p]];
|
||||
|
||||
VID_BlitLinearScreen(tmpscr, screens[0],
|
||||
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
|
||||
VID_BlitLinearScreen(tmpscr, vid.screens[0], vid.width, vid.height, vid.width, vid.width);
|
||||
}
|
||||
|
||||
angle_t R_ViewRollAngle(const player_t *player)
|
||||
@@ -889,6 +884,8 @@ void R_SetViewSize(void)
|
||||
setsizeneeded = true;
|
||||
}
|
||||
|
||||
static void R_SetupViewBuffers(void);
|
||||
|
||||
//
|
||||
// R_ExecuteSetViewSize
|
||||
//
|
||||
@@ -907,18 +904,15 @@ void R_ExecuteSetViewSize(void)
|
||||
// status bar overlay
|
||||
st_overlay = cv_showhud.value;
|
||||
|
||||
scaledviewwidth = vid.width;
|
||||
viewwidth = vid.width;
|
||||
viewheight = vid.height;
|
||||
|
||||
if (splitscreen)
|
||||
viewheight >>= 1;
|
||||
|
||||
viewwidth = scaledviewwidth;
|
||||
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwidth >>= 1;
|
||||
scaledviewwidth >>= 1;
|
||||
}
|
||||
|
||||
centerx = viewwidth/2;
|
||||
@@ -926,9 +920,7 @@ void R_ExecuteSetViewSize(void)
|
||||
centerxfrac = centerx<<FRACBITS;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
|
||||
R_SetFov(cv_fov.value);
|
||||
|
||||
R_InitViewBuffer(scaledviewwidth, viewheight);
|
||||
R_SetupViewBuffers();
|
||||
|
||||
// why did we calc all the software crap?
|
||||
#ifdef HWRENDER
|
||||
@@ -942,7 +934,10 @@ void R_ExecuteSetViewSize(void)
|
||||
|
||||
// thing clipping
|
||||
for (i = 0; i < viewwidth; i++)
|
||||
{
|
||||
negonearray[i] = -1;
|
||||
screenheightarray[i] = (INT16)viewheight;
|
||||
}
|
||||
|
||||
if (ds_su)
|
||||
Z_Free(ds_su);
|
||||
@@ -952,7 +947,6 @@ void R_ExecuteSetViewSize(void)
|
||||
Z_Free(ds_sz);
|
||||
|
||||
ds_su = ds_sv = ds_sz = NULL;
|
||||
ds_sup = ds_svp = ds_szp = NULL;
|
||||
|
||||
memset(scalelight, 0xFF, sizeof(scalelight));
|
||||
|
||||
@@ -980,33 +974,52 @@ void R_ExecuteSetViewSize(void)
|
||||
fixed_t R_GetPlayerFov(player_t *player)
|
||||
{
|
||||
fixed_t fov = cv_fov.value + player->fovadd;
|
||||
return max(MINFOV*FRACUNIT, min(fov, MAXFOV*FRACUNIT));
|
||||
return std::max(MINFOV*FRACUNIT, std::min(fov, MAXFOV*FRACUNIT));
|
||||
}
|
||||
|
||||
static void R_SetFov(fixed_t playerfov)
|
||||
static void R_CalcFov(fixed_t playerfov)
|
||||
{
|
||||
angle_t fov = FixedAngle(playerfov/2) + ANGLE_90;
|
||||
fovtan = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded);
|
||||
if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
|
||||
fovtan = 17*fovtan/10;
|
||||
|
||||
// this is only used for planes rendering in software mode
|
||||
INT32 j = viewheight*16;
|
||||
for (INT32 i = 0; i < j; i++)
|
||||
{
|
||||
fixed_t dy = (i - viewheight*8)<<FRACBITS;
|
||||
dy = FixedMul(abs(dy), fovtan);
|
||||
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
|
||||
}
|
||||
|
||||
projection = projectiony = FixedDiv(centerxfrac, fovtan);
|
||||
}
|
||||
|
||||
static void R_InitViewMapping(void)
|
||||
{
|
||||
R_InitTextureMapping();
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// this is only used for planes rendering in software mode
|
||||
INT32 j = viewheight*16;
|
||||
|
||||
for (INT32 i = 0; i < j; i++)
|
||||
{
|
||||
fixed_t dy = (i - viewheight*8)<<FRACBITS;
|
||||
dy = FixedMul(abs(dy), fovtan);
|
||||
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
|
||||
}
|
||||
}
|
||||
|
||||
// setup sky scaling
|
||||
R_SetSkyScale();
|
||||
}
|
||||
|
||||
static void R_SetupViewBuffers(void)
|
||||
{
|
||||
R_CalcFov(cv_fov.value);
|
||||
R_InitViewBuffer(viewwidth, viewheight);
|
||||
R_InitViewMapping();
|
||||
}
|
||||
|
||||
static void R_SetFov(fixed_t playerfov)
|
||||
{
|
||||
R_CalcFov(playerfov);
|
||||
R_InitViewMapping();
|
||||
}
|
||||
|
||||
//
|
||||
// R_Init
|
||||
@@ -1022,9 +1035,6 @@ void R_Init(void)
|
||||
R_InitViewBorder();
|
||||
R_SetViewSize(); // setsizeneeded is set true
|
||||
|
||||
//I_OutputMsg("\nR_InitPlanes");
|
||||
R_InitPlanes();
|
||||
|
||||
// this is now done by SCR_Recalc() at the first mode set
|
||||
//I_OutputMsg("\nR_InitLightTables");
|
||||
R_InitLightTables();
|
||||
@@ -1085,17 +1095,87 @@ static void R_SetupAimingFrame(player_t *player, camera_t *thiscam)
|
||||
}
|
||||
}
|
||||
|
||||
static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh)
|
||||
{
|
||||
if (!mh->skybox_scalex && !mh->skybox_scaley && !mh->skybox_scalez)
|
||||
return;
|
||||
|
||||
auto setup_skyscale = [&](fixed_t mox, fixed_t moy, fixed_t zscale)
|
||||
{
|
||||
if (skyboxmo[1])
|
||||
{
|
||||
angle_t ang;
|
||||
fixed_t x = 0, y = 0;
|
||||
|
||||
if (mh->skybox_scalex > 0)
|
||||
x = (mox - skyboxmo[1]->x) / mh->skybox_scalex;
|
||||
else if (mh->skybox_scalex < 0)
|
||||
x = (mox - skyboxmo[1]->x) * -mh->skybox_scalex;
|
||||
|
||||
if (mh->skybox_scaley > 0)
|
||||
y = (moy - skyboxmo[1]->y) / mh->skybox_scaley;
|
||||
else if (mh->skybox_scaley < 0)
|
||||
y = (moy - skyboxmo[1]->y) * -mh->skybox_scaley;
|
||||
|
||||
switch (viewmobj->angle)
|
||||
{
|
||||
case 0:
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
break;
|
||||
case ANGLE_90:
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
break;
|
||||
case ANGLE_180:
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
break;
|
||||
case ANGLE_270:
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
break;
|
||||
default:
|
||||
ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mh->skybox_scalez > 0)
|
||||
newview->z += zscale / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
newview->z += zscale * -mh->skybox_scalez;
|
||||
};
|
||||
|
||||
if (player->awayviewtics && player->awayviewmobj)
|
||||
{
|
||||
setup_skyscale(player->awayviewmobj->x, player->awayviewmobj->y, (player->awayviewmobj->z + 20*FRACUNIT));
|
||||
}
|
||||
else if (thiscam && thiscam->chase)
|
||||
{
|
||||
setup_skyscale(thiscam->x, thiscam->y, (thiscam->z + (thiscam->height>>1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
setup_skyscale(player->mo->x, player->mo->y, player->viewz);
|
||||
}
|
||||
}
|
||||
|
||||
void R_SkyboxFrame(int s)
|
||||
{
|
||||
player_t *player = &players[displayplayers[s]];
|
||||
camera_t *thiscam = &camera[s];
|
||||
subsector_t * subsector = NULL;
|
||||
mapheader_t *mh = mapheaderinfo[gamemap-1];
|
||||
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + s);
|
||||
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_SKY1 + s));
|
||||
|
||||
// cut-away view stuff
|
||||
newview->sky = true;
|
||||
viewmobj = skyboxmo[0];
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (P_MobjWasRemoved(viewmobj))
|
||||
{
|
||||
@@ -1103,78 +1183,19 @@ void R_SkyboxFrame(int s)
|
||||
I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri));
|
||||
}
|
||||
#endif
|
||||
|
||||
R_SetupAimingFrame(player, thiscam);
|
||||
|
||||
newview->angle += viewmobj->angle;
|
||||
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = 0;
|
||||
if (viewmobj->spawnpoint)
|
||||
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
newview->z = (viewmobj->spawnpoint) ? (((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS) : 0;
|
||||
|
||||
#define SETUPSKYVIEW(viewmo, zscale)\
|
||||
if (skyboxmo[1])\
|
||||
{\
|
||||
fixed_t x = 0, y = 0;\
|
||||
if (mh->skybox_scalex > 0)\
|
||||
x = (viewmo->x - skyboxmo[1]->x) / mh->skybox_scalex;\
|
||||
else if (mh->skybox_scalex < 0)\
|
||||
x = (viewmo->x - skyboxmo[1]->x) * -mh->skybox_scalex;\
|
||||
if (mh->skybox_scaley > 0)\
|
||||
y = (viewmo->y - skyboxmo[1]->y) / mh->skybox_scaley;\
|
||||
else if (mh->skybox_scaley < 0)\
|
||||
y = (viewmo->y - skyboxmo[1]->y) * -mh->skybox_scaley;\
|
||||
if (viewmobj->angle == 0)\
|
||||
{\
|
||||
newview->x += x;\
|
||||
newview->y += y;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_90)\
|
||||
{\
|
||||
newview->x -= y;\
|
||||
newview->y += x;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_180)\
|
||||
{\
|
||||
newview->x -= x;\
|
||||
newview->y -= y;\
|
||||
}\
|
||||
else if (viewmobj->angle == ANGLE_270)\
|
||||
{\
|
||||
newview->x += y;\
|
||||
newview->y -= x;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;\
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));\
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));\
|
||||
}\
|
||||
}\
|
||||
if (mh->skybox_scalez > 0)\
|
||||
newview->z += zscale / mh->skybox_scalez;\
|
||||
else if (mh->skybox_scalez < 0)\
|
||||
newview->z += zscale * -mh->skybox_scalez;
|
||||
|
||||
if (mapheaderinfo[gamemap-1])
|
||||
if (mh)
|
||||
{
|
||||
mapheader_t *mh = mapheaderinfo[gamemap-1];
|
||||
|
||||
if (player->awayviewtics && player->awayviewmobj)
|
||||
{
|
||||
SETUPSKYVIEW(player->awayviewmobj, (player->awayviewmobj->z + 20*FRACUNIT));
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
SETUPSKYVIEW(thiscam, (thiscam->z + (thiscam->height>>1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SETUPSKYVIEW(player->mo, player->viewz);
|
||||
}
|
||||
R_SetupSkyScale(player, thiscam, mh);
|
||||
}
|
||||
#undef SETUPSKYVIEW
|
||||
|
||||
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
|
||||
subsector = viewmobj->subsector;
|
||||
@@ -1189,7 +1210,8 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
boolean chasecam = (cv_chasecam[s].value);
|
||||
sector_t * sector = NULL;
|
||||
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1 + s);
|
||||
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_PLAYER1 + s));
|
||||
|
||||
if (thiscam->reset)
|
||||
{
|
||||
R_ResetViewInterpolation(s);
|
||||
@@ -1235,12 +1257,13 @@ void R_SetupFrame(int s, boolean skybox)
|
||||
else if (thiscam && chasecam) // use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
I_Assert(thiscam != NULL);
|
||||
|
||||
newview->x = thiscam->x;
|
||||
newview->y = thiscam->y;
|
||||
newview->z = thiscam->z + (thiscam->height>>1);
|
||||
|
||||
if (thiscam != NULL && thiscam->subsector && thiscam->subsector->sector)
|
||||
if (thiscam->subsector && thiscam->subsector->sector)
|
||||
sector = thiscam->subsector->sector;
|
||||
|
||||
R_SetupCommonFrame(player, sector);
|
||||
@@ -1268,8 +1291,8 @@ static void R_PortalFrame(portal_t *portal)
|
||||
viewz = portal->viewz;
|
||||
|
||||
viewangle = portal->viewangle;
|
||||
// viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
//viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
//viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
portalclipstart = portal->start;
|
||||
portalclipend = portal->end;
|
||||
@@ -1277,8 +1300,7 @@ static void R_PortalFrame(portal_t *portal)
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
portalclipline = &lines[portal->clipline];
|
||||
portalcullsector = portalclipline->frontsector;
|
||||
viewsector = portalclipline->frontsector;
|
||||
viewsector = portalcullsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1288,10 +1310,41 @@ static void R_PortalFrame(portal_t *portal)
|
||||
}
|
||||
}
|
||||
|
||||
static void Mask_Pre (maskcount_t* m)
|
||||
{
|
||||
m->drawsegs[0] = ds_p - drawsegs;
|
||||
m->vissprites[0] = visspritecount;
|
||||
m->viewx = viewx;
|
||||
m->viewy = viewy;
|
||||
m->viewz = viewz;
|
||||
m->viewsector = viewsector;
|
||||
}
|
||||
|
||||
static void Mask_Post (maskcount_t* m)
|
||||
{
|
||||
m->drawsegs[1] = ds_p - drawsegs;
|
||||
m->vissprites[1] = visspritecount;
|
||||
}
|
||||
|
||||
// ================
|
||||
// R_RenderView
|
||||
// ================
|
||||
|
||||
// viewx, viewy, viewangle, all that good stuff must be set
|
||||
static void R_RenderViewpoint(maskcount_t* mask, boolean drawprecip)
|
||||
{
|
||||
Mask_Pre(mask);
|
||||
|
||||
curdrawsegs = ds_p;
|
||||
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
|
||||
if (drawprecip)
|
||||
R_AddPrecipitationSprites();
|
||||
|
||||
Mask_Post(mask);
|
||||
}
|
||||
|
||||
// FAB NOTE FOR WIN32 PORT !! I'm not finished already,
|
||||
// but I suspect network may have problems with the video buffer being locked
|
||||
// for all duration of rendering, and being released only once at the end..
|
||||
@@ -1302,52 +1355,19 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
void R_RenderPlayerView(player_t *player)
|
||||
{
|
||||
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
|
||||
UINT8 i;
|
||||
|
||||
// if this is display player 1
|
||||
if (cv_homremoval.value && player == &players[displayplayers[0]])
|
||||
{
|
||||
if (cv_homremoval.value == 1)
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
|
||||
else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15));
|
||||
}
|
||||
// Draw over the fourth screen so you don't have to stare at a HOM :V
|
||||
else if (splitscreen == 2 && player == &players[displayplayers[2]])
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
|
||||
|
||||
for (x = vid.width>>1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height>>1; y < vid.height; y += ph)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
INT32 nummasks = 1;
|
||||
maskcount_t* masks = static_cast<maskcount_t*>(malloc(sizeof(maskcount_t)));
|
||||
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
|
||||
|
||||
// load previous saved value of skyVisible for the player
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
skyVisible = skyVisiblePerPlayer[viewssnum];
|
||||
|
||||
const fixed_t fov = R_GetPlayerFov(player);
|
||||
|
||||
if (viewfov[viewssnum] != fov)
|
||||
{
|
||||
if (player != &players[displayplayers[i]])
|
||||
continue;
|
||||
|
||||
skyVisible = skyVisiblePerPlayer[i];
|
||||
break;
|
||||
}
|
||||
|
||||
fixed_t fov = R_GetPlayerFov(player);
|
||||
|
||||
for (UINT8 j = 0; j <= splitscreen; j++)
|
||||
{
|
||||
if (player == &players[displayplayers[j]]
|
||||
&& viewfov[j] != fov)
|
||||
{
|
||||
viewfov[j] = fov;
|
||||
R_SetFov(fov);
|
||||
}
|
||||
viewfov[viewssnum] = fov;
|
||||
R_SetFov(fov);
|
||||
}
|
||||
|
||||
Portal_InitList();
|
||||
@@ -1361,17 +1381,13 @@ void R_RenderPlayerView(player_t *player)
|
||||
R_ClearDrawSegs();
|
||||
R_ClearPlanes();
|
||||
R_ClearSprites();
|
||||
#ifdef FLOORSPLATS
|
||||
R_ClearVisibleFloorSplats();
|
||||
#endif
|
||||
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_ClipSprites();
|
||||
R_RenderViewpoint(&masks[nummasks - 1], false);
|
||||
|
||||
R_ClipSprites(drawsegs, NULL);
|
||||
R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts
|
||||
R_DrawPlanes();
|
||||
#ifdef FLOORSPLATS
|
||||
R_DrawVisibleFloorSplats();
|
||||
#endif
|
||||
R_DrawMasked();
|
||||
R_DrawMasked(masks, nummasks);
|
||||
}
|
||||
PS_STOP_TIMING(ps_skyboxtime);
|
||||
|
||||
@@ -1398,22 +1414,16 @@ void R_RenderPlayerView(player_t *player)
|
||||
}
|
||||
R_ClearDrawSegs();
|
||||
R_ClearSprites();
|
||||
#ifdef FLOORSPLATS
|
||||
R_ClearVisibleFloorSplats();
|
||||
#endif
|
||||
|
||||
// check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// The head node is the last node output.
|
||||
|
||||
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
|
||||
PS_START_TIMING(ps_bsptime);
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_RenderViewpoint(&masks[nummasks - 1], true);
|
||||
PS_STOP_TIMING(ps_bsptime);
|
||||
R_AddPrecipitationSprites();
|
||||
PS_START_TIMING(ps_sw_spritecliptime);
|
||||
R_ClipSprites();
|
||||
R_ClipSprites(drawsegs, NULL);
|
||||
PS_STOP_TIMING(ps_sw_spritecliptime);
|
||||
|
||||
ps_numsprites.value.i = numvisiblesprites;
|
||||
@@ -1442,43 +1452,40 @@ void R_RenderPlayerView(player_t *player)
|
||||
// that were previously stored.
|
||||
Portal_ClipApply(portal);
|
||||
|
||||
validcount++;
|
||||
|
||||
masks = static_cast<maskcount_t*>(realloc(masks, (++nummasks)*sizeof(maskcount_t)));
|
||||
|
||||
// Render the BSP from the new viewpoint, and clip
|
||||
// any sprites with the new clipsegs and window.
|
||||
R_RenderBSPNode((INT32)numnodes - 1);
|
||||
R_ClipSprites();
|
||||
R_RenderViewpoint(&masks[nummasks - 1], true);
|
||||
|
||||
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
|
||||
|
||||
Portal_Remove(portal);
|
||||
|
||||
validcount++;
|
||||
}
|
||||
}
|
||||
PS_STOP_TIMING(ps_sw_portaltime);
|
||||
|
||||
PS_START_TIMING(ps_sw_planetime);
|
||||
if (!skybox)
|
||||
R_DrawSkyPlanes();
|
||||
R_DrawPlanes();
|
||||
PS_STOP_TIMING(ps_sw_planetime);
|
||||
#ifdef FLOORSPLATS
|
||||
R_DrawVisibleFloorSplats();
|
||||
#endif
|
||||
// draw mid texture and sprite
|
||||
// And now 3D floors/sides!
|
||||
PS_START_TIMING(ps_sw_maskedtime);
|
||||
R_DrawMasked();
|
||||
R_DrawMasked(masks, nummasks);
|
||||
PS_STOP_TIMING(ps_sw_maskedtime);
|
||||
|
||||
free(masks);
|
||||
|
||||
// Check for new console commands.
|
||||
NetUpdate();
|
||||
|
||||
// save value to skyVisiblePerPlayer
|
||||
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (player != &players[displayplayers[i]])
|
||||
continue;
|
||||
|
||||
skyVisiblePerPlayer[i] = skyVisible;
|
||||
break;
|
||||
}
|
||||
skyVisiblePerPlayer[viewssnum] = skyVisible;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
@@ -1519,11 +1526,13 @@ void R_RegisterEngineStuff(void)
|
||||
{
|
||||
CV_RegisterVar(&cv_chasecam[i]);
|
||||
}
|
||||
|
||||
CV_RegisterVar(&cv_shadow);
|
||||
CV_RegisterVar(&cv_shadowoffs);
|
||||
CV_RegisterVar(&cv_skybox);
|
||||
CV_RegisterVar(&cv_ffloorclip);
|
||||
CV_RegisterVar(&cv_spriteclip);
|
||||
CV_RegisterVar(&cv_softcyancut);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
+11
-1
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_MAIN__
|
||||
#define __R_MAIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_player.h"
|
||||
#include "r_data.h"
|
||||
#include "m_perfstats.h"
|
||||
@@ -84,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
||||
//
|
||||
// killough 5/2/98: reformatted
|
||||
//
|
||||
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *restrict node)
|
||||
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * restrict node)
|
||||
{
|
||||
if (!node->dx)
|
||||
return x <= node->x ? node->dy > 0 : node->dy < 0;
|
||||
@@ -207,6 +211,7 @@ extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_shadow, cv_shadowoffs;
|
||||
extern consvar_t cv_ffloorclip, cv_spriteclip;
|
||||
extern consvar_t cv_softcyancut;
|
||||
extern consvar_t cv_translucency;
|
||||
extern consvar_t cv_drawdist, cv_drawdist_precip, cv_lessprecip, cv_mobjscaleprecip;
|
||||
extern consvar_t cv_fov, cv_fovchange;
|
||||
@@ -245,4 +250,9 @@ void R_RegisterEngineStuff(void);
|
||||
INT32 R_GetHudUncap(void);
|
||||
// same as above but keeps interpolation during pause
|
||||
INT32 R_GetMenuUncap(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "z_zone.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#ifndef __R_PATCHROTATION__
|
||||
#define __R_PATCHROTATION__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
// Sprite rotation
|
||||
@@ -27,4 +31,8 @@ extern fixed_t rollcosang[ROTANGLES];
|
||||
extern fixed_t rollsinang[ROTANGLES];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __R_PATCHROTATION__
|
||||
-1204
File diff suppressed because it is too large.
Load diff
+1408
File diff suppressed because it is too large.
Load diff
+21
-19
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_PLANE__
|
||||
#define __R_PLANE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT
|
||||
#include "r_data.h"
|
||||
#include "p_polyobj.h"
|
||||
@@ -43,9 +47,8 @@ typedef struct visplane_s
|
||||
// colormaps per sector
|
||||
extracolormap_t *extra_colormap;
|
||||
|
||||
// leave pads for [minx-1]/[maxx+1]
|
||||
UINT16 padtopstart, top[MAXVIDWIDTH], padtopend;
|
||||
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
|
||||
UINT16 *top, *top_memory;
|
||||
UINT16 *bottom, *bottom_memory;
|
||||
INT32 high, low; // R_PlaneBounds should set these.
|
||||
|
||||
fixed_t xoffs, yoffs; // Scrolling flats.
|
||||
@@ -55,8 +58,11 @@ typedef struct visplane_s
|
||||
pslope_t *slope;
|
||||
|
||||
boolean noencore;
|
||||
boolean cyan;
|
||||
} visplane_t;
|
||||
|
||||
extern visplane_t *visplanes[MAXVISPLANES];
|
||||
|
||||
extern visplane_t *floorplane;
|
||||
extern visplane_t *ceilingplane;
|
||||
|
||||
@@ -64,25 +70,19 @@ extern visplane_t *ceilingplane;
|
||||
extern INT16 *lastopening, *openings;
|
||||
extern size_t maxopenings;
|
||||
|
||||
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
|
||||
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
|
||||
extern fixed_t cachedheight[MAXVIDHEIGHT];
|
||||
extern fixed_t cacheddistance[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedxstep[MAXVIDHEIGHT];
|
||||
extern fixed_t cachedystep[MAXVIDHEIGHT];
|
||||
extern INT16 *floorclip, *ceilingclip;
|
||||
extern fixed_t *frontscale, *yslopetab;
|
||||
extern fixed_t basexscale, baseyscale;
|
||||
|
||||
extern fixed_t *yslope;
|
||||
extern lighttable_t **planezlight;
|
||||
|
||||
void R_InitPlanes(void);
|
||||
void R_AllocPlaneMemory(void);
|
||||
void R_ClearPlanes(void);
|
||||
void R_ClearFFloorClips (void);
|
||||
|
||||
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
|
||||
void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
|
||||
void R_DrawSkyPlanes(void);
|
||||
void R_DrawPlanes(void);
|
||||
void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge);
|
||||
|
||||
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
|
||||
extracolormap_t *planecolormap, ffloor_t *ffloor
|
||||
, polyobj_t *polyobj
|
||||
@@ -93,9 +93,6 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_PlaneBounds(visplane_t *plane);
|
||||
|
||||
// Draws a single visplane.
|
||||
void R_DrawSinglePlane(visplane_t *pl);
|
||||
|
||||
typedef struct planemgr_s
|
||||
{
|
||||
visplane_t *plane;
|
||||
@@ -104,8 +101,8 @@ typedef struct planemgr_s
|
||||
fixed_t b_pos; // B for Back sector
|
||||
fixed_t f_frac, f_step;
|
||||
fixed_t b_frac, b_step;
|
||||
INT16 f_clip[MAXVIDWIDTH];
|
||||
INT16 c_clip[MAXVIDWIDTH];
|
||||
INT16 *f_clip;
|
||||
INT16 *c_clip;
|
||||
|
||||
// For slope rendering; the height at the other end
|
||||
fixed_t f_pos_slope;
|
||||
@@ -119,4 +116,9 @@ typedef struct planemgr_s
|
||||
|
||||
extern visffloor_t ffloor[MAXFFLOORS];
|
||||
extern INT32 numffloors;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+178
-15
@@ -1,6 +1,6 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Kart Krew.
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
#include "r_portal.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_main.h" // viewheight, viewwidth
|
||||
#include "r_main.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_spec.h" // Skybox viewpoints
|
||||
#include "z_zone.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
@@ -36,7 +38,6 @@ void Portal_InitList (void)
|
||||
portal_base = portal_cap = NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Store the clipping window for a portal in its given range.
|
||||
*
|
||||
* The window is copied from the current window at the time
|
||||
@@ -63,7 +64,6 @@ static void Portal_ClipRange (portal_t* portal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Apply the clipping window from a portal.
|
||||
*/
|
||||
void Portal_ClipApply (const portal_t* portal)
|
||||
@@ -91,6 +91,7 @@ void Portal_ClipApply (const portal_t* portal)
|
||||
floorclip[i] = -1;
|
||||
ceilingclip[i] = (INT16)viewheight;
|
||||
}
|
||||
|
||||
for (i = end; i < vid.width; i++)
|
||||
{
|
||||
floorclip[i] = -1;
|
||||
@@ -119,11 +120,11 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
|
||||
portal->next = NULL;
|
||||
|
||||
// Store clipping values so they can be restored once the portal is rendered.
|
||||
portal->ceilingclip = ceilingclipsave;
|
||||
portal->floorclip = floorclipsave;
|
||||
portal->frontscale = frontscalesave;
|
||||
portal->start = x1;
|
||||
portal->end = x2;
|
||||
portal->ceilingclip = ceilingclipsave;
|
||||
portal->floorclip = floorclipsave;
|
||||
portal->frontscale = frontscalesave;
|
||||
portal->start = x1;
|
||||
portal->end = x2;
|
||||
|
||||
// Increase recursion level.
|
||||
portal->pass = portalrender+1;
|
||||
@@ -166,6 +167,10 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
|
||||
|
||||
vertex_t dest_c, start_c;
|
||||
|
||||
portal->viewx = viewx;
|
||||
portal->viewy = viewy;
|
||||
portal->viewz = viewz;
|
||||
|
||||
// looking glass center
|
||||
start_c.x = (start->v1->x + start->v2->x) / 2;
|
||||
start_c.y = (start->v1->y + start->v2->y) / 2;
|
||||
@@ -174,13 +179,24 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
|
||||
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
|
||||
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint += dangle;
|
||||
|
||||
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
|
||||
if (dangle == 0)
|
||||
{
|
||||
// the entrance goes straight opposite the exit, so we just need to mess with the offset.
|
||||
portal->viewx += dest_c.x - start_c.x;
|
||||
portal->viewy += dest_c.y - start_c.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint += dangle;
|
||||
|
||||
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
}
|
||||
|
||||
portal->viewangle = viewangle + dangle;
|
||||
|
||||
portal->clipline = line2;
|
||||
@@ -190,4 +206,151 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
|
||||
g_portal = portal; // this tells R_StoreWallRange that curline is a portal seg
|
||||
}
|
||||
|
||||
/** Store the clipping window for a portal using a visplane.
|
||||
*
|
||||
* Since visplanes top/bottom windows work in an identical way,
|
||||
* it can just be copied almost directly.
|
||||
*/
|
||||
static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal)
|
||||
{
|
||||
INT16 start = portal->start;
|
||||
INT16 end = portal->end;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < end - start; i++)
|
||||
{
|
||||
// Invalid column.
|
||||
if (plane->top[i + start] == 65535)
|
||||
{
|
||||
portal->ceilingclip[i] = -1;
|
||||
portal->floorclip[i] = -1;
|
||||
continue;
|
||||
}
|
||||
portal->ceilingclip[i] = plane->top[i + start] - 1;
|
||||
portal->floorclip[i] = plane->bottom[i + start] + 1;
|
||||
portal->frontscale[i] = INT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
extern INT32 viewwidth;
|
||||
|
||||
static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end)
|
||||
{
|
||||
*start = plane->minx;
|
||||
*end = plane->maxx + 1;
|
||||
|
||||
// Visplanes have 1-px pads on their sides (extra columns).
|
||||
// Trim them, else it may render out of bounds.
|
||||
if (*end > viewwidth)
|
||||
*end = viewwidth;
|
||||
|
||||
if (!(*start < *end))
|
||||
return true;
|
||||
|
||||
|
||||
/** Trims a visplane's horizontal gap to match its render area.
|
||||
*
|
||||
* Visplanes' minx/maxx may sometimes exceed the area they're
|
||||
* covering. This merely adjusts the boundaries to the next
|
||||
* valid area.
|
||||
*/
|
||||
|
||||
while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end)
|
||||
{
|
||||
(*start)++;
|
||||
}
|
||||
|
||||
|
||||
while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start)
|
||||
{
|
||||
(*end)--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Creates a skybox portal out of a visplane.
|
||||
*
|
||||
* Applies the necessary offsets and rotation to give
|
||||
* a depth illusion to the skybox.
|
||||
*/
|
||||
void Portal_AddSkybox(const visplane_t* plane)
|
||||
{
|
||||
INT16 start, end;
|
||||
mapheader_t *mh;
|
||||
portal_t* portal;
|
||||
|
||||
if (TrimVisplaneBounds(plane, &start, &end))
|
||||
return;
|
||||
|
||||
portal = Portal_Add(start, end);
|
||||
|
||||
Portal_ClipVisplane(plane, portal);
|
||||
|
||||
portal->viewx = skyboxmo[0]->x;
|
||||
portal->viewy = skyboxmo[0]->y;
|
||||
portal->viewz = skyboxmo[0]->z;
|
||||
if (skyboxmo[0]->spawnpoint)
|
||||
portal->viewz = ((fixed_t)skyboxmo[0]->spawnpoint->angle)<<FRACBITS;
|
||||
|
||||
portal->viewangle = viewangle + skyboxmo[0]->angle;
|
||||
|
||||
mh = mapheaderinfo[gamemap-1];
|
||||
|
||||
// If a relative viewpoint exists, offset the viewpoint.
|
||||
if (skyboxmo[1])
|
||||
{
|
||||
fixed_t x = 0, y = 0;
|
||||
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
|
||||
|
||||
if (mh->skybox_scalex > 0)
|
||||
x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex;
|
||||
else if (mh->skybox_scalex < 0)
|
||||
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex;
|
||||
|
||||
if (mh->skybox_scaley > 0)
|
||||
y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley;
|
||||
else if (mh->skybox_scaley < 0)
|
||||
y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley;
|
||||
|
||||
// Apply transform to account for the skybox viewport angle.
|
||||
portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
portal->viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
|
||||
if (mh->skybox_scalez > 0)
|
||||
portal->viewz += viewz / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
portal->viewz += viewz * -mh->skybox_scalez;
|
||||
|
||||
portal->clipline = -1;
|
||||
}
|
||||
|
||||
/** Creates portals for the currently existing sky visplanes.
|
||||
* The visplanes are also removed and cleared from the list.
|
||||
*/
|
||||
void Portal_AddSkyboxPortals(void)
|
||||
{
|
||||
visplane_t *pl;
|
||||
INT32 i;
|
||||
UINT16 count = 0;
|
||||
|
||||
for (i = 0; i < MAXVISPLANES; i++, pl++)
|
||||
{
|
||||
for (pl = visplanes[i]; pl; pl = pl->next)
|
||||
{
|
||||
if (pl->picnum == skyflatnum)
|
||||
{
|
||||
Portal_AddSkybox(pl);
|
||||
|
||||
pl->minx = 0;
|
||||
pl->maxx = -1;
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count);
|
||||
}
|
||||
|
||||
+13
-2
@@ -14,10 +14,14 @@
|
||||
#ifndef __R_PORTAL__
|
||||
#define __R_PORTAL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_data.h"
|
||||
#include "r_plane.h" // visplanes
|
||||
|
||||
|
||||
/** Portal structure.
|
||||
/** Portal structure for the software renderer.
|
||||
*/
|
||||
typedef struct portal_s
|
||||
{
|
||||
@@ -54,4 +58,11 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
|
||||
|
||||
void Portal_ClipApply (const portal_t* portal);
|
||||
|
||||
void Portal_AddSkybox(const visplane_t* plane);
|
||||
void Portal_AddSkyboxPortals(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1006
-866
File diff suppressed because it is too large.
Load diff
+12
-1
@@ -14,13 +14,24 @@
|
||||
#ifndef __R_SEGS__
|
||||
#define __R_SEGS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
transnum_t R_GetLinedefTransTable(fixed_t alpha);
|
||||
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2);
|
||||
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
|
||||
void R_StoreWallRange(INT32 start, INT32 stop);
|
||||
|
||||
void R_AllocSegMemory(void);
|
||||
|
||||
transnum_t R_GetLinedefTransTable(fixed_t alpha);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+791
@@ -0,0 +1,791 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Vivian "toastergrl" Grannell.
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_skins.c
|
||||
/// \brief Loading skins
|
||||
|
||||
#include "dehacked.h" // get_number (for thok)
|
||||
#include "doomdef.h"
|
||||
#include "console.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "g_game.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "p_local.h"
|
||||
#include "st_stuff.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_md2.h"
|
||||
#endif
|
||||
|
||||
#include "qs22j.h"
|
||||
|
||||
CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2];
|
||||
|
||||
INT32 numskins = 0;
|
||||
INT32 numallskins = 0;
|
||||
INT32 numlocalskins = 0;
|
||||
skin_t skins[MAXSKINS];
|
||||
UINT8 skinstats[9][9][MAXSKINS];
|
||||
UINT8 skinstatscount[9][9] = {
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
UINT8 skinsorted[MAXSKINS];
|
||||
skin_t localskins[MAXLOCALSKINS];
|
||||
skin_t allskins[MAXSKINS+MAXLOCALSKINS];
|
||||
|
||||
// FIXTHIS: don't work because it must be inistilised before the config load
|
||||
//#define SKINVALUES
|
||||
#ifdef SKINVALUES
|
||||
CV_PossibleValue_t skin_cons_t[MAXSKINS+1];
|
||||
CV_PossibleValue_t localskin_cons_t[MAXLOCALSKINS+1];
|
||||
#endif
|
||||
|
||||
static void Sk_SetDefaultValue(skin_t *skin, boolean local)
|
||||
{
|
||||
INT32 i;
|
||||
//
|
||||
// set default skin values
|
||||
//
|
||||
memset(skin, 0, sizeof (skin_t));
|
||||
snprintf(skin->name, sizeof skin->name, "skin %u", K_GetMobjSkinNum(skin, local));
|
||||
skin->name[sizeof skin->name - 1] = '\0';
|
||||
skin->wadnum = INT16_MAX;
|
||||
strcpy(skin->sprite, "");
|
||||
|
||||
skin->flags = 0;
|
||||
|
||||
strcpy(skin->realname, "Someone");
|
||||
strcpy(skin->hudname, "???");
|
||||
strncpy(skin->facerank, "PLAYRANK", 9);
|
||||
strncpy(skin->facewant, "PLAYWANT", 9);
|
||||
strncpy(skin->facemmap, "PLAYMMAP", 9);
|
||||
|
||||
skin->starttranscolor = 160;
|
||||
skin->prefcolor = SKINCOLOR_GREEN;
|
||||
|
||||
// SRB2kart
|
||||
skin->kartspeed = 5;
|
||||
skin->kartweight = 5;
|
||||
//
|
||||
|
||||
skin->highresscale = FRACUNIT>>1;
|
||||
|
||||
for (i = 0; i < sfx_skinsoundslot0; i++)
|
||||
if (S_sfx[i].skinsound != -1)
|
||||
skin->soundsid[S_sfx[i].skinsound] = i;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the basic skins
|
||||
//
|
||||
void R_InitSkins(void)
|
||||
{
|
||||
skin_t *skin;
|
||||
#ifdef SKINVALUES
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i <= MAXSKINS; i++)
|
||||
{
|
||||
skin_cons_t[i].value = 0;
|
||||
skin_cons_t[i].strvalue = NULL;
|
||||
}
|
||||
for (i = 0; i <= MAXLOCALSKINS; i++)
|
||||
{
|
||||
localskin_cons_t[i].value = 0;
|
||||
localskin_cons_t[i].strvalue = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// skin[0] = Sonic skin
|
||||
skin = &skins[0];
|
||||
numskins = 1;
|
||||
Sk_SetDefaultValue(skin, false);
|
||||
memset(skinstats, 0, sizeof(skinstats));
|
||||
memset(skinsorted, 0, sizeof(skinsorted));
|
||||
|
||||
// Hardcoded S_SKIN customizations for Sonic.
|
||||
strcpy(skin->name, DEFAULTSKIN);
|
||||
#ifdef SKINVALUES
|
||||
skin_cons_t[0].strvalue = skins[0].name;
|
||||
#endif
|
||||
skin->flags = 0;
|
||||
strcpy(skin->realname, "Sonic");
|
||||
strcpy(skin->hudname, "SONIC");
|
||||
|
||||
strncpy(skin->facerank, "PLAYRANK", 9);
|
||||
strncpy(skin->facewant, "PLAYWANT", 9);
|
||||
strncpy(skin->facemmap, "PLAYMMAP", 9);
|
||||
skin->wadnum = 0; // god what have you brought to this world
|
||||
skin->prefcolor = SKINCOLOR_BLUE;
|
||||
skin->localskin = false;
|
||||
skin->localnum = 0;
|
||||
|
||||
// SRB2kart
|
||||
skin->kartspeed = 8;
|
||||
skin->kartweight = 2;
|
||||
//
|
||||
|
||||
skin->spritedef.numframes = sprites[SPR_PLAY].numframes;
|
||||
skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes;
|
||||
skin->sprinfo = spriteinfo[SPR_PLAY];
|
||||
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0);
|
||||
|
||||
// Set values for Sonic skin
|
||||
Forceskin_cons_t[1].value = 0;
|
||||
Forceskin_cons_t[1].strvalue = skin->name;
|
||||
|
||||
//MD2 for sonic doesn't want to load in Linux.
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_AddPlayerMD2(0, false);
|
||||
#endif
|
||||
|
||||
// lets set it
|
||||
allskins[0] = skins[0];
|
||||
numallskins = 1;
|
||||
}
|
||||
|
||||
// returns true if the skin name is found (loaded from pwad)
|
||||
// warning return -1 if not found
|
||||
INT32 R_SkinAvailable(const char *name)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
if (stricmp(skins[i].name,name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// returns true if the skin name is found (loaded from pwad)
|
||||
// warning return -1 if not found
|
||||
INT32 R_AnySkinAvailable(const char *name)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < numallskins; i++)
|
||||
{
|
||||
if (stricmp(allskins[i].name,name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
INT32 R_LocalSkinAvailable(const char *name, boolean local)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (local)
|
||||
{
|
||||
for (i = 0; i < numlocalskins; i++)
|
||||
{
|
||||
if (stricmp(localskins[i].name,name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return R_SkinAvailable(name);
|
||||
}
|
||||
|
||||
// network code calls this when a 'skin change' is received
|
||||
boolean SetPlayerSkin(INT32 playernum, const char *skinname)
|
||||
{
|
||||
INT32 i;
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
// search in the skin list
|
||||
if (stricmp(skins[i].name, skinname) == 0)
|
||||
{
|
||||
SetPlayerSkinByNum(playernum, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsLocalPlayer(player))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname);
|
||||
else if(server || IsPlayerAdmin(consoleplayer))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname);
|
||||
|
||||
SetPlayerSkinByNum(playernum, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetLocalPlayerSkin(INT32 playernum, const char *skinname, consvar_t *cvar)
|
||||
{
|
||||
INT32 i;
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
if (stricmp(skinname, "none"))
|
||||
{
|
||||
for (i = 0; i < numlocalskins; i++)
|
||||
{
|
||||
// search in the localskin list
|
||||
if (stricmp(localskins[i].name, skinname) == 0)
|
||||
{
|
||||
player->localskin = 1 + i;
|
||||
player->skinlocal = true;
|
||||
if (player->mo)
|
||||
{
|
||||
player->mo->localskin = &localskins[i];
|
||||
player->mo->skinlocal = true;
|
||||
}
|
||||
|
||||
goto setcvar;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
// search in the skin list
|
||||
if (stricmp(skins[i].name, skinname) == 0)
|
||||
{
|
||||
player->localskin = 1 + i;
|
||||
player->skinlocal = false;
|
||||
if (player->mo)
|
||||
{
|
||||
player->mo->localskin = &skins[i];
|
||||
player->mo->skinlocal = false;
|
||||
}
|
||||
|
||||
goto setcvar;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->localskin = 0;
|
||||
player->skinlocal = false;
|
||||
if (player->mo)
|
||||
{
|
||||
player->mo->localskin = 0;
|
||||
player->mo->skinlocal = false;
|
||||
}
|
||||
}
|
||||
|
||||
setcvar:
|
||||
if (cvar != NULL)
|
||||
{
|
||||
if (player->localskin > 0)
|
||||
{
|
||||
CV_StealthSet(&cv_fakelocalskin, K_GetSkinArray(player->skinlocal)[player->localskin-1].name);
|
||||
CV_StealthSet(cvar, K_GetSkinArray(player->skinlocal)[player->localskin-1].name);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSet(&cv_fakelocalskin, "none");
|
||||
CV_StealthSet(cvar, "none");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same as SetPlayerSkin, but uses the skin #.
|
||||
// network code calls this when a 'skin change' is received
|
||||
void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
skin_t *skin = &skins[skinnum];
|
||||
|
||||
if (skinnum >= 0 && skinnum < numskins) // Make sure it exists!
|
||||
{
|
||||
player->skin = skinnum;
|
||||
if (player->mo)
|
||||
player->mo->skin = skin;
|
||||
|
||||
player->charflags = (UINT32)skin->flags;
|
||||
|
||||
// SRB2kart
|
||||
player->kartspeed = skin->kartspeed;
|
||||
player->kartweight = skin->kartweight;
|
||||
|
||||
if (player->mo)
|
||||
P_SetScale(player->mo, player->mo->scale);
|
||||
|
||||
demo_extradata[playernum] |= DXD_SKIN;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (P_IsLocalPlayer(player))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum);
|
||||
else if(server || IsPlayerAdmin(consoleplayer))
|
||||
CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
|
||||
|
||||
SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
|
||||
}
|
||||
|
||||
//
|
||||
// Add skins from a pwad, each skin preceded by 'S_SKIN' marker
|
||||
//
|
||||
|
||||
// Does the same is in w_wad, but check only for
|
||||
// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2..
|
||||
// for wad editors that don't like multiple resources of the same name)
|
||||
//
|
||||
static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
|
||||
{
|
||||
UINT16 i;
|
||||
const char *S_SKIN = "S_SKIN";
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
// scan forward, start at <startlump>
|
||||
if (startlump < wadfiles[wadid]->numlumps)
|
||||
{
|
||||
lump_p = wadfiles[wadid]->lumpinfo + startlump;
|
||||
for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name,S_SKIN,6)==0)
|
||||
return i;
|
||||
}
|
||||
return INT16_MAX; // not found
|
||||
}
|
||||
|
||||
//sort function for sorting skin names
|
||||
static int skinSortFunc(const void *a, const void *b) //tbh i have no clue what the naming conventions for local functions are
|
||||
{
|
||||
const skin_t *in1 = &skins[*(const UINT8 *)a];
|
||||
const skin_t *in2 = &skins[*(const UINT8 *)b];
|
||||
INT32 temp = 0;
|
||||
const UINT8 val_a = *((const UINT8 *)a);
|
||||
const UINT8 val_b = *((const UINT8 *)b);
|
||||
|
||||
//return (strcmp(in1->realname, in2->realname) < 0) || (strcmp(in1->realname, in2->realname) ==);
|
||||
|
||||
switch (cv_skinselectgridsort.value)
|
||||
{
|
||||
case SKINMENUSORT_REALNAME:
|
||||
//CONS_Printf("Sorting by realname\n");
|
||||
// check name
|
||||
if ((temp = strcmp(in1->realname, in2->realname)))
|
||||
return temp;
|
||||
// sort by internal name
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
|
||||
case SKINMENUSORT_NAME:
|
||||
//CONS_Printf("Sorting by name\n");
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
|
||||
case SKINMENUSORT_SPEED:
|
||||
//CONS_Printf("Sorting by speed\n");
|
||||
// check speed
|
||||
if (in1->kartspeed < in2->kartspeed)
|
||||
return -1;
|
||||
else if (in2->kartspeed < in1->kartspeed)
|
||||
return 1;
|
||||
// then check weight
|
||||
if (in1->kartweight < in2->kartweight)
|
||||
return -1;
|
||||
else if (in2->kartweight < in1->kartweight)
|
||||
return 1;
|
||||
// then check name
|
||||
if ((temp = strcmp(in1->realname, in2->realname)))
|
||||
return temp;
|
||||
// sort by internal name
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
|
||||
case SKINMENUSORT_WEIGHT:
|
||||
//CONS_Printf("Sorting by weight\n");
|
||||
// check weight
|
||||
if (in1->kartweight < in2->kartweight)
|
||||
return -1;
|
||||
else if (in2->kartweight < in1->kartweight)
|
||||
return 1;
|
||||
// then check speed
|
||||
if (in1->kartspeed < in2->kartspeed)
|
||||
return -1;
|
||||
else if (in2->kartspeed < in1->kartspeed)
|
||||
return 1;
|
||||
// then check name
|
||||
if ((temp = strcmp(in1->realname, in2->realname)))
|
||||
return temp;
|
||||
// sort by internal name
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
|
||||
case SKINMENUSORT_PREFCOLOR:
|
||||
//CONS_Printf("Sorting by prefcolor\n");
|
||||
// check prefcolor
|
||||
if (in1->prefcolor < in2->prefcolor)
|
||||
return -1;
|
||||
else if (in2->prefcolor < in1->prefcolor)
|
||||
return 1;
|
||||
// then check name
|
||||
if ((temp = strcmp(in1->realname, in2->realname)))
|
||||
return temp;
|
||||
// sort by internal name
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
|
||||
case SKINMENUSORT_ID:
|
||||
//CONS_Printf("Sorting by id\n");
|
||||
//how do i do by ID?????
|
||||
//wait why dont i just convert the inputs to UINT32s
|
||||
//please tell me im allowed to define variables in here since its a block
|
||||
|
||||
if (val_a == val_b)
|
||||
return 0;
|
||||
else if (val_a < val_b)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return strcmp(in1->name, in2->name);
|
||||
break;
|
||||
}
|
||||
//im scared this somehow will sometimes end up here so im gonna add this here just to be safe
|
||||
return strcmp(in1->name, in2->name);
|
||||
}
|
||||
|
||||
void sortSkinGrid(void)
|
||||
{
|
||||
//CONS_Printf("Sorting skin list (%d)...\n", cv_skinselectgridsort.value);
|
||||
qs22j(skinsorted, numskins, sizeof(UINT8), skinSortFunc);
|
||||
}
|
||||
|
||||
//
|
||||
// Find skin sprites, sounds & optional status bar face, & add them
|
||||
//
|
||||
void R_AddSkins(UINT16 wadnum, boolean local)
|
||||
{
|
||||
UINT16 lump, lastlump = 0;
|
||||
char *buf;
|
||||
char *buf2;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
skin_t *skin;
|
||||
boolean hudname, realname;
|
||||
|
||||
#define lnumskins (local ? numlocalskins : numskins)
|
||||
|
||||
//
|
||||
// search for all skin markers in pwad
|
||||
//
|
||||
|
||||
while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
|
||||
{
|
||||
// advance by default
|
||||
lastlump = lump + 1;
|
||||
|
||||
if (!local && numskins >= MAXSKINS)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Unable to add skin, too many characters are loaded (%d maximum)\n"), MAXSKINS);
|
||||
continue; // so we know how many skins couldn't be added
|
||||
}
|
||||
if (local && numlocalskins >= MAXLOCALSKINS)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Unable to add localskin, too many localskins are loaded (%d maximum)\n"), MAXLOCALSKINS);
|
||||
continue; // so we know how many skins couldn't be added
|
||||
}
|
||||
|
||||
buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
// for strtok
|
||||
buf2 = malloc(size+1);
|
||||
if (!buf2)
|
||||
I_Error("R_AddSkins: No more free memory\n");
|
||||
M_Memcpy(buf2,buf,size);
|
||||
buf2[size] = '\0';
|
||||
|
||||
// set defaults
|
||||
skin = &K_GetSkinArray(local)[lnumskins];
|
||||
Sk_SetDefaultValue(skin, local);
|
||||
skin->wadnum = wadnum;
|
||||
hudname = realname = false;
|
||||
// parse
|
||||
stoken = strtok (buf2, "\r\n= ");
|
||||
while (stoken)
|
||||
{
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto next_token; // find the real next token
|
||||
}
|
||||
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
|
||||
if (!value)
|
||||
I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
|
||||
|
||||
if (!stricmp(stoken, "name"))
|
||||
{
|
||||
// the skin name must uniquely identify a single skin
|
||||
// I'm lazy so if name is already used I leave the 'skin x'
|
||||
// default skin name set in Sk_SetDefaultValue
|
||||
if (R_LocalSkinAvailable(value, local) == -1)
|
||||
{
|
||||
STRBUFCPY(skin->name, value);
|
||||
strlwr(skin->name);
|
||||
}
|
||||
// I'm not lazy, so if the name is already used I make the name 'namex'
|
||||
// using the default skin name's number set above
|
||||
else
|
||||
{
|
||||
const size_t stringspace =
|
||||
strlen(value) + sizeof lnumskins + 1;
|
||||
char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL);
|
||||
snprintf(value2, stringspace,
|
||||
"%s%d", value, lnumskins);
|
||||
value2[stringspace - 1] = '\0';
|
||||
if (R_LocalSkinAvailable(value2, local) == -1)
|
||||
{
|
||||
STRBUFCPY(skin->name,
|
||||
value2);
|
||||
strlwr(skin->name);
|
||||
}
|
||||
Z_Free(value2);
|
||||
}
|
||||
|
||||
// copy to hudname and fullname as a default.
|
||||
if (!realname)
|
||||
{
|
||||
STRBUFCPY(skin->realname, skin->name);
|
||||
for (value = skin->realname; *value; value++)
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
}
|
||||
if (!hudname)
|
||||
{
|
||||
STRBUFCPY(skin->hudname, skin->name);
|
||||
strupr(skin->hudname);
|
||||
for (value = skin->hudname; *value; value++)
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
}
|
||||
}
|
||||
else if (!stricmp(stoken, "realname"))
|
||||
{ // Display name (eg. "Knuckles")
|
||||
realname = true;
|
||||
STRBUFCPY(skin->realname, value);
|
||||
for (value = skin->realname; *value; value++)
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
if (!hudname)
|
||||
STRBUFCPY(skin->hudname, skin->realname);
|
||||
}
|
||||
else if (!stricmp(stoken, "hudname"))
|
||||
{ // Life icon name (eg. "K.T.E")
|
||||
hudname = true;
|
||||
STRBUFCPY(skin->hudname, value);
|
||||
for (value = skin->hudname; *value; value++)
|
||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
||||
if (!realname)
|
||||
STRBUFCPY(skin->realname, skin->hudname);
|
||||
}
|
||||
|
||||
else if (!stricmp(stoken, "sprite"))
|
||||
{
|
||||
strupr(value);
|
||||
memcpy(skin->sprite, value, sizeof skin->sprite);
|
||||
}
|
||||
else if (!stricmp(stoken, "facerank"))
|
||||
{
|
||||
strupr(value);
|
||||
memcpy(skin->facerank, value, sizeof(skin->facerank)-1);
|
||||
skin->facerank[sizeof(skin->facerank)-1] = '\0';
|
||||
}
|
||||
else if (!stricmp(stoken, "facewant"))
|
||||
{
|
||||
strupr(value);
|
||||
memcpy(skin->facewant, value, sizeof(skin->facewant)-1);
|
||||
skin->facewant[sizeof(skin->facewant)-1] = '\0';
|
||||
}
|
||||
else if (!stricmp(stoken, "facemmap"))
|
||||
{
|
||||
strupr(value);
|
||||
strncpy(skin->facemmap, value, sizeof(skin->facemmap)-1);
|
||||
skin->facemmap[sizeof(skin->facemmap)-1] = '\0';
|
||||
}
|
||||
|
||||
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
|
||||
// character type identification
|
||||
FULLPROCESS(flags)
|
||||
#undef FULLPROCESS
|
||||
|
||||
#define GETKARTSTAT(field) \
|
||||
else if (!stricmp(stoken, #field)) \
|
||||
{ \
|
||||
skin->field = atoi(value); \
|
||||
if (skin->field < 1) skin->field = 1; \
|
||||
if (skin->field > 9) skin->field = 9; \
|
||||
}
|
||||
GETKARTSTAT(kartspeed)
|
||||
GETKARTSTAT(kartweight)
|
||||
#undef GETKARTSTAT
|
||||
|
||||
// custom translation table
|
||||
else if (!stricmp(stoken, "startcolor"))
|
||||
skin->starttranscolor = atoi(value);
|
||||
|
||||
else if (!stricmp(stoken, "prefcolor"))
|
||||
skin->prefcolor = K_GetKartColorByName(value);
|
||||
else if (!stricmp(stoken, "highresscale"))
|
||||
skin->highresscale = FLOAT_TO_FIXED(atof(value));
|
||||
else
|
||||
{
|
||||
INT32 found = false;
|
||||
sfxenum_t i;
|
||||
// copy name of sounds that are remapped
|
||||
// for this skin
|
||||
for (i = 0; i < sfx_skinsoundslot0; i++)
|
||||
{
|
||||
if (!S_sfx[i].name)
|
||||
continue;
|
||||
if (S_sfx[i].skinsound != -1
|
||||
&& !stricmp(S_sfx[i].name,
|
||||
stoken + 2))
|
||||
{
|
||||
skin->soundsid[S_sfx[i].skinsound] =
|
||||
S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump# %d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
}
|
||||
next_token:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
}
|
||||
free(buf2);
|
||||
|
||||
lump++; // if no sprite defined use spirte just after this one
|
||||
if (skin->sprite[0] == '\0')
|
||||
{
|
||||
const char *csprname = W_CheckNameForNumPwad(wadnum, lump);
|
||||
|
||||
// skip to end of this skin's frames
|
||||
lastlump = lump;
|
||||
while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0)
|
||||
lastlump++;
|
||||
// allocate (or replace) sprite frames, and set spritedef
|
||||
R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump);
|
||||
}
|
||||
else
|
||||
{
|
||||
// search in the normal sprite tables
|
||||
size_t name;
|
||||
boolean found = false;
|
||||
const char *sprname = skin->sprite;
|
||||
for (name = 0;sprnames[name][0] != '\0';name++)
|
||||
if (strncmp(sprnames[name], sprname, 4) == 0)
|
||||
{
|
||||
found = true;
|
||||
skin->spritedef = sprites[name];
|
||||
}
|
||||
|
||||
// not found so make a new one
|
||||
// go through the entire current wad looking for our sprite
|
||||
// don't just mass add anything beginning with our four letters.
|
||||
// "HOODFACE" is not a sprite name.
|
||||
if (!found)
|
||||
{
|
||||
UINT16 localllump = 0, lstart = UINT16_MAX, lend = UINT16_MAX;
|
||||
const char *lname;
|
||||
|
||||
while ((lname = W_CheckNameForNumPwad(wadnum,localllump)))
|
||||
{
|
||||
// If this is a valid sprite...
|
||||
if (!memcmp(lname,sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8')
|
||||
{
|
||||
if (lstart == UINT16_MAX)
|
||||
lstart = localllump;
|
||||
// If already set do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lstart != UINT16_MAX)
|
||||
{
|
||||
lend = localllump;
|
||||
break;
|
||||
}
|
||||
// If not already set do nothing
|
||||
}
|
||||
++localllump;
|
||||
}
|
||||
|
||||
R_AddSingleSpriteDef(sprname, &skin->spritedef, wadnum, lstart, lend);
|
||||
}
|
||||
|
||||
// I don't particularly care about skipping to the end of the used frames.
|
||||
// We could be using frames from ANYWHERE in the current WAD file, including
|
||||
// right before us, which is a terrible idea.
|
||||
// So just let the function in the while loop take care of it for us.
|
||||
}
|
||||
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
|
||||
#ifdef SKINVALUES
|
||||
(local ? localskin_cons_t : skin_cons_t)[lnumskins].value = lnumskins;
|
||||
(local ? localskin_cons_t : skin_cons_t)[lnumskins].strvalue = skin->name;
|
||||
#endif
|
||||
|
||||
if (!local)
|
||||
{
|
||||
// Update the forceskin possiblevalues
|
||||
Forceskin_cons_t[numskins+1].value = numskins;
|
||||
Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name;
|
||||
skin->localskin = false;
|
||||
skin->localnum = numskins;
|
||||
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins);
|
||||
}
|
||||
else
|
||||
{
|
||||
skin->localskin = true;
|
||||
skin->localnum = numlocalskins;
|
||||
ST_LoadLocalFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numlocalskins);
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_AddPlayerMD2(lnumskins, local);
|
||||
#endif
|
||||
if (!local)
|
||||
{
|
||||
skinstats[skin->kartspeed-1][skin->kartweight-1][skinstatscount[skin->kartspeed-1][skin->kartweight-1]] = numskins;
|
||||
CONS_Debug(DBG_SETUP, M_GetText("Added %d to %d, %d\n"), numskins, skin->kartweight, skin->kartweight);
|
||||
skinstatscount[skin->kartspeed-1][skin->kartweight-1]++;
|
||||
CONS_Debug(DBG_SETUP, M_GetText("Incremented %d, %d to %d\n"), skin->kartspeed, skin->kartweight, skinstatscount[skin->kartspeed - 1][skin->kartweight - 1]);
|
||||
skinsorted[numskins] = numskins;
|
||||
}
|
||||
|
||||
allskins[numallskins] = K_GetSkinArray(local)[lnumskins];
|
||||
|
||||
local ? numlocalskins++ : numskins++;
|
||||
numallskins++;
|
||||
}
|
||||
|
||||
#undef lnumskins
|
||||
//sortSkinGrid();
|
||||
|
||||
return;
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Vivian "toastergrl" Grannell.
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1996 by id Software, Inc.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file r_skins.h
|
||||
/// \brief Skins stuff
|
||||
|
||||
#ifndef __R_SKINS__
|
||||
#define __R_SKINS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_player.h"
|
||||
#include "sounds.h"
|
||||
#include "r_patch.h"
|
||||
|
||||
// "Left" and "Right" character symbols for additional rotation functionality
|
||||
#define ROT_L ('L' - '0')
|
||||
#define ROT_R ('R' - '0')
|
||||
|
||||
#define SKINNAMESIZE 16
|
||||
// should be all lowercase!! S_SKIN processing does a strlwr
|
||||
#define DEFAULTSKIN "sonic"
|
||||
#define DEFAULTSKIN2 "tails" // secondary player
|
||||
#define DEFAULTSKIN3 "knuckles" // third player
|
||||
#define DEFAULTSKIN4 "eggman" // fourth player
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin
|
||||
spritedef_t spritedef;
|
||||
spriteinfo_t sprinfo;
|
||||
UINT16 wadnum;
|
||||
char sprite[4]; // Sprite name, if seperated from S_SKIN.
|
||||
skinflags_t flags;
|
||||
|
||||
char realname[SKINNAMESIZE+1]; // Display name for level completion.
|
||||
char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
|
||||
char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps
|
||||
|
||||
// SRB2kart
|
||||
UINT8 kartspeed;
|
||||
UINT8 kartweight;
|
||||
//
|
||||
|
||||
// Definable color translation table
|
||||
UINT8 starttranscolor;
|
||||
UINT8 prefcolor;
|
||||
fixed_t highresscale; // scale of highres, default is 0.5
|
||||
|
||||
// specific sounds per skin
|
||||
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
|
||||
|
||||
boolean localskin;
|
||||
INT32 localnum;
|
||||
} skin_t;
|
||||
|
||||
extern CV_PossibleValue_t Forceskin_cons_t[];
|
||||
|
||||
extern INT32 numskins;
|
||||
extern INT32 numlocalskins;
|
||||
extern INT32 numallskins;
|
||||
extern skin_t skins[MAXSKINS];
|
||||
extern UINT8 skinstats[9][9][MAXSKINS];
|
||||
extern UINT8 skinstatscount[9][9];
|
||||
extern UINT8 skinsorted[MAXSKINS];
|
||||
|
||||
extern skin_t localskins[MAXLOCALSKINS];
|
||||
extern skin_t allskins[MAXSKINS+MAXLOCALSKINS];
|
||||
|
||||
//faB: find sprites in wadfile, replace existing, add new ones
|
||||
// (only sprites from namelist are added or replaced)
|
||||
void R_AddSpriteDefs(UINT16 wadnum);
|
||||
|
||||
void R_InitSkins(void);
|
||||
void R_AddSkins(UINT16 wadnum, boolean local);
|
||||
|
||||
INT32 R_SkinAvailable(const char *name);
|
||||
INT32 R_AnySkinAvailable(const char *name);
|
||||
INT32 R_LocalSkinAvailable(const char *name, boolean local);
|
||||
|
||||
// had to move those here Zzz...
|
||||
INT32 K_GetSkinNum(player_t *player);
|
||||
INT32 K_GetMobjSkinNum(const skin_t *skin, boolean local);
|
||||
skin_t *K_GetPlayerSkin(player_t *player);
|
||||
skin_t *K_GetMobjSkin(const mobj_t *mobj);
|
||||
patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum);
|
||||
skin_t *K_GetSkinArray(boolean local);
|
||||
|
||||
void sortSkinGrid(void);
|
||||
|
||||
boolean SetPlayerSkin(INT32 playernum,const char *skinname);
|
||||
void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
|
||||
void SetLocalPlayerSkin(INT32 playernum,const char *skinname, consvar_t *cvar);
|
||||
|
||||
char *GetPlayerFacePic(INT32 skinnum);
|
||||
|
||||
// Functions to go from sprite character ID to frame number
|
||||
// for 2.1 compatibility this still uses the old 'A' + frame code
|
||||
// The use of symbols tends to be painful for wad editors though
|
||||
// So the future version of this tries to avoid using symbols
|
||||
// as much as possible while also defining all 64 slots in a sane manner
|
||||
// 2.1: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]]
|
||||
// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]]
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
return 'A' + frame;
|
||||
#else
|
||||
if (frame < 26) return 'A' + frame;
|
||||
if (frame < 36) return '0' + (frame - 26);
|
||||
if (frame < 62) return 'a' + (frame - 36);
|
||||
if (frame == 62) return '!';
|
||||
if (frame == 63) return '@';
|
||||
return '\xFF';
|
||||
#endif
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
|
||||
return cn - 'A';
|
||||
#else
|
||||
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
|
||||
if (cn >= '0' && cn <= '9') return (cn - '0') + 26;
|
||||
if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36;
|
||||
if (cn == '!') return 62;
|
||||
if (cn == '@') return 63;
|
||||
return 255;
|
||||
#endif
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation)
|
||||
{
|
||||
return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__R_SKINS__
|
||||
+20
-6
@@ -41,6 +41,10 @@ INT32 skytexture;
|
||||
*/
|
||||
INT32 skytexturemid;
|
||||
|
||||
/** \brief the x offset of the sky texture
|
||||
*/
|
||||
INT32 skytextureoffset;
|
||||
|
||||
/** \brief the scale of the sky
|
||||
*/
|
||||
fixed_t skyscale;
|
||||
@@ -50,6 +54,7 @@ fixed_t skyscale;
|
||||
INT32 levelskynum;
|
||||
INT32 globallevelskynum;
|
||||
|
||||
|
||||
/** \brief The R_SetupSkyDraw function
|
||||
|
||||
Called at loadlevel after skytexture is set, or when sky texture changes.
|
||||
@@ -61,12 +66,19 @@ INT32 globallevelskynum;
|
||||
*/
|
||||
void R_SetupSkyDraw(void)
|
||||
{
|
||||
// the horizon line in a 256x128 sky texture
|
||||
skytexturemid = (textures[skytexture]->height/2)<<FRACBITS;
|
||||
// the horizon line in the sky texture
|
||||
skytexturemid = (textures[skytexture]->height / 2) << FRACBITS;
|
||||
skytextureoffset = 0;
|
||||
|
||||
// get the right drawer, it was set by screen.c, depending on the
|
||||
// current video mode bytes per pixel (quick fix)
|
||||
wallcolfunc = walldrawerfunc;
|
||||
if (textures[skytexture]->type == TEXTURETYPE_SINGLEPATCH)
|
||||
{
|
||||
// Sal: Allow for sky offsets
|
||||
texpatch_t *const tex_patch = &textures[skytexture]->patches[0];
|
||||
patch_t *patch = W_CachePatchNumPwad(tex_patch->wad, tex_patch->lump, PU_CACHE);
|
||||
|
||||
skytexturemid += (patch->topoffset << FRACBITS);
|
||||
skytextureoffset += (patch->leftoffset << FRACBITS);
|
||||
}
|
||||
|
||||
R_SetSkyScale();
|
||||
}
|
||||
@@ -79,5 +91,7 @@ void R_SetupSkyDraw(void)
|
||||
*/
|
||||
void R_SetSkyScale(void)
|
||||
{
|
||||
skyscale = FixedDiv(fovtan, FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT));
|
||||
//skyscale = FixedDiv(fovtan, FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT));
|
||||
fixed_t difference = vid.fdupx-(vid.dupx<<FRACBITS);
|
||||
skyscale = FixedDiv(fovtan, vid.fdupx+difference);
|
||||
}
|
||||
+9
-1
@@ -14,6 +14,10 @@
|
||||
#ifndef __R_SKY__
|
||||
#define __R_SKY__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "m_fixed.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
@@ -26,7 +30,7 @@
|
||||
/// \brief The sky map is 256*128*4 maps.
|
||||
#define ANGLETOSKYSHIFT 22
|
||||
|
||||
extern INT32 skytexture, skytexturemid;
|
||||
extern INT32 skytexture, skytexturemid, skytextureoffset;
|
||||
extern fixed_t skyscale;
|
||||
|
||||
extern INT32 skyflatnum;
|
||||
@@ -38,4 +42,8 @@ void R_SetupSkyDraw(void);
|
||||
|
||||
void R_SetSkyScale(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+10
-1
@@ -33,7 +33,16 @@ struct rastery_s
|
||||
fixed_t tx1, ty1;
|
||||
fixed_t tx2, ty2; // start/end points in texture at this line
|
||||
};
|
||||
static struct rastery_s rastertab[MAXVIDHEIGHT];
|
||||
static struct rastery_s *rastertab;
|
||||
|
||||
static boolean *cliptable;
|
||||
|
||||
void R_AllocFloorSpriteTables(void)
|
||||
{
|
||||
//cliptable = Z_Realloc(cliptable, sizeof(*cliptable) * (viewwidth + 1), PU_STATIC, NULL);
|
||||
rastertab = Z_Realloc(rastertab, sizeof(*rastertab) * viewheight, PU_STATIC, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void prepare_rastertab(void);
|
||||
#endif
|
||||
|
||||
@@ -75,4 +75,6 @@ void R_ClearVisibleFloorSplats(void);
|
||||
void R_AddVisibleFloorSplats(subsector_t *subsec);
|
||||
void R_DrawVisibleFloorSplats(void);
|
||||
|
||||
void R_AllocFloorSpriteTables(void);
|
||||
|
||||
#endif /*__R_SPLATS_H__*/
|
||||
+1
-1
@@ -104,7 +104,7 @@ extern angle_t clipangle;
|
||||
extern angle_t doubleclipangle;
|
||||
|
||||
extern INT32 viewangletox[FINEANGLES/2];
|
||||
extern angle_t xtoviewangle[MAXVIDWIDTH+1];
|
||||
extern angle_t *xtoviewangle;
|
||||
|
||||
extern fixed_t rw_distance;
|
||||
extern angle_t rw_normalangle;
|
||||
|
||||
+380
-1051
File diff suppressed because it is too large.
Load diff
+32
-133
@@ -1,4 +1,4 @@
|
||||
// SONIC ROBO BLAST 2
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
@@ -14,13 +14,12 @@
|
||||
#ifndef __R_THINGS__
|
||||
#define __R_THINGS__
|
||||
|
||||
#include "sounds.h"
|
||||
#include "r_plane.h"
|
||||
#include "r_patch.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// "Left" and "Right" character symbols for additional rotation functionality
|
||||
#define ROT_L ('L' - '0')
|
||||
#define ROT_R ('R' - '0')
|
||||
#include "r_plane.h"
|
||||
#include "r_portal.h"
|
||||
|
||||
// number of sprite lumps for spritewidth,offset,topoffset lookup tables
|
||||
// Fab: this is a hack : should allocate the lookup tables per sprite
|
||||
@@ -44,8 +43,8 @@
|
||||
|
||||
// Constant arrays used for psprite clipping
|
||||
// and initializing clipping.
|
||||
extern INT16 negonearray[MAXVIDWIDTH];
|
||||
extern INT16 screenheightarray[MAXVIDWIDTH];
|
||||
extern INT16 *negonearray;
|
||||
extern INT16 *screenheightarray;
|
||||
|
||||
// vars for R_DrawMaskedColumn
|
||||
extern INT16 *mfloorclip;
|
||||
@@ -62,76 +61,33 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle);
|
||||
|
||||
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
|
||||
|
||||
void R_DrawMaskedColumn(column_t *column);
|
||||
void R_SortVisSprites(void);
|
||||
|
||||
//faB: find sprites in wadfile, replace existing, add new ones
|
||||
// (only sprites from namelist are added or replaced)
|
||||
void R_AddSpriteDefs(UINT16 wadnum);
|
||||
|
||||
//SoM: 6/5/2000: Light sprites correctly!
|
||||
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
|
||||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||
void R_AddPrecipitationSprites(void);
|
||||
void R_InitSprites(void);
|
||||
void R_ClearSprites(void);
|
||||
void R_DrawMasked(void);
|
||||
|
||||
boolean R_ThingVisible (mobj_t *thing);
|
||||
boolean R_ThingWithinDist (mobj_t *thing, INT32 limit_dist);
|
||||
|
||||
boolean R_ThingIsFullBright (mobj_t *thing);
|
||||
boolean R_ThingIsSemiBright (mobj_t *thing);
|
||||
boolean R_ThingIsFullDark (mobj_t *thing);
|
||||
|
||||
// -----------
|
||||
// SKINS STUFF
|
||||
// -----------
|
||||
#define SKINNAMESIZE 16
|
||||
// should be all lowercase!! S_SKIN processing does a strlwr
|
||||
#define DEFAULTSKIN "sonic"
|
||||
#define DEFAULTSKIN2 "tails" // secondary player
|
||||
#define DEFAULTSKIN3 "knuckles" // third player
|
||||
#define DEFAULTSKIN4 "eggman" // fourth player
|
||||
|
||||
/** Used to count the amount of masked elements
|
||||
* per portal to later group them in separate
|
||||
* drawnode lists.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin
|
||||
spritedef_t spritedef;
|
||||
spriteinfo_t sprinfo;
|
||||
UINT16 wadnum;
|
||||
char sprite[4]; // Sprite name, if seperated from S_SKIN.
|
||||
skinflags_t flags;
|
||||
size_t drawsegs[2];
|
||||
size_t vissprites[2];
|
||||
fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */
|
||||
sector_t* viewsector;
|
||||
} maskcount_t;
|
||||
|
||||
char realname[SKINNAMESIZE+1]; // Display name for level completion.
|
||||
char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
|
||||
char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps
|
||||
void R_DrawMasked(maskcount_t* masks, INT32 nummasks);
|
||||
|
||||
// SRB2kart
|
||||
UINT8 kartspeed;
|
||||
UINT8 kartweight;
|
||||
//
|
||||
boolean R_ThingVisible(mobj_t *thing);
|
||||
boolean R_ThingWithinDist(mobj_t *thing, INT32 limit_dist);
|
||||
|
||||
// Definable color translation table
|
||||
UINT8 starttranscolor;
|
||||
UINT8 prefcolor;
|
||||
fixed_t highresscale; // scale of highres, default is 0.5
|
||||
|
||||
// specific sounds per skin
|
||||
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
|
||||
|
||||
boolean localskin;
|
||||
INT32 localnum;
|
||||
} skin_t;
|
||||
|
||||
extern CV_PossibleValue_t Forceskin_cons_t[];
|
||||
|
||||
// had to move those here Zzz...
|
||||
INT32 K_GetSkinNum(player_t *player);
|
||||
INT32 K_GetMobjSkinNum(const skin_t *skin, boolean local);
|
||||
skin_t *K_GetPlayerSkin(player_t *player);
|
||||
skin_t *K_GetMobjSkin(const mobj_t *mobj);
|
||||
patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum);
|
||||
skin_t *K_GetSkinArray(boolean local);
|
||||
boolean R_ThingIsFullBright(mobj_t *thing);
|
||||
boolean R_ThingIsSemiBright(mobj_t *thing);
|
||||
boolean R_ThingIsFullDark(mobj_t *thing);
|
||||
|
||||
// -----------
|
||||
// NOT SKINS STUFF !
|
||||
@@ -201,7 +157,7 @@ typedef struct vissprite_s
|
||||
fixed_t spritexscale, spriteyscale;
|
||||
fixed_t spritexoffset, spriteyoffset;
|
||||
|
||||
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
|
||||
INT16 *clipbot, *cliptop;
|
||||
|
||||
boolean precip;
|
||||
boolean vflip; // Flip vertically
|
||||
@@ -211,10 +167,14 @@ typedef struct vissprite_s
|
||||
|
||||
extern UINT32 visspritecount, numvisiblesprites;
|
||||
|
||||
void R_ClipSprites(void);
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
|
||||
|
||||
void R_AllocVisSpriteMemory(void);
|
||||
|
||||
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
|
||||
|
||||
void R_InitDrawNodes(void);
|
||||
|
||||
// ----------
|
||||
// DRAW NODES
|
||||
// ----------
|
||||
@@ -233,69 +193,8 @@ typedef struct drawnode_s
|
||||
struct drawnode_s *prev;
|
||||
} drawnode_t;
|
||||
|
||||
extern INT32 numskins;
|
||||
extern INT32 numlocalskins;
|
||||
extern INT32 numallskins;
|
||||
extern skin_t skins[MAXSKINS];
|
||||
extern UINT8 skinstats[9][9][MAXSKINS];
|
||||
extern UINT8 skinstatscount[9][9];
|
||||
extern UINT8 skinsorted[MAXSKINS];
|
||||
|
||||
void sortSkinGrid(void);
|
||||
extern skin_t localskins[MAXLOCALSKINS];
|
||||
extern skin_t allskins[MAXSKINS+MAXLOCALSKINS];
|
||||
|
||||
boolean SetPlayerSkin(INT32 playernum,const char *skinname);
|
||||
void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
|
||||
void SetLocalPlayerSkin(INT32 playernum,const char *skinname, consvar_t *cvar);
|
||||
INT32 R_SkinAvailable(const char *name);
|
||||
INT32 R_AnySkinAvailable(const char *name);
|
||||
INT32 R_LocalSkinAvailable(const char *name, boolean local);
|
||||
void R_AddSkins(UINT16 wadnum, boolean local);
|
||||
|
||||
void R_InitDrawNodes(void);
|
||||
|
||||
char *GetPlayerFacePic(INT32 skinnum);
|
||||
|
||||
// Functions to go from sprite character ID to frame number
|
||||
// for 2.1 compatibility this still uses the old 'A' + frame code
|
||||
// The use of symbols tends to be painful for wad editors though
|
||||
// So the future version of this tries to avoid using symbols
|
||||
// as much as possible while also defining all 64 slots in a sane manner
|
||||
// 2.1: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]]
|
||||
// Future: [[ ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@ ]]
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE char R_Frame2Char(UINT8 frame)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
return 'A' + frame;
|
||||
#else
|
||||
if (frame < 26) return 'A' + frame;
|
||||
if (frame < 36) return '0' + (frame - 26);
|
||||
if (frame < 62) return 'a' + (frame - 36);
|
||||
if (frame == 62) return '!';
|
||||
if (frame == 63) return '@';
|
||||
return '\xFF';
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
|
||||
{
|
||||
#if 1 // 2.1 compat
|
||||
if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead
|
||||
return cn - 'A';
|
||||
#else
|
||||
if (cn >= 'A' && cn <= 'Z') return cn - 'A';
|
||||
if (cn >= '0' && cn <= '9') return (cn - '0') + 26;
|
||||
if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36;
|
||||
if (cn == '!') return 62;
|
||||
if (cn == '@') return 63;
|
||||
return 255;
|
||||
#endif
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation)
|
||||
{
|
||||
return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R));
|
||||
}
|
||||
|
||||
#endif //__R_THINGS__
|
||||
+69
-55
@@ -33,23 +33,6 @@
|
||||
// SRB2Kart
|
||||
#include "r_fps.h" // R_GetFramerateCap
|
||||
|
||||
// --------------------------------------------
|
||||
// assembly or c drawer routines for 8bpp/16bpp
|
||||
// --------------------------------------------
|
||||
void (*wallcolfunc)(void); // new wall column drawer to draw posts >128 high
|
||||
void (*colfunc)(void); // standard column, up to 128 high posts
|
||||
|
||||
void (*basecolfunc)(void);
|
||||
void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer
|
||||
void (*transcolfunc)(void); // translation column drawer
|
||||
void (*shadecolfunc)(void); // smokie test..
|
||||
void (*spanfunc)(void); // span drawer, use a 64x64 tile
|
||||
void (*splatfunc)(void); // span drawer w/ transparency
|
||||
void (*basespanfunc)(void); // default span func for color mode
|
||||
void (*transtransfunc)(void); // translucent translated column drawer
|
||||
void (*twosmultipatchfunc)(void); // for cols with transparent pixels
|
||||
void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency
|
||||
|
||||
// ------------------
|
||||
// global video state
|
||||
// ------------------
|
||||
@@ -65,6 +48,8 @@ consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL,
|
||||
consvar_t cv_vhseffect = {"vhspause", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shittyscreen = {"televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_parallelsoftware = {"parallelsoftware", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t votescale_cons_t[] = {{0, "Vanilla"}, {1, "Adaptive"}, {2, "VerticalFill"}, {3, "HorizontalFill"}, {0, NULL}};
|
||||
consvar_t cv_votebgscaling = {"votebgscaling", "Adaptive", CV_SAVE, votescale_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
@@ -89,13 +74,41 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL
|
||||
// SCREEN VARIABLES
|
||||
// =========================================================================
|
||||
|
||||
INT32 scr_bpp; // current video mode bytes per pixel
|
||||
UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init()
|
||||
|
||||
// =========================================================================
|
||||
|
||||
// Short and Tall sky drawer, for the current color mode
|
||||
void (*walldrawerfunc)(void);
|
||||
static void SCR_SetDrawFuncs(void)
|
||||
{
|
||||
//
|
||||
// setup the right draw routines
|
||||
//
|
||||
|
||||
spanfuncs[BASEDRAWFUNC] = R_DrawSpan;
|
||||
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan;
|
||||
spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawSpan_Tilted;
|
||||
spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTranslucentSpan_Tilted;
|
||||
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat;
|
||||
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat;
|
||||
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawSplat_Tilted;
|
||||
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTranslucentSpan_Tilted;
|
||||
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan;
|
||||
spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTranslucentWaterSpan_Tilted;
|
||||
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan;
|
||||
spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawFogSpan_Tilted;
|
||||
|
||||
colfuncs[BASEDRAWFUNC] = R_DrawColumn;
|
||||
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn;
|
||||
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn;
|
||||
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed;
|
||||
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn;
|
||||
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn;
|
||||
|
||||
R_SetColumnFunc(BASEDRAWFUNC);
|
||||
R_SetSpanFunc(BASEDRAWFUNC);
|
||||
}
|
||||
|
||||
void SCR_SetMode(void)
|
||||
{
|
||||
@@ -109,22 +122,47 @@ void SCR_SetMode(void)
|
||||
|
||||
V_SetPalette(0);
|
||||
|
||||
spanfunc = basespanfunc = R_DrawSpan_8;
|
||||
splatfunc = R_DrawSplat_8;
|
||||
transcolfunc = R_DrawTranslatedColumn_8;
|
||||
transtransfunc = R_DrawTranslatedTranslucentColumn_8;
|
||||
|
||||
colfunc = basecolfunc = R_DrawColumn_8;
|
||||
shadecolfunc = R_DrawShadeColumn_8;
|
||||
fuzzcolfunc = R_DrawTranslucentColumn_8;
|
||||
walldrawerfunc = R_DrawWallColumn_8;
|
||||
twosmultipatchfunc = R_Draw2sMultiPatchColumn_8;
|
||||
twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8;
|
||||
SCR_SetDrawFuncs();
|
||||
|
||||
// set the apprpriate drawer for the sky (tall or INT16)
|
||||
setmodeneeded = 0;
|
||||
}
|
||||
|
||||
void R_SetColumnFunc(size_t id)
|
||||
{
|
||||
I_Assert(id < COLDRAWFUNC_MAX);
|
||||
|
||||
colfunctype = id;
|
||||
colfunc = colfuncs[id];
|
||||
}
|
||||
|
||||
void R_SetSpanFunc(size_t id)
|
||||
{
|
||||
I_Assert(id < SPANDRAWFUNC_MAX);
|
||||
spanfunc = spanfuncs[id];
|
||||
}
|
||||
|
||||
boolean R_CheckColumnFunc(size_t id)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (colfunc == NULL)
|
||||
{
|
||||
// Shouldn't happen.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < COLDRAWFUNC_MAX; i++)
|
||||
{
|
||||
if (colfunc == colfuncs[id])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// do some initial settings for the game loading screen
|
||||
//
|
||||
void SCR_Startup(void)
|
||||
@@ -148,19 +186,9 @@ void SCR_Startup(void)
|
||||
|
||||
vid.meddupx = (UINT8)(vid.dupx >> 1) + 1;
|
||||
vid.meddupy = (UINT8)(vid.dupy >> 1) + 1;
|
||||
#ifdef HWRENDER
|
||||
vid.fmeddupx = vid.meddupx*FRACUNIT;
|
||||
vid.fmeddupy = vid.meddupy*FRACUNIT;
|
||||
#endif
|
||||
|
||||
vid.smalldupx = (UINT8)(vid.dupx / 3) + 1;
|
||||
vid.smalldupy = (UINT8)(vid.dupy / 3) + 1;
|
||||
#ifdef HWRENDER
|
||||
vid.fsmalldupx = vid.smalldupx*FRACUNIT;
|
||||
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
|
||||
#endif
|
||||
|
||||
vid.baseratio = FRACUNIT;
|
||||
|
||||
V_Init();
|
||||
CV_RegisterVar(&cv_highreshudscale);
|
||||
@@ -205,9 +233,6 @@ void SCR_Recalc(void)
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
// bytes per pixel quick access
|
||||
scr_bpp = vid.bpp;
|
||||
|
||||
// scale 1,2,3 times in x and y the patches for the menus and overlays...
|
||||
// calculated once and for all, used by routines in v_video.c
|
||||
vid.dupx = vid.width / BASEVIDWIDTH;
|
||||
@@ -226,22 +251,11 @@ void SCR_Recalc(void)
|
||||
|
||||
vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy);
|
||||
|
||||
//vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS);
|
||||
vid.baseratio = FRACUNIT;
|
||||
|
||||
vid.meddupx = (UINT8)(vid.dupx >> 1) + 1;
|
||||
vid.meddupy = (UINT8)(vid.dupy >> 1) + 1;
|
||||
#ifdef HWRENDER
|
||||
vid.fmeddupx = vid.meddupx*FRACUNIT;
|
||||
vid.fmeddupy = vid.meddupy*FRACUNIT;
|
||||
#endif
|
||||
|
||||
vid.smalldupx = (UINT8)(vid.dupx / 3) + 1;
|
||||
vid.smalldupy = (UINT8)(vid.dupy / 3) + 1;
|
||||
#ifdef HWRENDER
|
||||
vid.fsmalldupx = vid.smalldupx*FRACUNIT;
|
||||
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
|
||||
#endif
|
||||
|
||||
// toggle off (then back on) the automap because some screensize-dependent values will
|
||||
// be calculated next time the automap is activated.
|
||||
|
||||
+17
-73
@@ -39,113 +39,56 @@
|
||||
// we try to re-allocate a minimum of buffers for stability of the memory,
|
||||
// so all the small-enough tables based on screen size, are allocated once
|
||||
// and for all at the maximum size.
|
||||
#define MAXVIDWIDTH 5120 // don't set this too high because actually
|
||||
#define MAXVIDHEIGHT 2880 // lots of tables are allocated with the MAX size.
|
||||
#define MAXVIDWIDTH 8192 // don't set this too high because actually
|
||||
#define MAXVIDHEIGHT 8192 // lots of tables are allocated with the MAX size.
|
||||
#define BASEVIDWIDTH 320 // NEVER CHANGE THIS! This is the original
|
||||
#define BASEVIDHEIGHT 200 // resolution of the graphics.
|
||||
|
||||
// max res for png capture; just here to prevent some crashes on very high resolutions; tho you should never go this high cause ogl allocs certain things with MAXVIDWIDTH and MAXVIDHEIGHT too Zzz...
|
||||
#define MAXPNGWIDTH 7680
|
||||
#define MAXPNGHEIGHT 4320
|
||||
|
||||
// global video state
|
||||
typedef struct viddef_s
|
||||
{
|
||||
INT32 modenum; // vidmode num indexes videomodes list
|
||||
|
||||
// Each screen is [vid.width*vid.height];
|
||||
UINT8 *screens[5];
|
||||
// screens[0] = main display window
|
||||
// screens[1] = back screen, alternative blitting
|
||||
// screens[2] = screenshot buffer, gif movie buffer
|
||||
// screens[3] = fade screen start
|
||||
// screens[4] = fade screen end, postimage tempoarary buffer
|
||||
|
||||
UINT8 *buffer; // invisible screens buffer
|
||||
size_t rowbytes; // bytes per scanline of the VIDEO mode
|
||||
INT32 width; // PIXELS per scanline
|
||||
INT32 height;
|
||||
union { // don't need numpages for OpenGL, so we can use it for fullscreen/windowed mode
|
||||
INT32 numpages; // always 1, page flipping todo
|
||||
INT32 windowed; // windowed or fullscren mode?
|
||||
} u;
|
||||
INT32 recalc; // if true, recalc vid-based stuff
|
||||
UINT8 *direct; // linear frame buffer, or vga base mem.
|
||||
boolean recalc; // if true, recalc vid-based stuff
|
||||
INT32 dupx, dupy; // scale 1, 2, 3 value for menus & overlays
|
||||
INT32/*fixed_t*/ fdupx, fdupy; // same as dupx, dupy, but exact value when aspect ratio isn't 320/200
|
||||
INT32 bpp; // BYTES per pixel: 1 = 256color, 2 = highcolor
|
||||
|
||||
INT32 baseratio; // Used to get the correct value for lighting walls
|
||||
|
||||
// for Win32 version
|
||||
DNWH WndParent; // handle of the application's window
|
||||
UINT8 smalldupx, smalldupy; // factor for a little bit of scaling
|
||||
UINT8 meddupx, meddupy; // factor for moderate, but not full, scaling
|
||||
#ifdef HWRENDER
|
||||
INT32/*fixed_t*/ fsmalldupx, fsmalldupy;
|
||||
INT32/*fixed_t*/ fmeddupx, fmeddupy;
|
||||
INT32 glstate;
|
||||
#endif
|
||||
} viddef_t;
|
||||
#define VIDWIDTH vid.width
|
||||
#define VIDHEIGHT vid.height
|
||||
|
||||
enum
|
||||
{
|
||||
VID_GL_LIBRARY_LOADED = 1,
|
||||
VID_GL_LIBRARY_LOADED = 1,
|
||||
VID_GL_LIBRARY_ERROR = -1,
|
||||
};
|
||||
|
||||
// internal additional info for vesa modes only
|
||||
typedef struct
|
||||
{
|
||||
INT32 vesamode; // vesa mode number plus LINEAR_MODE bit
|
||||
void *plinearmem; // linear address of start of frame buffer
|
||||
} vesa_extra_t;
|
||||
|
||||
// a video modes from the video modes list,
|
||||
// note: video mode 0 is always standard VGA320x200.
|
||||
typedef struct vmode_s
|
||||
{
|
||||
struct vmode_s *pnext;
|
||||
char *name;
|
||||
UINT32 width, height;
|
||||
UINT32 rowbytes; // bytes per scanline
|
||||
UINT32 bytesperpixel; // 1 for 256c, 2 for highcolor
|
||||
INT32 windowed; // if true this is a windowed mode
|
||||
INT32 numpages;
|
||||
vesa_extra_t *pextradata; // vesa mode extra data
|
||||
#ifdef _WIN32
|
||||
INT32 (WINAPI *setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode);
|
||||
#else
|
||||
INT32 (*setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode);
|
||||
#endif
|
||||
INT32 misc; // misc for display driver (r_opengl.dll etc)
|
||||
} vmode_t;
|
||||
|
||||
#define NUMSPECIALMODES 4
|
||||
extern vmode_t specialmodes[NUMSPECIALMODES];
|
||||
|
||||
// ---------------------------------------------
|
||||
// color mode dependent drawer function pointers
|
||||
// ---------------------------------------------
|
||||
|
||||
extern void (*wallcolfunc)(void);
|
||||
extern void (*colfunc)(void);
|
||||
extern void (*basecolfunc)(void);
|
||||
extern void (*fuzzcolfunc)(void);
|
||||
extern void (*transcolfunc)(void);
|
||||
extern void (*shadecolfunc)(void);
|
||||
extern void (*spanfunc)(void);
|
||||
extern void (*basespanfunc)(void);
|
||||
extern void (*splatfunc)(void);
|
||||
extern void (*transtransfunc)(void);
|
||||
extern void (*twosmultipatchfunc)(void);
|
||||
extern void (*twosmultipatchtransfunc)(void);
|
||||
|
||||
// ----------------
|
||||
// screen variables
|
||||
// ----------------
|
||||
extern viddef_t vid;
|
||||
extern INT32 setmodeneeded; // mode number to set if needed, or 0
|
||||
extern double averageFPS;
|
||||
|
||||
extern INT32 scr_bpp;
|
||||
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
||||
|
||||
extern consvar_t cv_scr_width, cv_scr_height, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen;
|
||||
extern consvar_t cv_parallelsoftware;
|
||||
|
||||
extern consvar_t cv_highreshudscale;
|
||||
// wait for page flipping to end or not
|
||||
extern consvar_t cv_vidwait;
|
||||
@@ -155,8 +98,9 @@ extern consvar_t cv_alwaysgrabmouse;
|
||||
|
||||
extern consvar_t cv_votebgscaling;
|
||||
|
||||
// quick fix for tall/short skies, depending on bytesperpixel
|
||||
extern void (*walldrawerfunc)(void);
|
||||
void R_SetColumnFunc(size_t id);
|
||||
void R_SetSpanFunc(size_t id);
|
||||
boolean R_CheckColumnFunc(size_t id);
|
||||
|
||||
// Change video mode, only at the start of a refresh.
|
||||
void SCR_SetMode(void);
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
#ifndef __ENDTXT__
|
||||
#define __ENDTXT__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ShowEndTxt (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user