Update to ZDoom r3088:

* Added "special" console command for executing action specials.
    * Fixed buffer overflow attack for DEM_RUNSCRIPT(2).
    * Fixed: FMODSoundRenderer::DrawWaveDebug() only allocated enough space for the wavearray based on the window_size, so for large numbers of output channels, it would not allocate enough space for the spectrum data (which is definied by SPECTRUM_SIZE, not the window_size) and write junk on the stack when drawing the spectrums, causing a crash.
    * Merge voxels back into trunk. Even if it needs further tweaking, it should at least be stable now.
    * Added 'player.flechettetype' property so that the appropriate flechette type can be set per player class.
    * bumped savegame version for flechette type changes.
    * Added Chris's KDE IWAD picker submission.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@1153 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2011-01-02 22:29:16 +00:00
parent 3cbdbdf01f
commit 95f966faf5
38 changed files with 2745 additions and 252 deletions

View file

@ -705,6 +705,10 @@
RelativePath=".\src\md5.cpp" RelativePath=".\src\md5.cpp"
> >
</File> </File>
<File
RelativePath=".\src\memarena.cpp"
>
</File>
<File <File
RelativePath=".\src\name.cpp" RelativePath=".\src\name.cpp"
> >
@ -1350,6 +1354,10 @@
RelativePath=".\src\md5.h" RelativePath=".\src\md5.h"
> >
</File> </File>
<File
RelativePath=".\src\memarena.h"
>
</File>
<File <File
RelativePath=".\src\mscinlines.h" RelativePath=".\src\mscinlines.h"
> >

View file

@ -676,6 +676,7 @@ add_executable( zdoom WIN32
m_misc.cpp m_misc.cpp
m_png.cpp m_png.cpp
m_random.cpp m_random.cpp
memarena.cpp
md5.cpp md5.cpp
name.cpp name.cpp
nodebuild.cpp nodebuild.cpp

View file

@ -28,6 +28,9 @@
%define setupmvlineasm _setupmvlineasm %define setupmvlineasm _setupmvlineasm
%define mvlineasm1 _mvlineasm1 %define mvlineasm1 _mvlineasm1
%define mvlineasm4 _mvlineasm4 %define mvlineasm4 _mvlineasm4
%define R_SetupDrawSlab _R_SetupDrawSlab
%define R_DrawSlab _R_DrawSlab
%endif %endif
EXTERN ylookup ; near EXTERN ylookup ; near
@ -44,9 +47,6 @@ EXTERN dc_dest
EXTERN dc_source EXTERN dc_source
EXTERN dc_texturefrac EXTERN dc_texturefrac
mvlineasm4_counter:
dd 0
SECTION .text SECTION .text
ALIGN 16 ALIGN 16
@ -59,8 +59,45 @@ setvlinebpl_:
mov [fixchain2ma+2], eax mov [fixchain2ma+2], eax
mov [fixchain2mb+2], eax mov [fixchain2mb+2], eax
selfmod fixchain1a, fixchain2mb+6 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 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) ; pass it log2(texheight)
ALIGN 16 ALIGN 16
@ -549,6 +586,226 @@ mvcase0: jmp beginmvlineasm4
align 16 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 %ifdef M_TARGET_MACHO
GLOBAL _rtext_a_end GLOBAL _rtext_a_end
_rtext_a_end: _rtext_a_end:

View file

