mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- Merge voxels back into trunk. Even if it needs further tweaking, it should at least be stable now.
SVN r3086 (trunk)
This commit is contained in:
parent
e90b86acce
commit
2add3fb381
24 changed files with 2556 additions and 206 deletions
|
@ -658,6 +658,7 @@ add_executable( zdoom WIN32
|
|||
m_misc.cpp
|
||||
m_png.cpp
|
||||
m_random.cpp
|
||||
memarena.cpp
|
||||
md5.cpp
|
||||
name.cpp
|
||||
nodebuild.cpp
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
%define setupmvlineasm _setupmvlineasm
|
||||
%define mvlineasm1 _mvlineasm1
|
||||
%define mvlineasm4 _mvlineasm4
|
||||
|
||||
%define R_SetupDrawSlab _R_SetupDrawSlab
|
||||
%define R_DrawSlab _R_DrawSlab
|
||||
%endif
|
||||
|
||||
EXTERN ylookup ; near
|
||||
|
@ -44,9 +47,6 @@ EXTERN dc_dest
|
|||
EXTERN dc_source
|
||||
EXTERN dc_texturefrac
|
||||
|
||||
mvlineasm4_counter:
|
||||
dd 0
|
||||
|
||||
SECTION .text
|
||||
|
||||
ALIGN 16
|
||||
|
@ -59,8 +59,45 @@ setvlinebpl_:
|
|||
mov [fixchain2ma+2], eax
|
||||
mov [fixchain2mb+2], eax
|
||||
selfmod fixchain1a, fixchain2mb+6
|
||||
|
||||
setdrawslabbpl:
|
||||
mov dword [voxbpl1+2], eax
|
||||
mov dword [voxbpl2+2], eax
|
||||
mov dword [voxbpl3+2], eax
|
||||
mov dword [voxbpl4+2], eax
|
||||
mov dword [voxbpl5+2], eax
|
||||
mov dword [voxbpl6+2], eax
|
||||
mov dword [voxbpl7+2], eax
|
||||
mov dword [voxbpl8+2], eax
|
||||
selfmod voxbpl1, voxpl8+6
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
|
||||
lastslabcolormap:
|
||||
dd 4
|
||||
|
||||
SECTION .text
|
||||
|
||||
GLOBAL R_SetupDrawSlab
|
||||
GLOBAL @R_SetupDrawSlab@4
|
||||
R_SetupDrawSlab:
|
||||
mov ecx, [esp+4]
|
||||
@R_SetupDrawSlab@4:
|
||||
cmp [lastslabcolormap], ecx
|
||||
je .done
|
||||
mov [lastslabcolormap], ecx
|
||||
mov dword [voxpal1+2], ecx
|
||||
mov dword [voxpal2+2], ecx
|
||||
mov dword [voxpal3+2], ecx
|
||||
mov dword [voxpal4+2], ecx
|
||||
mov dword [voxpal5+2], ecx
|
||||
mov dword [voxpal6+2], ecx
|
||||
mov dword [voxpal7+2], ecx
|
||||
mov dword [voxpal8+2], ecx
|
||||
.done ret
|
||||
|
||||
|
||||
; pass it log2(texheight)
|
||||
|
||||
ALIGN 16
|
||||
|
@ -549,6 +586,226 @@ mvcase0: jmp beginmvlineasm4
|
|||
|
||||
align 16
|
||||
|
||||
|
||||
;*************************************************************************
|
||||
;***************************** Voxel Slabs *******************************
|
||||
;*************************************************************************
|
||||
|
||||
GLOBAL R_DrawSlab
|
||||
R_DrawSlab:
|
||||
push ebx
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov eax, [esp+5*4+0]
|
||||
mov ebx, [esp+5*4+4]
|
||||
mov ecx, [esp+5*4+8]
|
||||
mov edx, [esp+5*4+12]
|
||||
mov esi, [esp+5*4+16]
|
||||
mov edi, [esp+5*4+20]
|
||||
|
||||
cmp eax, 2
|
||||
je voxbegdraw2
|
||||
ja voxskip2
|
||||
xor eax, eax
|
||||
voxbegdraw1:
|
||||
mov ebp, ebx
|
||||
shr ebp, 16
|
||||
add ebx, edx
|
||||
dec ecx
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal1: mov al, byte [eax+88888888h]
|
||||
mov byte [edi], al
|
||||
voxbpl1: lea edi, [edi+88888888h]
|
||||
jnz voxbegdraw1
|
||||
jmp voxskipslab5
|
||||
|
||||
voxbegdraw2:
|
||||
mov ebp, ebx
|
||||
shr ebp, 16
|
||||
add ebx, edx
|
||||
xor eax, eax
|
||||
dec ecx
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal2: mov al, byte [eax+88888888h]
|
||||
mov ah, al
|
||||
mov word [edi], ax
|
||||
voxbpl2: lea edi, [edi+88888888h]
|
||||
jnz voxbegdraw2
|
||||
jmp voxskipslab5
|
||||
|
||||
voxskip2:
|
||||
cmp eax, 4
|
||||
jne voxskip4
|
||||
xor eax, eax
|
||||
voxbegdraw4:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal3: mov al, byte [eax+88888888h]
|
||||
mov ah, al
|
||||
shl eax, 8
|
||||
mov al, ah
|
||||
shl eax, 8
|
||||
mov al, ah
|
||||
mov dword [edi], eax
|
||||
voxbpl3: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegdraw4
|
||||
jmp voxskipslab5
|
||||
|
||||
voxskip4:
|
||||
add eax, edi
|
||||
|
||||
test edi, 1
|
||||
jz voxskipslab1
|
||||
cmp edi, eax
|
||||
je voxskipslab1
|
||||
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edi
|
||||
voxbegslab1:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal4: mov al, byte [eax+88888888h]
|
||||
mov byte [edi], al
|
||||
voxbpl4: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegslab1
|
||||
pop edi
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
inc edi
|
||||
|
||||
voxskipslab1:
|
||||
push eax
|
||||
test edi, 2
|
||||
jz voxskipslab2
|
||||
dec eax
|
||||
cmp edi, eax
|
||||
jge voxskipslab2
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
push edi
|
||||
voxbegslab2:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal5: mov al, byte [eax+88888888h]
|
||||
mov ah, al
|
||||
mov word [edi], ax
|
||||
voxbpl5: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegslab2
|
||||
pop edi
|
||||
pop ecx
|
||||
pop ebx
|
||||
add edi, 2
|
||||
|
||||
voxskipslab2:
|
||||
mov eax, [esp]
|
||||
|
||||
sub eax, 3
|
||||
cmp edi, eax
|
||||
jge voxskipslab3
|
||||
|
||||
voxprebegslab3:
|
||||
push ebx
|
||||
push ecx
|
||||
push edi
|
||||
voxbegslab3:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal6: mov al, byte [eax+88888888h]
|
||||
mov ah, al
|
||||
shl eax, 8
|
||||
mov al, ah
|
||||
shl eax, 8
|
||||
mov al, ah
|
||||
mov dword [edi], eax
|
||||
voxbpl6: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegslab3
|
||||
pop edi
|
||||
pop ecx
|
||||
pop ebx
|
||||
add edi, 4
|
||||
|
||||
mov eax, [esp]
|
||||
|
||||
sub eax, 3
|
||||
cmp edi, eax
|
||||
jl voxprebegslab3
|
||||
|
||||
voxskipslab3:
|
||||
mov eax, [esp]
|
||||
|
||||
dec eax
|
||||
cmp edi, eax
|
||||
jge voxskipslab4
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
push edi
|
||||
voxbegslab4:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal7: mov al, byte [eax+88888888h]
|
||||
mov ah, al
|
||||
mov word [edi], ax
|
||||
voxbpl7: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegslab4
|
||||
pop edi
|
||||
pop ecx
|
||||
pop ebx
|
||||
add edi, 2
|
||||
|
||||
voxskipslab4:
|
||||
pop eax
|
||||
|
||||
cmp edi, eax
|
||||
je voxskipslab5
|
||||
|
||||
voxbegslab5:
|
||||
mov ebp, ebx
|
||||
add ebx, edx
|
||||
shr ebp, 16
|
||||
xor eax, eax
|
||||
mov al, byte [esi+ebp]
|
||||
voxpal8: mov al, byte [eax+88888888h]
|
||||
mov byte [edi], al
|
||||
voxbpl8: add edi, 88888888h
|
||||
dec ecx
|
||||
jnz voxbegslab5
|
||||
|
||||
voxskipslab5:
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
align 16
|
||||
|
||||
%ifdef M_TARGET_MACHO
|
||||
GLOBAL _rtext_a_end
|
||||
_rtext_a_end:
|
||||
|
|
|
@ -850,8 +850,8 @@ GLOBAL R_DrawColumnHorizP_ASM
|
|||
align 16
|
||||
|
||||
@R_DrawColumnHorizP_ASM@0:
|
||||
R_DrawColumnHorizP_ASM:
|
||||
_R_DrawColumnHorizP_ASM:
|
||||
R_DrawColumnHorizP_ASM:
|
||||
|
||||
; count = dc_yh - dc_yl;
|
||||
|
||||
|
@ -870,8 +870,10 @@ _R_DrawColumnHorizP_ASM:
|
|||
inc eax ; make 0 count mean 0 pixels
|
||||
and edx,3
|
||||
push eax
|
||||
mov esi,[dc_ctspan+edx*4]
|
||||
lea eax,[dc_temp+ecx*4+edx] ; eax = top of column in buffer
|
||||
mov eax,[dc_temp]
|
||||
mov esi,[dc_ctspan+edx*4]
|
||||
add eax,edx
|
||||
lea eax,[eax+ecx*4] ; eax = top of column in buffer
|
||||
mov ebp,[dc_yh]
|
||||
mov [esi],ecx
|
||||
mov [esi+4],ebp
|
||||
|
@ -1102,8 +1104,9 @@ _rt_copy1col_asm:
|
|||
lea esi,[eax*4]
|
||||
inc ebx ; ebx = count
|
||||
mov eax,edx
|
||||
lea ecx,[dc_temp+ecx+esi] ; ecx = source
|
||||
add ecx,esi
|
||||
mov edi,[ylookup+esi]
|
||||
add ecx,[dc_temp] ; ecx = source
|
||||
mov esi,[dc_pitch] ; esi = pitch
|
||||
add eax,edi ; eax = dest
|
||||
add eax,[dc_destorg]
|
||||
|
@ -1169,10 +1172,11 @@ _rt_copy4cols_asm:
|
|||
inc ebx ; ebx = count
|
||||
mov eax,ecx
|
||||
mov esi,[ylookup+edx*4]
|
||||
lea ecx,[dc_temp+edx*4] ; ecx = source
|
||||
mov edx,[dc_pitch] ; edx = pitch
|
||||
mov ecx,[dc_temp]
|
||||
add eax,esi ; eax = dest
|
||||
add eax,[dc_destorg]
|
||||
lea ecx,[ecx+edx*4] ; ecx = source
|
||||
mov edx,[dc_pitch] ; edx = pitch
|
||||
|
||||
shr ebx,1
|
||||
jnc .even
|
||||
|
@ -1241,7 +1245,8 @@ _rt_map1col_asm:
|
|||
mov esi,[dc_colormap] ; esi = colormap
|
||||
inc ebx ; ebx = count
|
||||
mov eax,edx
|
||||
lea ebp,[dc_temp+ecx+edi] ; ebp = source
|
||||
lea ebp,[ecx+edi] ; ebp = source
|
||||
add ebp,[dc_temp]
|
||||
mov ecx,[ylookup+edi]
|
||||
mov edi,[dc_pitch] ; edi = pitch
|
||||
add eax,ecx ; eax = dest
|
||||
|
@ -1320,7 +1325,8 @@ _rt_map4cols_asm1:
|
|||
mov eax,ecx
|
||||
inc ebx ; ebx = count
|
||||
mov edi,[ylookup+edx]
|
||||
lea ebp,[dc_temp+edx] ; ebp = source
|
||||
mov ebp,[dc_temp]
|
||||
add ebp,edx ; ebp = source
|
||||
add eax,edi ; eax = dest
|
||||
mov edi,[dc_pitch] ; edi = pitch
|
||||
add eax,[dc_destorg]
|
||||
|
@ -1414,7 +1420,8 @@ _rt_map4cols_asm2:
|
|||
mov eax,ecx
|
||||
inc ebx ; ebx = count
|
||||
mov edi,[ylookup+edx]
|
||||
lea ebp,[dc_temp+edx] ; ebp = source
|
||||
mov ebp,[dc_temp]
|
||||
add ebp,edx ; ebp = source
|
||||
add eax,edi ; eax = dest
|
||||
mov edi,[dc_pitch] ; edi = pitch
|
||||
add eax,[dc_destorg]
|
||||
|
@ -1493,10 +1500,11 @@ _rt_shaded4cols_asm:
|
|||
add eax,[dc_destorg] ; eax = destination
|
||||
push ebx
|
||||
push esi
|
||||
mov esi,[dc_temp]
|
||||
inc ebp ; ebp = count
|
||||
add eax,[esp+16]
|
||||
push edi
|
||||
lea esi,[dc_temp+ecx*4] ; esi = source
|
||||
lea esi,[esi+ecx*4] ; esi = source
|
||||
|
||||
align 16
|
||||
|
||||
|
@ -1580,10 +1588,11 @@ _rt_add4cols_asm:
|
|||
add eax,[dc_destorg]
|
||||
push ebx
|
||||
push esi
|
||||
mov esi,[dc_temp]
|
||||
push ebp
|
||||
inc edi
|
||||
add eax,[esp+20]
|
||||
lea esi,[dc_temp+ecx*4]
|
||||
lea esi,[esi+ecx*4]
|
||||
|
||||
align 16
|
||||
a4loop:
|
||||
|
@ -1659,10 +1668,11 @@ _rt_addclamp4cols_asm:
|
|||
add eax,[dc_destorg]
|
||||
push ebx
|
||||
push esi
|
||||
mov esi,[dc_temp]
|
||||
push ebp
|
||||
inc edi
|
||||
add eax,[esp+20]
|
||||
lea esi,[dc_temp+ecx*4]
|
||||
lea esi,[esi+ecx*4]
|
||||
push edi
|
||||
|
||||
align 16
|
||||
|
|
|
@ -166,5 +166,6 @@ void ResetButtonStates (); // Same as above, but also clear bDown
|
|||
|
||||
extern unsigned int MakeKey (const char *s);
|
||||
extern unsigned int MakeKey (const char *s, size_t len);
|
||||
extern unsigned int SuperFastHash (const char *data, size_t len);
|
||||
|
||||
#endif //__C_DISPATCH_H__
|
||||
|
|
376
src/memarena.cpp
Normal file
376
src/memarena.cpp
Normal file
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
** memarena.cpp
|
||||
** Implements memory arenas.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
** A memory arena is used for efficient allocation of many small objects that
|
||||
** will all be freed at once. Note that since individual destructors are not
|
||||
** called, you must not use an arena to allocate any objects that use a
|
||||
** destructor, either explicitly or implicitly (because they have members
|
||||
** with destructors).
|
||||
*/
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_alloc.h"
|
||||
#include "memarena.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "zstring.h"
|
||||
|
||||
#define BLOCK_SIZE (10*1024)
|
||||
|
||||
struct FMemArena::Block
|
||||
{
|
||||
Block *NextBlock;
|
||||
void *Limit; // End of this block
|
||||
void *Avail; // Start of free space in this block
|
||||
|
||||
void Reset();
|
||||
void *Alloc(size_t size);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// RoundPointer
|
||||
//
|
||||
// Rounds a pointer up to a pointer-sized boundary.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static inline void *RoundPointer(void *ptr)
|
||||
{
|
||||
return (void *)(((size_t)ptr + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMemArena::FMemArena()
|
||||
{
|
||||
TopBlock = NULL;
|
||||
FreeBlocks = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMemArena::~FMemArena()
|
||||
{
|
||||
FreeAllBlocks();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: Alloc
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void *FMemArena::Alloc(size_t size)
|
||||
{
|
||||
Block *block;
|
||||
|
||||
for (block = TopBlock; block != NULL; block = block->NextBlock)
|
||||
{
|
||||
void *res = block->Alloc(size);
|
||||
if (res != NULL)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
block = AddBlock(size);
|
||||
return block->Alloc(size);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: FreeAll
|
||||
//
|
||||
// Moves all blocks to the free list. No system-level deallocation occurs.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMemArena::FreeAll()
|
||||
{
|
||||
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||
{
|
||||
next = block->NextBlock;
|
||||
block->Reset();
|
||||
block->NextBlock = FreeBlocks;
|
||||
FreeBlocks = block;
|
||||
}
|
||||
TopBlock = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: FreeAllBlocks
|
||||
//
|
||||
// Frees all blocks used by this arena.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMemArena::FreeAllBlocks()
|
||||
{
|
||||
FreeBlockChain(TopBlock);
|
||||
FreeBlockChain(FreeBlocks);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: FreeBlockChain
|
||||
//
|
||||
// Frees a chain of blocks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMemArena::FreeBlockChain(Block *&top)
|
||||
{
|
||||
for (Block *next, *block = top; block != NULL; block = next)
|
||||
{
|
||||
next = block->NextBlock;
|
||||
M_Free(block);
|
||||
}
|
||||
top = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: AddBlock
|
||||
//
|
||||
// Allocates a block large enough to hold at least <size> bytes and adds it
|
||||
// to the TopBlock chain.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMemArena::Block *FMemArena::AddBlock(size_t size)
|
||||
{
|
||||
Block *mem, **last;
|
||||
size += sizeof(Block); // Account for header size
|
||||
|
||||
// Search for a free block to use
|
||||
for (last = &FreeBlocks, mem = FreeBlocks; mem != NULL; last = &mem->NextBlock, mem = mem->NextBlock)
|
||||
{
|
||||
if ((BYTE *)mem->Limit - (BYTE *)mem >= (ptrdiff_t)size)
|
||||
{
|
||||
*last = mem->NextBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mem == NULL)
|
||||
{
|
||||
// Allocate a new block
|
||||
if (size < BLOCK_SIZE)
|
||||
{
|
||||
size = BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
{ // Stick some free space at the end so we can use this block for
|
||||
// other things.
|
||||
size += BLOCK_SIZE/2;
|
||||
}
|
||||
mem = (Block *)M_Malloc(size);
|
||||
mem->Limit = (BYTE *)mem + size;
|
||||
}
|
||||
mem->Reset();
|
||||
mem->NextBlock = TopBlock;
|
||||
TopBlock = mem;
|
||||
return mem;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: Block :: Reset
|
||||
//
|
||||
// Resets this block's Avail pointer.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMemArena::Block::Reset()
|
||||
{
|
||||
Avail = RoundPointer(this + sizeof(*this));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMemArena :: Block :: Alloc
|
||||
//
|
||||
// Allocates memory from the block if it has space. Returns NULL if not.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void *FMemArena::Block::Alloc(size_t size)
|
||||
{
|
||||
if ((char *)Avail + size > Limit)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void *res = Avail;
|
||||
Avail = RoundPointer((char *)Avail + size);
|
||||
return res;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSharedStringArena::FSharedStringArena()
|
||||
{
|
||||
memset(Buckets, 0, sizeof(Buckets));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSharedStringArena::~FSharedStringArena()
|
||||
{
|
||||
FreeAll();
|
||||
// FMemArena destructor will free the blocks.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena :: Alloc
|
||||
//
|
||||
// Allocates a new string and initializes it with the passed string. This
|
||||
// version takes an FString as a parameter, so it won't need to allocate any
|
||||
// memory for the string text if it already exists in the arena.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FString *FSharedStringArena::Alloc(const FString &source)
|
||||
{
|
||||
unsigned int hash;
|
||||
Node *strnode;
|
||||
|
||||
strnode = FindString(source, source.Len(), hash);
|
||||
if (strnode == NULL)
|
||||
{
|
||||
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||
::new(&strnode->String) FString(source);
|
||||
strnode->Hash = hash;
|
||||
hash %= countof(Buckets);
|
||||
strnode->Next = Buckets[hash];
|
||||
Buckets[hash] = strnode;
|
||||
}
|
||||
return &strnode->String;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena :: Alloc
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FString *FSharedStringArena::Alloc(const char *source)
|
||||
{
|
||||
return Alloc(source, strlen(source));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena :: Alloc
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FString *FSharedStringArena::Alloc(const char *source, size_t strlen)
|
||||
{
|
||||
unsigned int hash;
|
||||
Node *strnode;
|
||||
|
||||
strnode = FindString(source, strlen, hash);
|
||||
if (strnode == NULL)
|
||||
{
|
||||
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||
::new(&strnode->String) FString(source, strlen);
|
||||
strnode->Hash = hash;
|
||||
hash %= countof(Buckets);
|
||||
strnode->Next = Buckets[hash];
|
||||
Buckets[hash] = strnode;
|
||||
}
|
||||
return &strnode->String;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena :: FindString
|
||||
//
|
||||
// Finds the string if it's already in the arena. Returns NULL if not.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FSharedStringArena::Node *FSharedStringArena::FindString(const char *str, size_t strlen, unsigned int &hash)
|
||||
{
|
||||
hash = SuperFastHash(str, strlen);
|
||||
|
||||
for (Node *node = Buckets[hash % countof(Buckets)]; node != NULL; node = node->Next)
|
||||
{
|
||||
if (node->Hash == hash && node->String.Len() == strlen && memcmp(&node->String[0], str, strlen) == 0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FSharedStringArena :: FreeAll
|
||||
//
|
||||
// In addition to moving all used blocks onto the free list, all FStrings
|
||||
// they contain will have their destructors called.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FSharedStringArena::FreeAll()
|
||||
{
|
||||
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||
{
|
||||
next = block->NextBlock;
|
||||
void *limit = block->Avail;
|
||||
block->Reset();
|
||||
for (Node *string = (Node *)block->Avail; string < limit; ++string)
|
||||
{
|
||||
string->~Node();
|
||||
}
|
||||
block->NextBlock = FreeBlocks;
|
||||
FreeBlocks = block;
|
||||
}
|
||||
memset(Buckets, 0, sizeof(Buckets));
|
||||
}
|
83
src/memarena.h
Normal file
83
src/memarena.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
** memarena.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "zstring.h"
|
||||
|
||||
// A general purpose arena.
|
||||
class FMemArena
|
||||
{
|
||||
public:
|
||||
FMemArena();
|
||||
~FMemArena();
|
||||
|
||||
void *Alloc(size_t size);
|
||||
void FreeAll();
|
||||
void FreeAllBlocks();
|
||||
|
||||
protected:
|
||||
struct Block;
|
||||
|
||||
Block *AddBlock(size_t size);
|
||||
void FreeBlockChain(Block *&top);
|
||||
|
||||
Block *TopBlock;
|
||||
Block *FreeBlocks;
|
||||
};
|
||||
|
||||
// An arena specializing in storage of FStrings. It knows how to free them,
|
||||
// but this means it also should never be used for allocating anything else.
|
||||
// Identical strings all return the same pointer.
|
||||
class FSharedStringArena : public FMemArena
|
||||
{
|
||||
public:
|
||||
FSharedStringArena();
|
||||
~FSharedStringArena();
|
||||
void FreeAll();
|
||||
|
||||
class FString *Alloc(const FString &source);
|
||||
class FString *Alloc(const char *source);
|
||||
class FString *Alloc(const char *source, size_t strlen);
|
||||
|
||||
protected:
|
||||
struct Node
|
||||
{
|
||||
Node *Next;
|
||||
FString String;
|
||||
unsigned int Hash;
|
||||
};
|
||||
Node *Buckets[256];
|
||||
|
||||
Node *FindString(const char *str, size_t strlen, unsigned int &hash);
|
||||
private:
|
||||
void *Alloc(size_t size) { return NULL; } // No access to FMemArena::Alloc for outsiders.
|
||||
};
|
304
src/r_data.cpp
304
src/r_data.cpp
|
@ -355,6 +355,304 @@ const BYTE *R_GetColumn (FTexture *tex, int col)
|
|||
return tex->GetColumn (col, NULL);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetVoxelRemap
|
||||
//
|
||||
// Calculates a remap table for the voxel's palette. Results are cached so
|
||||
// passing the same palette repeatedly will not require repeated
|
||||
// recalculations.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static BYTE *GetVoxelRemap(const BYTE *pal)
|
||||
{
|
||||
static BYTE remap[256];
|
||||
static BYTE oldpal[768];
|
||||
static bool firsttime = true;
|
||||
|
||||
if (firsttime || memcmp(oldpal, pal, 768) != 0)
|
||||
{ // Not the same palette as last time, so recalculate.
|
||||
firsttime = false;
|
||||
memcpy(oldpal, pal, 768);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
// The voxel palette uses VGA colors, so we have to expand it
|
||||
// from 6 to 8 bits per component.
|
||||
remap[i] = BestColor((uint32 *)GPalette.BaseColors,
|
||||
(oldpal[i*3 + 0] << 2) | (oldpal[i*3 + 0] >> 4),
|
||||
(oldpal[i*3 + 1] << 2) | (oldpal[i*3 + 1] >> 4),
|
||||
(oldpal[i*3 + 2] << 2) | (oldpal[i*3 + 2] >> 4));
|
||||
}
|
||||
}
|
||||
return remap;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CopyVoxelSlabs
|
||||
//
|
||||
// Copy all the slabs in a block of slabs.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool CopyVoxelSlabs(kvxslab_t *dest, const kvxslab_t *src, int size)
|
||||
{
|
||||
while (size >= 3)
|
||||
{
|
||||
int slabzleng = src->zleng;
|
||||
|
||||
if (3 + slabzleng > size)
|
||||
{ // slab is too tall
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->ztop = src->ztop;
|
||||
dest->zleng = src->zleng;
|
||||
dest->backfacecull = src->backfacecull;
|
||||
|
||||
for (int j = 0; j < slabzleng; ++j)
|
||||
{
|
||||
dest->col[j] = src->col[j];
|
||||
}
|
||||
slabzleng += 3;
|
||||
src = (kvxslab_t *)((BYTE *)src + slabzleng);
|
||||
dest = (kvxslab_t *)((BYTE *)dest + slabzleng);
|
||||
size -= slabzleng;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// RemapVoxelSlabs
|
||||
//
|
||||
// Remaps all the slabs in a block of slabs.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void RemapVoxelSlabs(kvxslab_t *dest, int size, const BYTE *remap)
|
||||
{
|
||||
while (size >= 3)
|
||||
{
|
||||
int slabzleng = dest->zleng;
|
||||
|
||||
for (int j = 0; j < slabzleng; ++j)
|
||||
{
|
||||
dest->col[j] = remap[dest->col[j]];
|
||||
}
|
||||
slabzleng += 3;
|
||||
dest = (kvxslab_t *)((BYTE *)dest + slabzleng);
|
||||
size -= slabzleng;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_LoadKVX
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FVoxel *R_LoadKVX(int lumpnum)
|
||||
{
|
||||
const kvxslab_t *slabs[MAXVOXMIPS];
|
||||
FVoxel *voxel = new FVoxel;
|
||||
const BYTE *rawmip;
|
||||
int mip, maxmipsize;
|
||||
int i, j, n;
|
||||
|
||||
FMemLump lump = Wads.ReadLump(lumpnum); // FMemLump adds an extra 0 byte to the end.
|
||||
BYTE *rawvoxel = (BYTE *)lump.GetMem();
|
||||
int voxelsize = (int)(lump.GetSize()-1);
|
||||
|
||||
// Oh, KVX, why couldn't you have a proper header? We'll just go through
|
||||
// and collect each MIP level, doing lots of range checking, and if the
|
||||
// last one doesn't end exactly 768 bytes before the end of the file,
|
||||
// we'll reject it.
|
||||
|
||||
for (mip = 0, rawmip = rawvoxel, maxmipsize = voxelsize - 768 - 4;
|
||||
mip < MAXVOXMIPS;
|
||||
mip++)
|
||||
{
|
||||
int numbytes = GetInt(rawmip);
|
||||
if (numbytes > maxmipsize || numbytes < 24)
|
||||
{
|
||||
break;
|
||||
}
|
||||
rawmip += 4;
|
||||
|
||||
FVoxelMipLevel *mipl = &voxel->Mips[mip];
|
||||
|
||||
// Load header data.
|
||||
mipl->SizeX = GetInt(rawmip + 0);
|
||||
mipl->SizeY = GetInt(rawmip + 4);
|
||||
mipl->SizeZ = GetInt(rawmip + 8);
|
||||
mipl->PivotX = GetInt(rawmip + 12);
|
||||
mipl->PivotY = GetInt(rawmip + 16);
|
||||
mipl->PivotZ = GetInt(rawmip + 20);
|
||||
|
||||
// How much space do we have for voxdata?
|
||||
int offsetsize = (mipl->SizeX + 1) * 4 + mipl->SizeX * (mipl->SizeY + 1) * 2;
|
||||
int voxdatasize = numbytes - 24 - offsetsize;
|
||||
if (voxdatasize < 0)
|
||||
{ // Clearly, not enough.
|
||||
break;
|
||||
}
|
||||
if (voxdatasize == 0)
|
||||
{ // This mip level is empty.
|
||||
goto nextmip;
|
||||
}
|
||||
|
||||
// Allocate slab data space.
|
||||
mipl->OffsetX = new int[(numbytes - 24 + 3) / 4];
|
||||
mipl->OffsetXY = (short *)(mipl->OffsetX + mipl->SizeX + 1);
|
||||
mipl->SlabData = (BYTE *)(mipl->OffsetXY + mipl->SizeX * (mipl->SizeY + 1));
|
||||
|
||||
// Load x offsets.
|
||||
for (i = 0, n = mipl->SizeX; i <= n; ++i)
|
||||
{
|
||||
// The X offsets stored in the KVX file are relative to the start of the
|
||||
// X offsets array. Make them relative to voxdata instead.
|
||||
mipl->OffsetX[i] = GetInt(rawmip + 24 + i * 4) - offsetsize;
|
||||
}
|
||||
|
||||
// The first X offset must be 0 (since we subtracted offsetsize), according to the spec:
|
||||
// NOTE: xoffset[0] = (xsiz+1)*4 + xsiz*(ysiz+1)*2 (ALWAYS)
|
||||
if (mipl->OffsetX[0] != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// And the final X offset must point just past the end of the voxdata.
|
||||
if (mipl->OffsetX[mipl->SizeX] != voxdatasize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Load xy offsets.
|
||||
i = 24 + i * 4;
|
||||
for (j = 0, n *= mipl->SizeY + 1; j < n; ++j)
|
||||
{
|
||||
mipl->OffsetXY[j] = GetShort(rawmip + i + j * 2);
|
||||
}
|
||||
|
||||
// Ensure all offsets are within bounds.
|
||||
for (i = 0; i < mipl->SizeX; ++i)
|
||||
{
|
||||
int xoff = mipl->OffsetX[i];
|
||||
for (j = 0; j < mipl->SizeY; ++j)
|
||||
{
|
||||
int yoff = mipl->OffsetXY[(mipl->SizeY + 1) * i + j];
|
||||
if (unsigned(xoff + yoff) > unsigned(voxdatasize))
|
||||
{
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record slab location for the end.
|
||||
slabs[mip] = (kvxslab_t *)(rawmip + 24 + offsetsize);
|
||||
|
||||
// Time for the next mip Level.
|
||||
nextmip:
|
||||
rawmip += numbytes;
|
||||
maxmipsize -= numbytes + 4;
|
||||
}
|
||||
// Did we get any mip levels, and if so, does the last one leave just
|
||||
// enough room for the palette after it?
|
||||
if (mip == 0 || rawmip != rawvoxel + voxelsize - 768)
|
||||
{
|
||||
bad: delete voxel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Do not count empty mips at the end.
|
||||
for (; mip > 0; --mip)
|
||||
{
|
||||
if (voxel->Mips[mip - 1].SlabData != NULL)
|
||||
break;
|
||||
}
|
||||
voxel->NumMips = mip;
|
||||
|
||||
for (i = 0; i < mip; ++i)
|
||||
{
|
||||
if (!CopyVoxelSlabs((kvxslab_t *)voxel->Mips[i].SlabData, slabs[i], voxel->Mips[i].OffsetX[voxel->Mips[i].SizeX]))
|
||||
{ // Invalid slabs encountered. Reject this voxel.
|
||||
delete voxel;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
voxel->LumpNum = lumpnum;
|
||||
voxel->Palette = new BYTE[768];
|
||||
memcpy(voxel->Palette, rawvoxel + voxelsize - 768, 768);
|
||||
|
||||
return voxel;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FVoxelMipLevel Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FVoxelMipLevel::FVoxelMipLevel()
|
||||
{
|
||||
SizeZ = SizeY = SizeX = 0;
|
||||
PivotZ = PivotY = PivotX = 0;
|
||||
OffsetX = NULL;
|
||||
OffsetXY = NULL;
|
||||
SlabData = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FVoxelMipLevel Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FVoxelMipLevel::~FVoxelMipLevel()
|
||||
{
|
||||
if (OffsetX != NULL)
|
||||
{
|
||||
delete[] OffsetX;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FVoxel Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FVoxel::FVoxel()
|
||||
{
|
||||
Palette = NULL;
|
||||
}
|
||||
|
||||
FVoxel::~FVoxel()
|
||||
{
|
||||
if (Palette != NULL) delete [] Palette;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Remap the voxel to the game palette
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FVoxel::Remap()
|
||||
{
|
||||
if (Palette != NULL)
|
||||
{
|
||||
BYTE *remap = GetVoxelRemap(Palette);
|
||||
for (int i = 0; i < NumMips; ++i)
|
||||
{
|
||||
RemapVoxelSlabs((kvxslab_t *)Mips[i].SlabData, Mips[i].OffsetX[Mips[i].SizeX], remap);
|
||||
}
|
||||
delete [] Palette;
|
||||
Palette = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -389,10 +687,4 @@ CCMD (printspans)
|
|||
Printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (picnum)
|
||||
{
|
||||
//int picnum = TexMan.GetTexture (argv[1], FTexture::TEX_Any);
|
||||
//Printf ("%d: %s - %s\n", picnum, TexMan[picnum]->Name, TexMan(picnum)->Name);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -144,4 +144,6 @@ extern size_t numfakecmaps;
|
|||
|
||||
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin
|
||||
|
||||
FVoxel *R_LoadKVX(int lumpnum);
|
||||
|
||||
#endif
|
||||
|
|
95
src/r_defs.h
95
src/r_defs.h
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "templates.h"
|
||||
#include "memarena.h"
|
||||
|
||||
// Some more or less basic data types
|
||||
// we depend on.
|
||||
|
@ -1051,7 +1052,6 @@ struct column_t
|
|||
|
||||
typedef BYTE lighttable_t; // This could be wider for >8 bit display.
|
||||
|
||||
|
||||
// A vissprite_t is a thing
|
||||
// that will be drawn during a refresh.
|
||||
// I.e. a sprite object that is partly visible.
|
||||
|
@ -1059,8 +1059,9 @@ struct vissprite_t
|
|||
{
|
||||
short x1, x2;
|
||||
fixed_t cx; // for line side calculation
|
||||
fixed_t gx, gy; // for drawseg and fake floor clipping
|
||||
fixed_t gz, gzt; // global bottom / top for silhouette clipping
|
||||
fixed_t gx, gy, gz; // origin in world coordinates
|
||||
angle_t angle;
|
||||
fixed_t gzb, gzt; // global bottom / top for silhouette clipping
|
||||
fixed_t startfrac; // horizontal position of x1
|
||||
fixed_t xscale, yscale;
|
||||
fixed_t xiscale; // negative if flipped
|
||||
|
@ -1073,12 +1074,17 @@ struct vissprite_t
|
|||
sector_t *sector; // [RH] sector this sprite is in
|
||||
fixed_t alpha;
|
||||
fixed_t floorclip;
|
||||
FTexture *pic;
|
||||
union
|
||||
{
|
||||
FTexture *pic;
|
||||
struct FVoxel *voxel;
|
||||
};
|
||||
BYTE bIsVoxel:1; // [RH] Use voxel instead of pic
|
||||
BYTE bSplitSprite:1; // [RH] Sprite was split by a drawseg
|
||||
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
|
||||
short renderflags;
|
||||
DWORD Translation; // [RH] for color translation
|
||||
FRenderStyle RenderStyle;
|
||||
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
|
||||
BYTE bSplitSprite; // [RH] Sprite was split by a drawseg
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -1100,14 +1106,16 @@ enum
|
|||
//
|
||||
struct spriteframe_t
|
||||
{
|
||||
struct FVoxelDef *Voxel;// voxel to use for this frame
|
||||
FTextureID Texture[16]; // texture to use for view angles 0-15
|
||||
WORD Flip; // flip (1 = flip) to use for view angles 0-15.
|
||||
WORD Flip; // flip (1 = flip) to use for view angles 0-15.
|
||||
};
|
||||
|
||||
//
|
||||
// A sprite definition:
|
||||
// a number of animation frames.
|
||||
//
|
||||
|
||||
struct spritedef_t
|
||||
{
|
||||
union
|
||||
|
@ -1140,4 +1148,77 @@ public:
|
|||
int namespc; // namespace for this skin
|
||||
};
|
||||
|
||||
|
||||
// [RH] Voxels from Build
|
||||
|
||||
#define MAXVOXMIPS 5
|
||||
|
||||
struct kvxslab_t
|
||||
{
|
||||
BYTE ztop; // starting z coordinate of top of slab
|
||||
BYTE zleng; // # of bytes in the color array - slab height
|
||||
BYTE backfacecull; // low 6 bits tell which of 6 faces are exposed
|
||||
BYTE col[1/*zleng*/];// color data from top to bottom
|
||||
};
|
||||
|
||||
struct FVoxelMipLevel
|
||||
{
|
||||
FVoxelMipLevel();
|
||||
~FVoxelMipLevel();
|
||||
|
||||
int SizeX;
|
||||
int SizeY;
|
||||
int SizeZ;
|
||||
fixed_t PivotX; // 24.8 fixed point
|
||||
fixed_t PivotY; // ""
|
||||
fixed_t PivotZ; // ""
|
||||
int *OffsetX;
|
||||
short *OffsetXY;
|
||||
BYTE *SlabData;
|
||||
};
|
||||
|
||||
struct FVoxel
|
||||
{
|
||||
int LumpNum;
|
||||
int NumMips;
|
||||
BYTE *Palette;
|
||||
FVoxelMipLevel Mips[MAXVOXMIPS];
|
||||
|
||||
FVoxel();
|
||||
~FVoxel();
|
||||
void Remap();
|
||||
};
|
||||
|
||||
struct FVoxelDef
|
||||
{
|
||||
FVoxel *Voxel;
|
||||
int PlacedSpin; // degrees/sec to spin actors without MF_DROPPED set
|
||||
int DroppedSpin; // degrees/sec to spin actors with MF_DROPPED set
|
||||
fixed_t Scale;
|
||||
angle_t AngleOffset; // added to actor's angle to compensate for wrong-facing voxels
|
||||
};
|
||||
|
||||
// [RH] A c-buffer. Used for keeping track of offscreen voxel spans.
|
||||
|
||||
struct FCoverageBuffer
|
||||
{
|
||||
struct Span
|
||||
{
|
||||
Span *NextSpan;
|
||||
short Start, Stop;
|
||||
};
|
||||
|
||||
FCoverageBuffer(int size);
|
||||
~FCoverageBuffer();
|
||||
|
||||
void Clear();
|
||||
void InsertSpan(int listnum, int start, int stop);
|
||||
Span *AllocSpan();
|
||||
|
||||
FMemArena SpanArena;
|
||||
Span **Spans; // [0..NumLists-1] span lists
|
||||
Span *FreeSpans;
|
||||
unsigned int NumLists;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1352,6 +1352,97 @@ void R_FillSpan (void)
|
|||
memset (ylookup[ds_y] + ds_x1 + dc_destorg, ds_color, ds_x2 - ds_x1 + 1);
|
||||
}
|
||||
|
||||
// Draw a voxel slab
|
||||
//
|
||||
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
||||
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||
// See the included license file "BUILDLIC.TXT" for license info.
|
||||
|
||||
// Actually, this is just R_DrawColumn with an extra width parameter.
|
||||
|
||||
#ifndef X86_ASM
|
||||
static const BYTE *slabcolormap;
|
||||
|
||||
extern "C" void R_SetupDrawSlab(const BYTE *colormap)
|
||||
{
|
||||
slabcolormap = colormap;
|
||||
}
|
||||
|
||||
extern "C" void STACK_ARGS R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *vptr, BYTE *p)
|
||||
{
|
||||
int x;
|
||||
const BYTE *colormap = slabcolormap;
|
||||
int pitch = dc_pitch;
|
||||
|
||||
assert(dx > 0);
|
||||
|
||||
if (dx == 1)
|
||||
{
|
||||
while (dy > 0)
|
||||
{
|
||||
*p = colormap[vptr[v >> FRACBITS]];
|
||||
p += pitch;
|
||||
v += vi;
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
else if (dx == 2)
|
||||
{
|
||||
while (dy > 0)
|
||||
{
|
||||
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||
p[0] = color;
|
||||
p[1] = color;
|
||||
p += pitch;
|
||||
v += vi;
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
else if (dx == 3)
|
||||
{
|
||||
while (dy > 0)
|
||||
{
|
||||
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||
p[0] = color;
|
||||
p[1] = color;
|
||||
p[2] = color;
|
||||
p += pitch;
|
||||
v += vi;
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
else if (dx == 4)
|
||||
{
|
||||
while (dy > 0)
|
||||
{
|
||||
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||
p[0] = color;
|
||||
p[1] = color;
|
||||
p[2] = color;
|
||||
p[3] = color;
|
||||
p += pitch;
|
||||
v += vi;
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
else while (dy > 0)
|
||||
{
|
||||
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||
// The optimizer will probably turn this into a memset call.
|
||||
// Since dx is not likely to be large, I'm not sure that's a good thing,
|
||||
// hence the alternatives above.
|
||||
for (x = 0; x < dx; x++)
|
||||
{
|
||||
p[x] = color;
|
||||
}
|
||||
p += pitch;
|
||||
v += vi;
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************/
|
||||
/****************************************************/
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ extern "C" BYTE* palookupoffse[4];
|
|||
extern "C" const BYTE* bufplce[4];
|
||||
|
||||
// [RH] Temporary buffer for column drawing
|
||||
extern "C" BYTE dc_temp[MAXHEIGHT*4];
|
||||
extern "C" BYTE *dc_temp;
|
||||
extern "C" unsigned int dc_tspans[4][MAXHEIGHT];
|
||||
extern "C" unsigned int *dc_ctspan[4];
|
||||
extern "C" unsigned int horizspans[4];
|
||||
|
@ -178,7 +178,7 @@ extern void (STACK_ARGS *rt_map4cols)(int sx, int yl, int yh);
|
|||
void rt_draw4cols (int sx);
|
||||
|
||||
// [RH] Preps the temporary horizontal buffer.
|
||||
void rt_initcols (void);
|
||||
void rt_initcols (BYTE *buffer=NULL);
|
||||
|
||||
void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip);
|
||||
|
||||
|
@ -216,6 +216,9 @@ void R_FillColumnP (void);
|
|||
void R_FillColumnHorizP (void);
|
||||
void R_FillSpan (void);
|
||||
|
||||
extern "C" void R_SetupDrawSlab(const BYTE *colormap);
|
||||
extern "C" void STACK_ARGS R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *vptr, BYTE *p);
|
||||
|
||||
extern "C" int ds_y;
|
||||
extern "C" int ds_x1;
|
||||
extern "C" int ds_x2;
|
||||
|
|
|
@ -52,9 +52,13 @@
|
|||
// dc_temp is the buffer R_DrawColumnHoriz writes into.
|
||||
// dc_tspans points into it.
|
||||
// dc_ctspan points into dc_tspans.
|
||||
// But what is horizspan, and what is its relation with dc_ctspan?
|
||||
// horizspan also points into dc_tspans.
|
||||
|
||||
BYTE dc_temp[MAXHEIGHT*4];
|
||||
// dc_ctspan is advanced while drawing into dc_temp.
|
||||
// horizspan is advanced up to dc_ctspan when drawing from dc_temp to the screen.
|
||||
|
||||
BYTE dc_tempbuff[MAXHEIGHT*4];
|
||||
BYTE *dc_temp;
|
||||
unsigned int dc_tspans[4][MAXHEIGHT];
|
||||
unsigned int *dc_ctspan[4];
|
||||
unsigned int *horizspan[4];
|
||||
|
@ -998,10 +1002,11 @@ void rt_draw4cols (int sx)
|
|||
|
||||
// Before each pass through a rendering loop that uses these routines,
|
||||
// call this function to set up the span pointers.
|
||||
void rt_initcols (void)
|
||||
void rt_initcols (BYTE *buff)
|
||||
{
|
||||
int y;
|
||||
|
||||
dc_temp = buff == NULL ? dc_tempbuff : buff;
|
||||
for (y = 3; y >= 0; y--)
|
||||
horizspan[y] = dc_ctspan[y] = &dc_tspans[y][0];
|
||||
}
|
||||
|
@ -1035,26 +1040,18 @@ void R_DrawColumnHorizP_C (void)
|
|||
const BYTE *source = dc_source;
|
||||
|
||||
if (count & 1) {
|
||||
*dest = source[frac>>FRACBITS];
|
||||
dest += 4;
|
||||
frac += fracstep;
|
||||
*dest = source[frac>>FRACBITS]; dest += 4; frac += fracstep;
|
||||
}
|
||||
if (count & 2) {
|
||||
dest[0] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest += 8;
|
||||
}
|
||||
if (count & 4) {
|
||||
dest[0] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[8] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[12] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[8] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[12]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest += 16;
|
||||
}
|
||||
count >>= 3;
|
||||
|
@ -1062,22 +1059,14 @@ void R_DrawColumnHorizP_C (void)
|
|||
|
||||
do
|
||||
{
|
||||
dest[0] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[8] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[12] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[16] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[20] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[24] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[28] = source[frac>>FRACBITS];
|
||||
frac += fracstep;
|
||||
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[8] = source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[12]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[16]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[20]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[24]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest[28]= source[frac>>FRACBITS]; frac += fracstep;
|
||||
dest += 32;
|
||||
} while (--count);
|
||||
}
|
||||
|
@ -1110,8 +1099,7 @@ void R_FillColumnHorizP (void)
|
|||
if (!(count >>= 1))
|
||||
return;
|
||||
do {
|
||||
dest[0] = color;
|
||||
dest[4] = color;
|
||||
dest[0] = color; dest[4] = color;
|
||||
dest += 8;
|
||||
} while (--count);
|
||||
}
|
||||
|
|
|
@ -102,7 +102,6 @@ static fixed_t MaxVisForFloor;
|
|||
static FRandom pr_torchflicker ("TorchFlicker");
|
||||
static FRandom pr_hom;
|
||||
static TArray<InterpolationViewer> PastViewers;
|
||||
static int centerxwide;
|
||||
static bool polyclipped;
|
||||
static bool r_showviewer;
|
||||
bool r_dontmaplines;
|
||||
|
@ -134,6 +133,7 @@ float LastFOV;
|
|||
int WidescreenRatio;
|
||||
|
||||
fixed_t GlobVis;
|
||||
fixed_t viewingrangerecip;
|
||||
fixed_t FocalTangent;
|
||||
fixed_t FocalLengthX;
|
||||
fixed_t FocalLengthY;
|
||||
|
@ -150,6 +150,8 @@ float WallTMapScale2;
|
|||
extern "C" {
|
||||
int centerx;
|
||||
int centery;
|
||||
int centerxwide;
|
||||
|
||||
}
|
||||
|
||||
DCanvas *RenderTarget; // [RH] canvas to render to
|
||||
|
@ -158,6 +160,7 @@ fixed_t globaluclip, globaldclip;
|
|||
fixed_t centerxfrac;
|
||||
fixed_t centeryfrac;
|
||||
fixed_t yaspectmul;
|
||||
fixed_t baseyaspectmul; // yaspectmul without a forced aspect ratio
|
||||
float iyaspectmulfloat;
|
||||
fixed_t InvZtoScale;
|
||||
|
||||
|
@ -457,6 +460,9 @@ void R_InitTextureMapping ()
|
|||
FocalLengthY = Scale (centerxfrac, yaspectmul, hitan);
|
||||
FocalLengthXfloat = (float)FocalLengthX / 65536.f;
|
||||
|
||||
// This is 1/FocalTangent before the widescreen extension of FOV.
|
||||
viewingrangerecip = DivScale32(1, finetangent[FINEANGLES/4+(FieldOfView/2)]);
|
||||
|
||||
// Now generate xtoviewangle for sky texture mapping.
|
||||
// [RH] Do not generate viewangletox, because texture mapping is no
|
||||
// longer done with trig, so it's not needed.
|
||||
|
@ -599,7 +605,7 @@ void R_SetViewSize (int blocks)
|
|||
|
||||
void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
||||
{
|
||||
int virtheight, virtwidth;
|
||||
int virtheight, virtwidth, trueratio, virtwidth2, virtheight2;
|
||||
|
||||
if (windowSize >= 11)
|
||||
{
|
||||
|
@ -620,7 +626,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
|||
}
|
||||
|
||||
// If the screen is approximately 16:9 or 16:10, consider it widescreen.
|
||||
WidescreenRatio = CheckRatio (fullWidth, fullHeight);
|
||||
WidescreenRatio = CheckRatio (fullWidth, fullHeight, &trueratio);
|
||||
|
||||
DrawFSHUD = (windowSize == 11);
|
||||
|
||||
|
@ -643,8 +649,18 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
|||
centerxfrac = centerx<<FRACBITS;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
|
||||
virtwidth = fullWidth;
|
||||
virtheight = fullHeight;
|
||||
virtwidth = virtwidth2 = fullWidth;
|
||||
virtheight = virtheight2 = fullHeight;
|
||||
|
||||
if (trueratio & 4)
|
||||
{
|
||||
virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48;
|
||||
}
|
||||
else
|
||||
{
|
||||
virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48;
|
||||
}
|
||||
|
||||
if (WidescreenRatio & 4)
|
||||
{
|
||||
virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48;
|
||||
|
@ -656,6 +672,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
|||
centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48;
|
||||
}
|
||||
|
||||
baseyaspectmul = Scale(320 << FRACBITS, virtheight2, r_Yaspect * virtwidth2);
|
||||
yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth);
|
||||
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
|
||||
InvZtoScale = yaspectmul * centerx;
|
||||
|
|
|
@ -43,6 +43,7 @@ extern fixed_t viewsin;
|
|||
extern fixed_t viewtancos;
|
||||
extern fixed_t viewtansin;
|
||||
extern fixed_t FocalTangent;
|
||||
extern fixed_t viewingrangerecip;
|
||||
extern fixed_t FocalLengthX, FocalLengthY;
|
||||
extern float FocalLengthXfloat;
|
||||
extern fixed_t InvZtoScale;
|
||||
|
@ -62,7 +63,7 @@ extern int viewwindowy;
|
|||
|
||||
|
||||
|
||||
extern "C" int centerx;
|
||||
extern "C" int centerx, centerxwide;
|
||||
extern "C" int centery;
|
||||
|
||||
extern fixed_t centerxfrac;
|
||||
|
|
1329
src/r_things.cpp
1329
src/r_things.cpp
File diff suppressed because it is too large
Load diff
|
@ -104,6 +104,14 @@ void R_ClearSprites ();
|
|||
void R_DrawMasked ();
|
||||
void R_DrawRemainingPlayerSprites ();
|
||||
|
||||
void R_CheckOffscreenBuffer(int width, int height, bool spansonly);
|
||||
|
||||
enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2 };
|
||||
|
||||
void R_DrawVoxel(fixed_t dasprx, fixed_t daspry, fixed_t dasprz, angle_t dasprang,
|
||||
fixed_t daxscale, fixed_t dayscale, FVoxel *voxobj,
|
||||
lighttable_t *colormap, short *daumost, short *dadmost, int minslabz, int maxslabz, int flags);
|
||||
|
||||
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);
|
||||
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ bool FWadFile::Open(bool quiet)
|
|||
SetNamespace("TX_START", "TX_END", ns_newtextures);
|
||||
SetNamespace("V_START", "V_END", ns_strifevoices);
|
||||
SetNamespace("HI_START", "HI_END", ns_hires);
|
||||
SetNamespace("VX_START", "VX_END", ns_voxels);
|
||||
SkinHack();
|
||||
}
|
||||
delete [] fileinfo;
|
||||
|
|
|
@ -116,6 +116,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
|
|||
!strncmp(iname, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(iname, "hires/", 6) ? ns_hires :
|
||||
!strncmp(iname, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(iname, "voxels/", 7) ? ns_voxels :
|
||||
!strncmp(iname, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(iname, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(iname, "voices/", 7) ? ns_strifevoices :
|
||||
|
@ -137,7 +138,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
|
|||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
else if (Namespace == ns_sprites)
|
||||
else if (Namespace == ns_sprites || Namespace == ns_voxels)
|
||||
{
|
||||
char *c;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ extern fixed_t finesine[5*FINEANGLES/4];
|
|||
// (encapsulated in a struct so that we can still use array accesses).
|
||||
struct cosine_inline
|
||||
{
|
||||
fixed_t operator[] (unsigned int x)
|
||||
fixed_t operator[] (unsigned int x) const
|
||||
{
|
||||
return finesine[x+FINEANGLES/4];
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ void FTextureManager::AddTiles (void *tiles)
|
|||
rot.Texture[8] =
|
||||
rot.Texture[9] = texnum.GetIndex() + 4;
|
||||
rot.Flip = 0x00FC;
|
||||
rot.Voxel = NULL;
|
||||
tex->Rotations = SpriteFrames.Push (rot);
|
||||
}
|
||||
else if (rotType == 2)
|
||||
|
@ -247,6 +248,7 @@ void FTextureManager::AddTiles (void *tiles)
|
|||
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
||||
}
|
||||
rot.Flip = 0;
|
||||
rot.Voxel = NULL;
|
||||
tex->Rotations = SpriteFrames.Push (rot);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1313,6 +1313,21 @@ void DFrameBuffer::RenderView(player_t *player)
|
|||
FCanvasTextureInfo::UpdateAll ();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
extern TDeletingArray<FVoxel *> Voxels;
|
||||
|
||||
void DFrameBuffer::RemapVoxels()
|
||||
{
|
||||
for (unsigned i=0; i<Voxels.Size(); i++)
|
||||
{
|
||||
Voxels[i]->Remap();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Render the view to a savegame picture
|
||||
|
@ -1689,6 +1704,7 @@ void V_Init2()
|
|||
Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
screen->SetGamma (gamma);
|
||||
screen->RemapVoxels();
|
||||
FBaseCVar::ResetColors ();
|
||||
C_NewModeAdjust();
|
||||
M_InitVideoModesMenu();
|
||||
|
@ -1733,43 +1749,61 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
|
|||
// 1: 16:9
|
||||
// 2: 16:10
|
||||
// 4: 5:4
|
||||
int CheckRatio (int width, int height)
|
||||
int CheckRatio (int width, int height, int *trueratio)
|
||||
{
|
||||
int fakeratio = -1;
|
||||
int ratio;
|
||||
|
||||
if ((vid_aspect >=1) && (vid_aspect <=4))
|
||||
{
|
||||
// [SP] User wants to force aspect ratio; let them.
|
||||
return vid_aspect == 3? 0: int(vid_aspect);
|
||||
fakeratio = vid_aspect == 3? 0: int(vid_aspect);
|
||||
}
|
||||
if (vid_nowidescreen)
|
||||
{
|
||||
if (!vid_tft)
|
||||
{
|
||||
return 0;
|
||||
fakeratio = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fakeratio = (height * 5/4 == width) ? 4 : 0;
|
||||
}
|
||||
return (height * 5/4 == width) ? 4 : 0;
|
||||
}
|
||||
// If the size is approximately 16:9, consider it so.
|
||||
if (abs (height * 16/9 - width) < 10)
|
||||
{
|
||||
return 1;
|
||||
ratio = 1;
|
||||
}
|
||||
// 16:10 has more variance in the pixel dimensions. Grr.
|
||||
if (abs (height * 16/10 - width) < 60)
|
||||
else if (abs (height * 16/10 - width) < 60)
|
||||
{
|
||||
// 320x200 and 640x400 are always 4:3, not 16:10
|
||||
if ((width == 320 && height == 200) || (width == 640 && height == 400))
|
||||
{
|
||||
return 0;
|
||||
ratio = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ratio = 2;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
// Unless vid_tft is set, 1280x1024 is 4:3, not 5:4.
|
||||
if (height * 5/4 == width && vid_tft)
|
||||
else if (height * 5/4 == width && vid_tft)
|
||||
{
|
||||
return 4;
|
||||
ratio = 4;
|
||||
}
|
||||
// Assume anything else is 4:3.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
ratio = 0;
|
||||
}
|
||||
|
||||
if (trueratio != NULL)
|
||||
{
|
||||
*trueratio = ratio;
|
||||
}
|
||||
return (fakeratio >= 0) ? fakeratio : ratio;
|
||||
}
|
||||
|
||||
// First column: Base width (unused)
|
||||
|
|
|
@ -364,6 +364,9 @@ public:
|
|||
// Set the rect defining the area affected by blending.
|
||||
virtual void SetBlendingRect (int x1, int y1, int x2, int y2);
|
||||
|
||||
// Remap voxel palette
|
||||
virtual void RemapVoxels();
|
||||
|
||||
// render 3D view
|
||||
virtual void RenderView(player_t *player);
|
||||
|
||||
|
@ -500,7 +503,7 @@ void V_DrawFrame (int left, int top, int width, int height);
|
|||
extern "C" void ASM_PatchPitch (void);
|
||||
#endif
|
||||
|
||||
int CheckRatio (int width, int height);
|
||||
int CheckRatio (int width, int height, int *trueratio=NULL);
|
||||
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
|
||||
extern const int BaseRatioSizes[5][4];
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ typedef enum {
|
|||
ns_bloodmisc,
|
||||
ns_strifevoices,
|
||||
ns_hires,
|
||||
ns_voxels,
|
||||
|
||||
// These namespaces are only used to mark lumps in special subdirectories
|
||||
// so that their contents doesn't interfere with the global namespace.
|
||||
|
|
|
@ -704,6 +704,10 @@
|
|||
RelativePath=".\src\md5.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\memarena.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\name.cpp"
|
||||
>
|
||||
|
@ -1353,6 +1357,10 @@
|
|||
RelativePath=".\src\md5.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\memarena.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\mscinlines.h"
|
||||
>
|
||||
|
|
Loading…
Reference in a new issue