@ -850,8 +850,8 @@ GLOBAL R_DrawColumnHorizP_ASM
align 16 align 16
@R_DrawColumnHorizP_ASM@0: @R_DrawColumnHorizP_ASM@0:
R_DrawColumnHorizP_ASM:
_R_DrawColumnHorizP_ASM: _R_DrawColumnHorizP_ASM:
R_DrawColumnHorizP_ASM:
; count = dc_yh - dc_yl; ; count = dc_yh - dc_yl;
@ -870,8 +870,10 @@ _R_DrawColumnHorizP_ASM:
inc eax ; make 0 count mean 0 pixels inc eax ; make 0 count mean 0 pixels
and edx,3 and edx,3
push eax push eax
mov esi,[dc_ctspan+edx*4] mov eax,[dc_temp]
lea eax,[dc_temp+ecx*4+edx] ; eax = top of column in buffer 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 ebp,[dc_yh]
mov [esi],ecx mov [esi],ecx
mov [esi+4],ebp mov [esi+4],ebp
@ -1102,8 +1104,9 @@ _rt_copy1col_asm:
lea esi,[eax*4] lea esi,[eax*4]
inc ebx ; ebx = count inc ebx ; ebx = count
mov eax,edx mov eax,edx
lea ecx,[dc_temp+ecx+esi] ; ecx = source add ecx,esi
mov edi,[ylookup+esi] mov edi,[ylookup+esi]
add ecx,[dc_temp] ; ecx = source
mov esi,[dc_pitch] ; esi = pitch mov esi,[dc_pitch] ; esi = pitch
add eax,edi ; eax = dest add eax,edi ; eax = dest
add eax,[dc_destorg] add eax,[dc_destorg]
@ -1169,10 +1172,11 @@ _rt_copy4cols_asm:
inc ebx ; ebx = count inc ebx ; ebx = count
mov eax,ecx mov eax,ecx
mov esi,[ylookup+edx*4] mov esi,[ylookup+edx*4]
lea ecx,[dc_temp+edx*4] ; ecx = source mov ecx,[dc_temp]
mov edx,[dc_pitch] ; edx = pitch
add eax,esi ; eax = dest add eax,esi ; eax = dest
add eax,[dc_destorg] add eax,[dc_destorg]
lea ecx,[ecx+edx*4] ; ecx = source
mov edx,[dc_pitch] ; edx = pitch
shr ebx,1 shr ebx,1
jnc .even jnc .even
@ -1241,7 +1245,8 @@ _rt_map1col_asm:
mov esi,[dc_colormap] ; esi = colormap mov esi,[dc_colormap] ; esi = colormap
inc ebx ; ebx = count inc ebx ; ebx = count
mov eax,edx 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 ecx,[ylookup+edi]
mov edi,[dc_pitch] ; edi = pitch mov edi,[dc_pitch] ; edi = pitch
add eax,ecx ; eax = dest add eax,ecx ; eax = dest
@ -1320,7 +1325,8 @@ _rt_map4cols_asm1:
mov eax,ecx mov eax,ecx
inc ebx ; ebx = count inc ebx ; ebx = count
mov edi,[ylookup+edx] 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 add eax,edi ; eax = dest
mov edi,[dc_pitch] ; edi = pitch mov edi,[dc_pitch] ; edi = pitch
add eax,[dc_destorg] add eax,[dc_destorg]
@ -1414,7 +1420,8 @@ _rt_map4cols_asm2:
mov eax,ecx mov eax,ecx
inc ebx ; ebx = count inc ebx ; ebx = count
mov edi,[ylookup+edx] 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 add eax,edi ; eax = dest
mov edi,[dc_pitch] ; edi = pitch mov edi,[dc_pitch] ; edi = pitch
add eax,[dc_destorg] add eax,[dc_destorg]
@ -1493,10 +1500,11 @@ _rt_shaded4cols_asm:
add eax,[dc_destorg] ; eax = destination add eax,[dc_destorg] ; eax = destination
push ebx push ebx
push esi push esi
mov esi,[dc_temp]
inc ebp ; ebp = count inc ebp ; ebp = count
add eax,[esp+16] add eax,[esp+16]
push edi push edi
lea esi,[dc_temp+ecx*4] ; esi = source lea esi,[esi+ecx*4] ; esi = source
align 16 align 16
@ -1580,10 +1588,11 @@ _rt_add4cols_asm:
add eax,[dc_destorg] add eax,[dc_destorg]
push ebx push ebx
push esi push esi
mov esi,[dc_temp]
push ebp push ebp
inc edi inc edi
add eax,[esp+20] add eax,[esp+20]
lea esi,[dc_temp+ecx*4] lea esi,[esi+ecx*4]
align 16 align 16
a4loop: a4loop:
@ -1659,10 +1668,11 @@ _rt_addclamp4cols_asm:
add eax,[dc_destorg] add eax,[dc_destorg]
push ebx push ebx
push esi push esi
mov esi,[dc_temp]
push ebp push ebp
inc edi inc edi
add eax,[esp+20] add eax,[esp+20]
lea esi,[dc_temp+ecx*4] lea esi,[esi+ecx*4]
push edi push edi
align 16 align 16

View file

@ -453,7 +453,7 @@ CCMD (puke)
if (argc < 2 || argc > 5) if (argc < 2 || argc > 5)
{ {
Printf (" puke <script> [arg1] [arg2] [arg3]\n"); Printf ("Usage: puke <script> [arg1] [arg2] [arg3]\n");
} }
else else
{ {
@ -489,6 +489,52 @@ CCMD (puke)
} }
} }
CCMD (special)
{
int argc = argv.argc();
if (argc < 2 || argc > 7)
{
Printf("Usage: special <special-name> [arg1] [arg2] [arg3] [arg4] [arg5]\n");
}
else
{
int specnum;
if (argv[1][0] >= '0' && argv[1][0] <= '9')
{
specnum = atoi(argv[1]);
if (specnum < 0 || specnum > 255)
{
Printf("Bad special number\n");
return;
}
}
else
{
int min_args;
specnum = P_FindLineSpecial(argv[1], &min_args);
if (specnum == 0 || min_args < 0)
{
Printf("Unknown special\n");
return;
}
if (argc < 2 + min_args)
{
Printf("%s needs at least %d argument%s\n", argv[1], min_args, min_args == 1 ? "" : "s");
return;
}
}
Net_WriteByte(DEM_RUNSPECIAL);
Net_WriteByte(specnum);
Net_WriteByte(argc - 2);
for (int i = 2; i < argc; ++i)
{
Net_WriteLong(atoi(argv[i]));
}
}
}
CCMD (error) CCMD (error)
{ {
if (argv.argc() > 1) if (argv.argc() > 1)

View file

@ -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);
extern unsigned int MakeKey (const char *s, size_t len); extern unsigned int MakeKey (const char *s, size_t len);
extern unsigned int SuperFastHash (const char *data, size_t len);
#endif //__C_DISPATCH_H__ #endif //__C_DISPATCH_H__

View file

@ -57,6 +57,7 @@
#include "g_level.h" #include "g_level.h"
#include "d_event.h" #include "d_event.h"
#include "m_argv.h" #include "m_argv.h"
#include "p_lnspec.h"
int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backSide, int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backSide,
int arg0, int arg1, int arg2, int always, bool wantResultCode, bool net); int arg0, int arg1, int arg2, int always, bool wantResultCode, bool net);
@ -2316,13 +2317,38 @@ void Net_DoCommand (int type, BYTE **stream, int player)
for (i = 0; i < argn; ++i) for (i = 0; i < argn; ++i)
{ {
arg[i] = ReadLong (stream); int argval = ReadLong(stream);
if (i < countof(arg))
{
arg[i] = argval;
}
} }
P_StartScript (players[player].mo, NULL, snum, level.mapname, false, P_StartScript (players[player].mo, NULL, snum, level.mapname, false,
arg[0], arg[1], arg[2], type == DEM_RUNSCRIPT2, false, true); arg[0], arg[1], arg[2], type == DEM_RUNSCRIPT2, false, true);
} }
break; break;
case DEM_RUNSPECIAL:
{
int snum = ReadByte(stream);
int argn = ReadByte(stream);
int arg[5] = { 0, 0, 0, 0, 0 };
for (i = 0; i < argn; ++i)
{
int argval = ReadLong(stream);
if (i < countof(arg))
{
arg[i] = argval;
}
}
if (!CheckCheatmode(player == consoleplayer))
{
LineSpecials[snum](NULL, players[player].mo, false, arg[0], arg[1], arg[2], arg[3], arg[4]);
}
}
break;
case DEM_CROUCH: case DEM_CROUCH:
if (gamestate == GS_LEVEL && players[player].mo != NULL && if (gamestate == GS_LEVEL && players[player].mo != NULL &&
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP)) players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP))
@ -2521,6 +2547,10 @@ void Net_SkipCommand (int type, BYTE **stream)
skip = 3 + *(*stream + 2) * 4; skip = 3 + *(*stream + 2) * 4;
break; break;
case DEM_RUNSPECIAL:
skip = 2 + *(*stream + 1) * 4;
break;
case DEM_CONVREPLY: case DEM_CONVREPLY:
skip = 3; skip = 3;
break; break;

View file

@ -137,6 +137,7 @@ public:
int SpawnMask; int SpawnMask;
FNameNoInit MorphWeapon; FNameNoInit MorphWeapon;
fixed_t AttackZOffset; // attack height, relative to player center fixed_t AttackZOffset; // attack height, relative to player center
const PClass *FlechetteType;
// [CW] Fades for when you are being damaged. // [CW] Fades for when you are being damaged.
PalEntry DamageFade; PalEntry DamageFade;

View file

@ -158,6 +158,7 @@ enum EDemoCommand
DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number
DEM_CONVCLOSE, // 60 DEM_CONVCLOSE, // 60
DEM_CONVNULL, // 61 DEM_CONVNULL, // 61
DEM_RUNSPECIAL, // 62 Byte: Special number, Byte: Arg count, Ints: Args
}; };
// The following are implemented by cht_DoCheat in m_cheat.cpp // The following are implemented by cht_DoCheat in m_cheat.cpp

View file

@ -455,6 +455,8 @@ CCMD (drop)
} }
} }
const PClass *GetFlechetteType(AActor *other);
CCMD (useflechette) CCMD (useflechette)
{ // Select from one of arti_poisonbag1-3, whichever the player has { // Select from one of arti_poisonbag1-3, whichever the player has
static const ENamedName bagnames[3] = static const ENamedName bagnames[3] =
@ -463,22 +465,26 @@ CCMD (useflechette)
NAME_ArtiPoisonBag2, NAME_ArtiPoisonBag2,
NAME_ArtiPoisonBag3 NAME_ArtiPoisonBag3
}; };
int i, j;
if (who == NULL) if (who == NULL)
return; return;
if (who->IsKindOf (PClass::FindClass (NAME_ClericPlayer))) const PClass *type = GetFlechetteType(who);
i = 0; if (type != NULL)
else if (who->IsKindOf (PClass::FindClass (NAME_MagePlayer)))
i = 1;
else
i = 2;
for (j = 0; j < 3; ++j)
{ {
AInventory *item; AInventory *item;
if ( (item = who->FindInventory (bagnames[(i+j)%3])) ) if ( (item = who->FindInventory (type) ))
{
SendItemUse = item;
return;
}
}
// The default flechette could not be found. Try all 3 types then.
for (int j = 0; j < 3; ++j)
{
AInventory *item;
if ( (item = who->FindInventory (bagnames[j])) )
{ {
SendItemUse = item; SendItemUse = item;
break; break;

View file

@ -141,6 +141,27 @@ bool AArtiPoisonBag3::Use (bool pickup)
return false; return false;
} }
//============================================================================
//
// GetFlechetteType
//
//============================================================================
const PClass *GetFlechetteType(AActor *other)
{
const PClass *spawntype = NULL;
if (other->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
{
spawntype = static_cast<APlayerPawn*>(other)->FlechetteType;
}
if (spawntype == NULL)
{
// default fallback if nothing valid defined.
spawntype = RUNTIME_CLASS(AArtiPoisonBag3);
}
return spawntype;
}
//============================================================================ //============================================================================
// //
// AArtiPoisonBag :: HandlePickup // AArtiPoisonBag :: HandlePickup
@ -155,21 +176,7 @@ bool AArtiPoisonBag::HandlePickup (AInventory *item)
return Super::HandlePickup (item); return Super::HandlePickup (item);
} }
bool matched; if (GetClass() == GetFlechetteType(Owner))
if (Owner->IsKindOf (PClass::FindClass(NAME_ClericPlayer)))
{
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag1));
}
else if (Owner->IsKindOf (PClass::FindClass(NAME_MagePlayer)))
{
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag2));
}
else
{
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag3));
}
if (matched)
{ {
if (Amount < MaxAmount) if (Amount < MaxAmount)
{ {
@ -204,20 +211,8 @@ AInventory *AArtiPoisonBag::CreateCopy (AActor *other)
} }
AInventory *copy; AInventory *copy;
const PClass *spawntype;
if (other->IsKindOf (PClass::FindClass(NAME_ClericPlayer))) const PClass *spawntype = GetFlechetteType(other);
{
spawntype = RUNTIME_CLASS(AArtiPoisonBag1);
}
else if (other->IsKindOf (PClass::FindClass(NAME_MagePlayer)))
{
spawntype = RUNTIME_CLASS(AArtiPoisonBag2);
}
else
{
spawntype = RUNTIME_CLASS(AArtiPoisonBag3);
}
copy = static_cast<AInventory *>(Spawn (spawntype, 0, 0, 0, NO_REPLACE)); copy = static_cast<AInventory *>(Spawn (spawntype, 0, 0, 0, NO_REPLACE));
copy->Amount = Amount; copy->Amount = Amount;
copy->MaxAmount = MaxAmount; copy->MaxAmount = MaxAmount;

376
src/memarena.cpp Normal file
View 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
View 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.
};

View file

@ -432,7 +432,8 @@ void APlayerPawn::Serialize (FArchive &arc)
<< InvSel << InvSel
<< MorphWeapon << MorphWeapon
<< DamageFade << DamageFade
<< PlayerFlags; << PlayerFlags
<< FlechetteType;
} }
//=========================================================================== //===========================================================================

View file

@ -355,6 +355,304 @@ const BYTE *R_GetColumn (FTexture *tex, int col)
return tex->GetColumn (col, NULL); 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"); 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 #endif

View file

@ -145,4 +145,6 @@ extern size_t numfakecmaps;
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin int R_FindSkin (const char *name, int pclass); // [RH] Find a skin
FVoxel *R_LoadKVX(int lumpnum);
#endif #endif

View file

@ -25,6 +25,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "templates.h" #include "templates.h"
#include "memarena.h"
// Some more or less basic data types // Some more or less basic data types
// we depend on. // we depend on.
@ -1157,7 +1158,6 @@ struct column_t
typedef BYTE lighttable_t; // This could be wider for >8 bit display. typedef BYTE lighttable_t; // This could be wider for >8 bit display.
// A vissprite_t is a thing // A vissprite_t is a thing
// that will be drawn during a refresh. // that will be drawn during a refresh.
// I.e. a sprite object that is partly visible. // I.e. a sprite object that is partly visible.
@ -1165,8 +1165,9 @@ struct vissprite_t
{ {
short x1, x2; short x1, x2;
fixed_t cx; // for line side calculation fixed_t cx; // for line side calculation
fixed_t gx, gy; // for drawseg and fake floor clipping fixed_t gx, gy, gz; // origin in world coordinates
fixed_t gz, gzt; // global bottom / top for silhouette clipping angle_t angle;
fixed_t gzb, gzt; // global bottom / top for silhouette clipping
fixed_t startfrac; // horizontal position of x1 fixed_t startfrac; // horizontal position of x1
fixed_t xscale, yscale; fixed_t xscale, yscale;
fixed_t xiscale; // negative if flipped fixed_t xiscale; // negative if flipped
@ -1179,12 +1180,17 @@ struct vissprite_t
sector_t *sector; // [RH] sector this sprite is in sector_t *sector; // [RH] sector this sprite is in
fixed_t alpha; fixed_t alpha;
fixed_t floorclip; 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; short renderflags;
DWORD Translation; // [RH] for color translation DWORD Translation; // [RH] for color translation
FRenderStyle RenderStyle; FRenderStyle RenderStyle;
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
BYTE bSplitSprite; // [RH] Sprite was split by a drawseg
}; };
enum enum
@ -1206,14 +1212,16 @@ enum
// //
struct spriteframe_t struct spriteframe_t
{ {
struct FVoxelDef *Voxel;// voxel to use for this frame
FTextureID Texture[16]; // texture to use for view angles 0-15 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 sprite definition:
// a number of animation frames. // a number of animation frames.
// //
struct spritedef_t struct spritedef_t
{ {
union union
@ -1246,4 +1254,77 @@ public:
int namespc; // namespace for this skin 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 #endif

View file

@ -1352,6 +1352,97 @@ void R_FillSpan (void)
memset (ylookup[ds_y] + ds_x1 + dc_destorg, ds_color, ds_x2 - ds_x1 + 1); 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
/****************************************************/ /****************************************************/
/****************************************************/ /****************************************************/

View file

@ -53,7 +53,7 @@ extern "C" BYTE* palookupoffse[4];
extern "C" const BYTE* bufplce[4]; extern "C" const BYTE* bufplce[4];
// [RH] Temporary buffer for column drawing // [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_tspans[4][MAXHEIGHT];
extern "C" unsigned int *dc_ctspan[4]; extern "C" unsigned int *dc_ctspan[4];
extern "C" unsigned int horizspans[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); void rt_draw4cols (int sx);
// [RH] Preps the temporary horizontal buffer. // [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); 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_FillColumnHorizP (void);
void R_FillSpan (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_y;
extern "C" int ds_x1; extern "C" int ds_x1;
extern "C" int ds_x2; extern "C" int ds_x2;

View file

@ -52,9 +52,13 @@
// dc_temp is the buffer R_DrawColumnHoriz writes into. // dc_temp is the buffer R_DrawColumnHoriz writes into.
// dc_tspans points into it. // dc_tspans points into it.
// dc_ctspan points into dc_tspans. // 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_tspans[4][MAXHEIGHT];
unsigned int *dc_ctspan[4]; unsigned int *dc_ctspan[4];
unsigned int *horizspan[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, // Before each pass through a rendering loop that uses these routines,
// call this function to set up the span pointers. // call this function to set up the span pointers.
void rt_initcols (void) void rt_initcols (BYTE *buff)
{ {
int y; int y;
dc_temp = buff == NULL ? dc_tempbuff : buff;
for (y = 3; y >= 0; y--) for (y = 3; y >= 0; y--)
horizspan[y] = dc_ctspan[y] = &dc_tspans[y][0]; horizspan[y] = dc_ctspan[y] = &dc_tspans[y][0];
} }
@ -1035,26 +1040,18 @@ void R_DrawColumnHorizP_C (void)
const BYTE *source = dc_source; const BYTE *source = dc_source;
if (count & 1) { if (count & 1) {
*dest = source[frac>>FRACBITS]; *dest = source[frac>>FRACBITS]; dest += 4; frac += fracstep;
dest += 4;
frac += fracstep;
} }
if (count & 2) { if (count & 2) {
dest[0] = source[frac>>FRACBITS]; dest[0] = source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[4] = source[frac>>FRACBITS]; frac += fracstep;
dest[4] = source[frac>>FRACBITS];
frac += fracstep;
dest += 8; dest += 8;
} }
if (count & 4) { if (count & 4) {
dest[0] = source[frac>>FRACBITS]; dest[0] = source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[4] = source[frac>>FRACBITS]; frac += fracstep;
dest[4] = source[frac>>FRACBITS]; dest[8] = source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[12]= source[frac>>FRACBITS]; frac += fracstep;
dest[8] = source[frac>>FRACBITS];
frac += fracstep;
dest[12] = source[frac>>FRACBITS];
frac += fracstep;
dest += 16; dest += 16;
} }
count >>= 3; count >>= 3;
@ -1062,22 +1059,14 @@ void R_DrawColumnHorizP_C (void)
do do
{ {
dest[0] = source[frac>>FRACBITS]; dest[0] = source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[4] = source[frac>>FRACBITS]; frac += fracstep;
dest[4] = source[frac>>FRACBITS]; dest[8] = source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[12]= source[frac>>FRACBITS]; frac += fracstep;
dest[8] = source[frac>>FRACBITS]; dest[16]= source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[20]= source[frac>>FRACBITS]; frac += fracstep;
dest[12] = source[frac>>FRACBITS]; dest[24]= source[frac>>FRACBITS]; frac += fracstep;
frac += fracstep; dest[28]= 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; dest += 32;
} while (--count); } while (--count);
} }
@ -1110,8 +1099,7 @@ void R_FillColumnHorizP (void)
if (!(count >>= 1)) if (!(count >>= 1))
return; return;
do { do {
dest[0] = color; dest[0] = color; dest[4] = color;
dest[4] = color;
dest += 8; dest += 8;
} while (--count); } while (--count);
} }

View file

@ -106,7 +106,6 @@ static fixed_t MaxVisForFloor;
static FRandom pr_torchflicker ("TorchFlicker"); static FRandom pr_torchflicker ("TorchFlicker");
static FRandom pr_hom; static FRandom pr_hom;
static TArray<InterpolationViewer> PastViewers; static TArray<InterpolationViewer> PastViewers;
static int centerxwide;
static bool polyclipped; static bool polyclipped;
static bool r_showviewer; static bool r_showviewer;
bool r_dontmaplines; bool r_dontmaplines;
@ -138,6 +137,7 @@ float LastFOV;
int WidescreenRatio; int WidescreenRatio;
fixed_t GlobVis; fixed_t GlobVis;
fixed_t viewingrangerecip;
fixed_t FocalTangent; fixed_t FocalTangent;
fixed_t FocalLengthX; fixed_t FocalLengthX;
fixed_t FocalLengthY; fixed_t FocalLengthY;
@ -154,6 +154,8 @@ float WallTMapScale2;
extern "C" { extern "C" {
int centerx; int centerx;
int centery; int centery;
int centerxwide;
} }
DCanvas *RenderTarget; // [RH] canvas to render to DCanvas *RenderTarget; // [RH] canvas to render to
@ -162,6 +164,7 @@ fixed_t globaluclip, globaldclip;
fixed_t centerxfrac; fixed_t centerxfrac;
fixed_t centeryfrac; fixed_t centeryfrac;
fixed_t yaspectmul; fixed_t yaspectmul;
fixed_t baseyaspectmul; // yaspectmul without a forced aspect ratio
float iyaspectmulfloat; float iyaspectmulfloat;
fixed_t InvZtoScale; fixed_t InvZtoScale;
@ -461,6 +464,9 @@ void R_InitTextureMapping ()
FocalLengthY = Scale (centerxfrac, yaspectmul, hitan); FocalLengthY = Scale (centerxfrac, yaspectmul, hitan);
FocalLengthXfloat = (float)FocalLengthX / 65536.f; 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. // Now generate xtoviewangle for sky texture mapping.
// [RH] Do not generate viewangletox, because texture mapping is no // [RH] Do not generate viewangletox, because texture mapping is no
// longer done with trig, so it's not needed. // longer done with trig, so it's not needed.
@ -603,7 +609,7 @@ void R_SetViewSize (int blocks)
void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
{ {
int virtheight, virtwidth; int virtheight, virtwidth, trueratio, virtwidth2, virtheight2;
if (windowSize >= 11) if (windowSize >= 11)
{ {
@ -624,7 +630,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. // 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); DrawFSHUD = (windowSize == 11);
@ -647,8 +653,18 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
centerxfrac = centerx<<FRACBITS; centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS; centeryfrac = centery<<FRACBITS;
virtwidth = fullWidth; virtwidth = virtwidth2 = fullWidth;
virtheight = fullHeight; virtheight = virtheight2 = fullHeight;
if (trueratio & 4)
{
virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48;
}
else
{
virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48;
}
if (WidescreenRatio & 4) if (WidescreenRatio & 4)
{ {
virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48; virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48;
@ -660,6 +676,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48; centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48;
} }
baseyaspectmul = Scale(320 << FRACBITS, virtheight2, r_Yaspect * virtwidth2);
yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth); yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth);
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight; iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
InvZtoScale = yaspectmul * centerx; InvZtoScale = yaspectmul * centerx;

View file

@ -43,6 +43,7 @@ extern fixed_t viewsin;
extern fixed_t viewtancos; extern fixed_t viewtancos;
extern fixed_t viewtansin; extern fixed_t viewtansin;
extern fixed_t FocalTangent; extern fixed_t FocalTangent;
extern fixed_t viewingrangerecip;
extern fixed_t FocalLengthX, FocalLengthY; extern fixed_t FocalLengthX, FocalLengthY;
extern float FocalLengthXfloat; extern float FocalLengthXfloat;
extern fixed_t InvZtoScale; 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 "C" int centery;
extern fixed_t centerxfrac; extern fixed_t centerxfrac;

File diff suppressed because it is too large Load diff

View file

@ -104,6 +104,14 @@ void R_ClearSprites ();
void R_DrawMasked (); void R_DrawMasked ();
void R_DrawRemainingPlayerSprites (); 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); void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);

View file

@ -113,6 +113,7 @@ bool FWadFile::Open(bool quiet)
SetNamespace("TX_START", "TX_END", ns_newtextures); SetNamespace("TX_START", "TX_END", ns_newtextures);
SetNamespace("V_START", "V_END", ns_strifevoices); SetNamespace("V_START", "V_END", ns_strifevoices);
SetNamespace("HI_START", "HI_END", ns_hires); SetNamespace("HI_START", "HI_END", ns_hires);
SetNamespace("VX_START", "VX_END", ns_voxels);
SkinHack(); SkinHack();
} }
delete [] fileinfo; delete [] fileinfo;

View file

@ -116,6 +116,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
!strncmp(iname, "textures/", 9) ? ns_newtextures : !strncmp(iname, "textures/", 9) ? ns_newtextures :
!strncmp(iname, "hires/", 6) ? ns_hires : !strncmp(iname, "hires/", 6) ? ns_hires :
!strncmp(iname, "sprites/", 8) ? ns_sprites : !strncmp(iname, "sprites/", 8) ? ns_sprites :
!strncmp(iname, "voxels/", 7) ? ns_voxels :
!strncmp(iname, "colormaps/", 10) ? ns_colormaps : !strncmp(iname, "colormaps/", 10) ? ns_colormaps :
!strncmp(iname, "acs/", 4) ? ns_acslibrary : !strncmp(iname, "acs/", 4) ? ns_acslibrary :
!strncmp(iname, "voices/", 7) ? ns_strifevoices : !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 // 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 // we have to work around this for sprites because it is a valid
// frame character. // frame character.
else if (Namespace == ns_sprites) else if (Namespace == ns_sprites || Namespace == ns_voxels)
{ {
char *c; char *c;

View file

@ -608,6 +608,57 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
return defaultiwad; return defaultiwad;
} }
#if !defined(__APPLE__)
const char *str;
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
{
FString cmd("kdialog --title \""GAMESIG" "DOTVERSIONSTR": Select an IWAD to use\""
" --menu \"ZDoom found more than one IWAD\n"
"Select from the list below to determine which one to use:\"");
for(i = 0; i < numwads; ++i)
{
const char *filepart = strrchr(wads[i].Path, '/');
if(filepart == NULL)
filepart = wads[i].Path;
else
filepart++;
// Menu entries are specified in "tag" "item" pairs, where when a
// particular item is selected (and the Okay button clicked), its
// corresponding tag is printed to stdout for identification.
cmd.AppendFormat(" \"%d\" \"%s (%s)\"", i, wads[i].Name.GetChars(), filepart);
}
if(defaultiwad >= 0 && defaultiwad < numwads)
{
const char *filepart = strrchr(wads[defaultiwad].Path, '/');
if(filepart == NULL)
filepart = wads[defaultiwad].Path;
else
filepart++;
cmd.AppendFormat(" --default \"%s (%s)\"", wads[defaultiwad].Name.GetChars(), filepart);
}
FILE *f = popen(cmd, "r");
if(f != NULL)
{
char gotstr[16];
if(fgets(gotstr, sizeof(gotstr), f) == NULL ||
sscanf(gotstr, "%d", &i) != 1)
i = -1;
// Exit status = 1 means the selection was canceled (either by
// Cancel/Esc or the X button), not that there was an error running
// the program. In that case, nothing was printed so fgets will
// have failed. Other values can indicate an error running the app,
// so fall back to whatever else can be used.
int status = pclose(f);
if(WIFEXITED(status) && (WEXITSTATUS(status) == 0 || WEXITSTATUS(status) == 1))
return i;
}
}
#endif
#ifndef NO_GTK #ifndef NO_GTK
if (GtkAvailable) if (GtkAvailable)
{ {

View file

@ -2555,7 +2555,7 @@ void FMODSoundRenderer::DrawWaveDebug(int mode)
// 16 pixels of padding between each window. // 16 pixels of padding between each window.
window_size = (screen->GetWidth() - 16) / numoutchans - 16; window_size = (screen->GetWidth() - 16) / numoutchans - 16;
float *wavearray = (float*)alloca(window_size*sizeof(float)); float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float));
y = 16; y = 16;
y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode); y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);

View file

@ -60,7 +60,7 @@ extern fixed_t finesine[5*FINEANGLES/4];
// (encapsulated in a struct so that we can still use array accesses). // (encapsulated in a struct so that we can still use array accesses).
struct cosine_inline struct cosine_inline
{ {
fixed_t operator[] (unsigned int x) fixed_t operator[] (unsigned int x) const
{ {
return finesine[x+FINEANGLES/4]; return finesine[x+FINEANGLES/4];
} }

View file

@ -234,6 +234,7 @@ void FTextureManager::AddTiles (void *tiles)
rot.Texture[8] = rot.Texture[8] =
rot.Texture[9] = texnum.GetIndex() + 4; rot.Texture[9] = texnum.GetIndex() + 4;
rot.Flip = 0x00FC; rot.Flip = 0x00FC;
rot.Voxel = NULL;
tex->Rotations = SpriteFrames.Push (rot); tex->Rotations = SpriteFrames.Push (rot);
} }
else if (rotType == 2) else if (rotType == 2)
@ -247,6 +248,7 @@ void FTextureManager::AddTiles (void *tiles)
rot.Texture[17-j*2] = texnum.GetIndex() + j; rot.Texture[17-j*2] = texnum.GetIndex() + j;
} }
rot.Flip = 0; rot.Flip = 0;
rot.Voxel = NULL;
tex->Rotations = SpriteFrames.Push (rot); tex->Rotations = SpriteFrames.Push (rot);
} }
} }

View file

@ -601,11 +601,11 @@ DEFINE_PROPERTY(renderstyle, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
static const char * renderstyles[]={ static const char * renderstyles[]={
"NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD", "SHADED", "SHADOW", NULL}; "NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD","SHADED", NULL};
static const int renderstyle_values[]={ static const int renderstyle_values[]={
STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy,
STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, STYLE_Shadow}; STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded};
// make this work for old style decorations, too. // make this work for old style decorations, too.
if (!strnicmp(str, "style_", 6)) str+=6; if (!strnicmp(str, "style_", 6)) str+=6;
@ -2070,6 +2070,15 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn)
defaults->MorphWeapon = FName(z); defaults->MorphWeapon = FName(z);
} }
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player, flechettetype, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
defaults->FlechetteType = FindClassTentative(str, "ArtiPoisonBag");
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================

View file

@ -1313,6 +1313,21 @@ void DFrameBuffer::RenderView(player_t *player)
FCanvasTextureInfo::UpdateAll (); 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 // Render the view to a savegame picture
@ -1689,6 +1704,7 @@ void V_Init2()
Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT); Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
screen->SetGamma (gamma); screen->SetGamma (gamma);
screen->RemapVoxels();
FBaseCVar::ResetColors (); FBaseCVar::ResetColors ();
C_NewModeAdjust(); C_NewModeAdjust();
M_InitVideoModesMenu(); M_InitVideoModesMenu();
@ -1733,43 +1749,61 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
// 1: 16:9 // 1: 16:9
// 2: 16:10 // 2: 16:10
// 4: 5:4 // 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)) if ((vid_aspect >=1) && (vid_aspect <=4))
{ {
// [SP] User wants to force aspect ratio; let them. // [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_nowidescreen)
{ {
if (!vid_tft) 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 the size is approximately 16:9, consider it so.
if (abs (height * 16/9 - width) < 10) if (abs (height * 16/9 - width) < 10)
{ {
return 1; ratio = 1;
} }
// 16:10 has more variance in the pixel dimensions. Grr. // 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 // 320x200 and 640x400 are always 4:3, not 16:10
if ((width == 320 && height == 200) || (width == 640 && height == 400)) 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. // 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. // 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) // First column: Base width (unused)

View file

@ -364,6 +364,9 @@ public:
// Set the rect defining the area affected by blending. // Set the rect defining the area affected by blending.
virtual void SetBlendingRect (int x1, int y1, int x2, int y2); virtual void SetBlendingRect (int x1, int y1, int x2, int y2);
// Remap voxel palette
virtual void RemapVoxels();
// render 3D view // render 3D view
virtual void RenderView(player_t *player); 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); extern "C" void ASM_PatchPitch (void);
#endif #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)); } static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
extern const int BaseRatioSizes[5][4]; extern const int BaseRatioSizes[5][4];

View file

@ -66,7 +66,7 @@
// Protocol version used in demos. // Protocol version used in demos.
// Bump it if you change existing DEM_ commands or add new ones. // Bump it if you change existing DEM_ commands or add new ones.
// Otherwise, it should be safe to leave it alone. // Otherwise, it should be safe to leave it alone.
#define DEMOGAMEVERSION 0x213 #define DEMOGAMEVERSION 0x214
// Minimum demo version we can play. // Minimum demo version we can play.
// Bump it whenever you change or remove existing DEM_ commands. // Bump it whenever you change or remove existing DEM_ commands.
@ -77,7 +77,7 @@
// SAVESIG should match SAVEVER. // SAVESIG should match SAVEVER.
// MINSAVEVER is the minimum level snapshot version that can be loaded. // MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 3030 #define MINSAVEVER 3085
#if ZD_SVN_REVISION_NUMBER < MINSAVEVER #if ZD_SVN_REVISION_NUMBER < MINSAVEVER
// If we don't know the current revision write something very high to ensure that // If we don't know the current revision write something very high to ensure that

View file

@ -62,6 +62,7 @@ typedef enum {
ns_bloodmisc, ns_bloodmisc,
ns_strifevoices, ns_strifevoices,
ns_hires, ns_hires,
ns_voxels,
// These namespaces are only used to mark lumps in special subdirectories // These namespaces are only used to mark lumps in special subdirectories
// so that their contents doesn't interfere with the global namespace. // so that their contents doesn't interfere with the global namespace.

View file

@ -28,6 +28,7 @@ ACTOR ClericPlayer : PlayerPawn
Player.WeaponSlot 2, CWeapStaff Player.WeaponSlot 2, CWeapStaff
Player.WeaponSlot 3, CWeapFlame Player.WeaponSlot 3, CWeapFlame
Player.WeaponSlot 4, CWeapWraithverge Player.WeaponSlot 4, CWeapWraithverge
Player.FlechetteType "ArtiPoisonBag1"
Player.ColorRange 146, 163 Player.ColorRange 146, 163
Player.Colorset 0, "Blue", 146, 163, 161 Player.Colorset 0, "Blue", 146, 163, 161

View file

@ -30,6 +30,7 @@ ACTOR MagePlayer : PlayerPawn
Player.WeaponSlot 2, MWeapFrost Player.WeaponSlot 2, MWeapFrost
Player.WeaponSlot 3, MWeapLightning Player.WeaponSlot 3, MWeapLightning
Player.WeaponSlot 4, MWeapBloodscourge Player.WeaponSlot 4, MWeapBloodscourge
Player.FlechetteType "ArtiPoisonBag2"
Player.ColorRange 146, 163 Player.ColorRange 146, 163
Player.Colorset 0, "Blue", 146, 163, 161 Player.Colorset 0, "Blue", 146, 163, 161

View file

@ -28,6 +28,7 @@ Actor PlayerPawn : Actor native
Player.SoundClass "player" Player.SoundClass "player"
Player.DamageScreenColor "ff 00 00" Player.DamageScreenColor "ff 00 00"
Player.MugShotMaxHealth 0 Player.MugShotMaxHealth 0
Player.FlechetteType "ArtiPoisonBag3"
} }
Actor PlayerChunk : PlayerPawn native Actor PlayerChunk : PlayerPawn native