Update to ZDoom r922:

- Added Martin Howe's fixes for morphing and DECORATE function prototypes.
- Minor fixes in texture code.
- Fixed: The FMOD::System object was never released, only closed, so
  snd_reset would eventually run into the hard limit on the total number
  of FMOD::System objects that can be created concurrently (currently 15).
- Added proper error checks to the FMOD initialization process.
- Updated fmod_wrap.h for FMOD 4.14.
- Set note velocity back to using a linear sounding volume curve, although
  it's now used to scale channel volume and expression, so recompute_amp()
  is still only doing one volume curve lookup.
- Fixed: TimidityMIDIDevice caused a crash at the end of a non-looping song.
- Made translation support for multipatch textures operational.
- Added support for the GUS patch format's scale_frequency and scale_factor
  parameters. These seem to be used primarily to restrict percussion
  instruments to specific notes.
- Changed note velocity to not use the volume curve in recompute_amp(), since
  this sounds closer to TiMidity++, although I don't believe it's correct
  MIDI behavior. Also changed expression so that it scales the channel volume
  before going through the curve.
- Reworked load_instrument() to be less opaque.
- Went through the TiMidity code and removed pretty much all of the SDL_mixer
  extensions. The only exception would be kill_others(), which I reworked
  into a kill_key_group() function, which should be useful for DLS
  instruments in the future.
- Added translation support to multipatch textures. Not tested yet!
- Added Martin Howe's morph weapon update.
- Changed true color texture creation to use a newly defined Bitmap class
  instead of having the copy functions in the frame buffer class.
- Fixed: The WolfSS didn't have its obituary defined.
- Added submission for ACS CheckPlayerCamera ACS function.
- Removed FRadiusThingsIterator after discovering that VC++ misoptimized
  it in P_CheckPosition. Now FBlockThingsIterator is used with the distance
  check being done manually.


git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@94 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2008-04-17 20:58:50 +00:00
parent 7fef77f47b
commit 93df2a62bf
52 changed files with 1526 additions and 2628 deletions

View file

@ -2654,6 +2654,14 @@
RelativePath=".\src\textures\automaptexture.cpp"
>
</File>
<File
RelativePath=".\src\textures\bitmap.cpp"
>
</File>
<File
RelativePath=".\src\textures\bitmap.h"
>
</File>
<File
RelativePath=".\src\textures\buildtexture.cpp"
>

View file

@ -605,6 +605,12 @@ public:
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
}
bool intersects(AActor *other) const
{
fixed_t blockdist = radius + other->radius;
return ( abs(x - other->x) < blockdist && abs(y - other->y) < blockdist);
}
// Calculate amount of missile damage
virtual int GetMissileDamage(int mask, int add);

View file

@ -145,9 +145,9 @@ public:
player_t *oldplayer = CPlayer;
DBaseStatusBar::AttachToPlayer (player);
if (oldplayer != CPlayer)
if (oldplayer != CPlayer || savegamerestore/*added for morphing*/)
{
SetFace (&skins[CPlayer->userinfo.skin]);
SetFace (&skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin]);
}
if (multiplayer)
{
@ -211,7 +211,7 @@ private:
void Unload ();
~FDoomStatusBarTexture ();
void SetPlayerRemap(FRemapTable *remap);
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
FTextureFormat GetFormat()
{
@ -224,7 +224,7 @@ private:
FTexture *BaseTexture;
BYTE *Pixels;
FRemapTable *STBFremap;
FRemapTable *STFBRemap;
}
StatusBarTex;
@ -1044,7 +1044,7 @@ DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture ()
// now copy all the properties from the base texture
CopySize(BaseTexture);
Pixels = NULL;
STBFremap = NULL;
STFBRemap = NULL;
}
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out)
@ -1090,36 +1090,36 @@ void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL);
DrawToBar("STTPRCNT", 90, 3, NULL);
DrawToBar("STTPRCNT", 221, 3, NULL);
if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL);
if (multiplayer) DrawToBar("STFBANY", 143, 1, STFBRemap? STFBRemap->Remap : NULL);
}
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
FTexture *tex;
// rotate is never used here
BaseTexture->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x, y);
// rotate and inf are never used here
BaseTexture->CopyTrueColorPixels(bmp, x, y);
if (!deathmatch)
{
tex = TexMan["STARMS"];
if (tex != NULL)
{
tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+104, y);
tex->CopyTrueColorPixels(bmp, x+104, y);
}
}
tex = TexMan["STTPRCNT"];
if (tex != NULL)
{
tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+90, y+3);
tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+221, y+3);
tex->CopyTrueColorPixels(bmp, x+90, y+3);
tex->CopyTrueColorPixels(bmp, x+221, y+3);
}
if (multiplayer)
{
tex = TexMan["STFBANY"];
if (tex != NULL)
{
tex->CopyTrueColorTranslated(buffer, buf_pitch, buf_height, x+143, y+1, STBFremap);
tex->CopyTrueColorTranslated(bmp, x+143, y+1, 0, STFBRemap);
}
}
return -1;
@ -1141,7 +1141,7 @@ void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap)
{
Unload();
KillNative();
STBFremap = remap;
STFBRemap = remap;
}
DBaseStatusBar *CreateDoomStatusBar ()

View file

@ -5,6 +5,7 @@
#include "p_local.h"
#include "a_sharedglobal.h"
#include "s_sound.h"
#include "m_bbox.h"
static FRandom pr_thrustraise ("ThrustRaise");
@ -262,9 +263,14 @@ void A_ThrustBlock (AActor *actor)
void A_ThrustImpale (AActor *actor)
{
AActor *thing;
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
if (!thing->intersects(actor))
{
continue;
}
if (!(thing->flags & MF_SHOOTABLE) )
continue;

View file

@ -535,6 +535,7 @@ void APowerStrength::InitEffect ()
void APowerStrength::Tick ()
{
// Strength counts up to diminish the fade.
assert(EffectTics < (INT_MAX - 1)); // I can't see a game lasting nearly two years, but...
EffectTics += 2;
Super::Tick();
}
@ -998,6 +999,7 @@ void APowerFlight::Tick ()
// The Wings of Wrath only expire in multiplayer and non-hub games
if (!multiplayer && (level.flags & LEVEL_INFINITE_FLIGHT))
{
assert(EffectTics < INT_MAX); // I can't see a game lasting nearly two years, but...
EffectTics++;
}

View file

@ -206,6 +206,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
const PClass *exit_flash = player->MorphExitFlash;
bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON);
player->morphTics = 0;
player->MorphedPlayerClass = 0;
@ -267,13 +268,32 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
{
player->ReadyWeapon = player->PendingWeapon = NULL;
}
if (beastweap != NULL)
{ // You don't get to keep your morphed weapon.
if (beastweap->SisterWeapon != NULL)
if (correctweapon)
{ // Better "lose morphed weapon" semantics
const PClass *morphweapon = PClass::FindClass (mo->MorphWeapon);
if (morphweapon != NULL && morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
{
beastweap->SisterWeapon->Destroy ();
AWeapon *OriginalMorphWeapon = static_cast<AWeapon *>(mo->FindInventory (morphweapon));
if ((OriginalMorphWeapon != NULL) && (OriginalMorphWeapon->GivenAsMorphWeapon))
{ // You don't get to keep your morphed weapon.
if (OriginalMorphWeapon->SisterWeapon != NULL)
{
OriginalMorphWeapon->SisterWeapon->Destroy ();
}
OriginalMorphWeapon->Destroy ();
}
}
}
else // old behaviour (not really useful now)
{ // Assumptions made here are no longer valid
if (beastweap != NULL)
{ // You don't get to keep your morphed weapon.
if (beastweap->SisterWeapon != NULL)
{
beastweap->SisterWeapon->Destroy ();
}
beastweap->Destroy ();
}
beastweap->Destroy ();
}
pmo->tracer = NULL;
pmo->Destroy ();

View file

@ -17,7 +17,8 @@ enum
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
MORPH_WHENINVULNERABLE = 0x00000040 // Player can morph when invulnerable but ONLY if doing it to themselves
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph when invulnerable but ONLY if doing it to themselves
MORPH_LOSEACTUALWEAPON = 0X00000080 // Player loses specified morph weapon only (not "whichever they have when unmorphing")
};
struct PClass;

View file

@ -221,6 +221,7 @@ public:
// In-inventory instance variables
TObjPtr<AAmmo> Ammo1, Ammo2;
TObjPtr<AWeapon> SisterWeapon;
bool GivenAsMorphWeapon;
bool bAltFire; // Set when this weapon's alternate fire is used.

View file

@ -52,7 +52,7 @@ void AWeapon::Serialize (FArchive &arc)
<< ProjectileType << AltProjectileType
<< SelectionOrder
<< MoveCombatDist
<< Ammo1 << Ammo2 << SisterWeapon
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
<< bAltFire;
}
@ -230,6 +230,7 @@ void AWeapon::AttachToOwner (AActor *other)
StatusBar->ReceivedWeapon (this);
}
}
GivenAsMorphWeapon = false; // will be set explicitly by morphing code
}
//===========================================================================

View file

@ -63,15 +63,6 @@ public:
void Dim (PalEntry color, float damount, int x1, int y1, int w, int h);
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false);
// texture copy functions
virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
const BYTE * patch, int pix_width, int pix_height, int step_x, int step_y,
int rotate, int ct);
virtual void CopyPixelData(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
const BYTE * patch, int pix_width, int pix_height,
int step_x, int step_y, int rotate, PalEntry * palette);
void PrecacheTexture(FTexture *tex, bool cache);
// Create a native texture from a game texture.
@ -81,13 +72,6 @@ public:
void RenderView (player_t* player);
void WriteSavePic (player_t *player, FILE *file, int width, int height);
void SetTranslationInfo(int _cm, int _trans=-1337)
{
if (_cm != -1) cm = _cm;
if (_trans != -1337) translation = _trans;
}
bool WipeStartScreen(int type);
void WipeEndScreen();
bool WipeDo(int ticks);
@ -96,8 +80,12 @@ public:
private:
PalEntry Flash;
// Texture creation info
int cm;
int translation;
bool iscomplex;
PalEntry SourcePalette[256];
BYTE *ScreenshotBuffer;
@ -122,10 +110,5 @@ private:
};
inline void SetTranslationInfo(int _cm, int _trans=-1337)
{
static_cast<OpenGLFrameBuffer*>(screen)->SetTranslationInfo(_cm,_trans);
}
#endif //__GL_FRAMEBUFFER

View file

@ -329,7 +329,7 @@ int FGLTexture::CheckExternalFile(bool & hascolorkey)
// Checks for the presence of a hires texture replacement and loads it
//
//==========================================================================
unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height)
unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height, int cm)
{
if (HiresLump==-1)
{
@ -350,8 +350,11 @@ unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height)
unsigned char * buffer=new unsigned char[w*(h+1)*4];
memset(buffer, 0, w * (h+1) * 4);
FGLBitmap bmp(buffer, w*4, w, h);
bmp.SetTranslationInfo(cm);
int trans = hirestexture->CopyTrueColorPixels(buffer, w<<2, h, 0, 0);
int trans = hirestexture->CopyTrueColorPixels(&bmp, 0, 0);
CheckTrans(buffer, w*h, trans);
if (bHasColorkey)

View file

@ -76,9 +76,9 @@ public:
if (faces[0]) return faces[0]->GetPixels();
return NULL;
}
virtual int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y)
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
if (faces[0]) return faces[0]->CopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
if (faces[0]) return faces[0]->CopyTrueColorPixels(bmp, x, y, rotate, inf);
return 0;
}
bool UseBasePalette() { return false; } // not really but here it's not important.

View file

@ -48,6 +48,7 @@
#include "stats.h"
#include "templates.h"
#include "sc_man.h"
#include "r_translate.h"
#include "gl/gl_struct.h"
#include "gl/gl_framebuffer.h"
@ -94,8 +95,8 @@ EXTERN_CVAR(Bool, gl_render_precise)
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
static char GlobalBrightmap[256];
static bool HasGlobalBrightmap;
static FRemapTable GlobalBrightmap;
//===========================================================================
//
@ -111,7 +112,13 @@ void gl_GenerateGlobalBrightmapFromColormap()
const unsigned char *cmapdata = (const unsigned char *)cmap.GetMem();
const unsigned char *paldata = (const unsigned char *)palette.GetMem();
memset(GlobalBrightmap, 255, 256);
const int black = 0;
const int white = ColorMatcher.Pick(255,255,255);
GlobalBrightmap.MakeIdentity();
memset(GlobalBrightmap.Remap, white, 256);
for(int i=0;i<256;i++) GlobalBrightmap.Palette[i]=PalEntry(255,255,255);
for(int j=0;j<32;j++)
{
for(int i=0;i<256;i++)
@ -120,38 +127,18 @@ void gl_GenerateGlobalBrightmapFromColormap()
// and Hexen.
if (cmapdata[i+j*256]!=i || (paldata[3*i]<10 && paldata[3*i+1]<10 && paldata[3*i+2]<10))
{
GlobalBrightmap[i]=0;
GlobalBrightmap.Remap[i]=black;
GlobalBrightmap.Palette[i]=PalEntry(0,0,0);
}
}
}
for(int i=0;i<256;i++)
{
HasGlobalBrightmap|=!!GlobalBrightmap[i];
HasGlobalBrightmap |= GlobalBrightmap.Remap[i] == black;
//if (GlobalBrightmap[i]) Printf("Marked color %d as fullbright\n",i);
}
}
static const BYTE IcePalette[16][3] =
{
{ 10, 8, 18 },
{ 15, 15, 26 },
{ 20, 16, 36 },
{ 30, 26, 46 },
{ 40, 36, 57 },
{ 50, 46, 67 },
{ 59, 57, 78 },
{ 69, 67, 88 },
{ 79, 77, 99 },
{ 89, 87,109 },
{ 99, 97,120 },
{ 109,107,130 },
{ 118,118,141 },
{ 128,128,151 },
{ 138,138,162 },
{ 148,148,172 }
};
//===========================================================================
//
// multi-format pixel copy with colormap application
@ -300,16 +287,16 @@ static CopyFunc copyfuncs[]={
// base palette because they wouldn't be used anyway.
//
//===========================================================================
void OpenGLFrameBuffer::CopyPixelDataRGB(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
int rotate, int ct)
void FGLBitmap::CopyPixelDataRGB(int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
int rotate, int ct, FCopyInfo *inf)
{
if (ClipCopyPixelRect(texpitch>>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
buffer+=4*originx + texpitch*originy;
BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
for (int y=0;y<srcheight;y++)
{
copyfuncs[ct](&buffer[y*texpitch], &patch[y*step_y], cm, srcwidth, step_x);
copyfuncs[ct](&buffer[y*Pitch], &patch[y*step_y], cm, srcwidth, step_x);
}
}
}
@ -444,17 +431,16 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count)
// Paletted to True Color texture copy function
//
//===========================================================================
void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight,
int step_x, int step_y, int rotate, PalEntry * palette)
void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight,
int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf)
{
PalEntry penew[256];
int x,y,pos,i;
if (ClipCopyPixelRect(texpitch>>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
buffer+=4*originx + texpitch*originy;
BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
// CM_SHADE is an alpha map with 0==transparent and 1==opaque
if (cm == CM_SHADE)
@ -467,28 +453,6 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
penew[i]=0xffffffff; // If the palette contains transparent colors keep them.
}
}
else if (cm == CM_BRIGHTMAP)
{
if (palette == GetPalette() && translation >= 0)
{
for(int i=0;i<256;i++)
{
if (GlobalBrightmap[i] && palette[i].a==0)
{
penew[i] = PalEntry(0,255,255,255);
}
else
{
penew[i] = PalEntry(255,0,0,0);
}
}
}
else
{
for(int i=0;i<256;i++)
penew[i] = PalEntry(palette[i].a,0,0,0);
}
}
else
{
// apply any translation.
@ -535,7 +499,7 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
// This can also handle full PNG translucency.
for (y=0;y<srcheight;y++)
{
pos=(y*texpitch);
pos=(y*Pitch);
for (x=0;x<srcwidth;x++,pos+=4)
{
int v=(unsigned char)patch[y*step_y+x*step_x];
@ -568,23 +532,31 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
//
//===========================================================================
int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_height, int xx, int yy, int rotate)
int FWarpTexture::CopyTrueColorPixels(FBitmap *bmp, int xx, int yy, int rotate, FCopyInfo *inf)
{
if (gl_warp_shader || gl_glsl_renderer)
int buf_pitch = bmp->GetPitch();
int buf_width = bmp->GetWidth();
int buf_height = bmp->GetHeight();
if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
{
return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
}
unsigned long * in=new unsigned long[Width*Height];
FGLBitmap inb;
if (!inb.Create(Width, Height))
return false;
unsigned long * in = (unsigned long *)inb.GetPixels();
unsigned long * out;
bool direct;
int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{
out = (unsigned long*)buffer;
out = (unsigned long*)bmp->GetPixels();
direct=true;
}
else
@ -595,9 +567,9 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
static unsigned long linebuffer[4096]; // that's the maximum texture size for most graphics cards!
static unsigned long linebuffer[256]; // anything larger will bring down performance so it is excluded above.
int timebase = r_FrameTime*23/28;
int xsize = Width;
int ysize = Height;
@ -638,7 +610,7 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
if (xx<0) xx=0;
if (yy<0) yy=0;
unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
int linelen=MIN<int>(Width, buf_width-xx);
int linecount=MIN<int>(Height, buf_height-yy);
@ -649,7 +621,6 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
}
delete [] out;
}
delete [] in;
GenTime=r_FrameTime;
return ret;
}
@ -663,23 +634,31 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
//
//===========================================================================
int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_height, int xx, int yy, int rotate)
int FWarp2Texture::CopyTrueColorPixels(FBitmap *bmp, int xx, int yy, int rotate, FCopyInfo *inf)
{
if (gl_warp_shader || gl_glsl_renderer)
int buf_pitch = bmp->GetPitch();
int buf_width = bmp->GetWidth();
int buf_height = bmp->GetHeight();
if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
{
return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
}
unsigned long * in=new unsigned long[Width*Height];
FGLBitmap inb;
if (!inb.Create(Width, Height))
return false;
unsigned long * in = (unsigned long *)inb.GetPixels();
unsigned long * out;
bool direct;
int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{
out = (unsigned long*)buffer;
out = (unsigned long*)bmp->GetPixels();
direct=true;
}
else
@ -690,7 +669,7 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
int xsize = Width;
int ysize = Height;
@ -721,22 +700,22 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
if (!direct)
{
// Negative offsets cannot occur here.
// This can only happen for sprites so
// negative offsets cannot occur here.
if (xx<0) xx=0;
if (yy<0) yy=0;
unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
int linelen=MIN<int>(Width, buf_width-xx);
int linecount=MIN<int>(Height, buf_height-yy);
for(i=0;i<linecount;i++)
{
memcpy(targ, &out[Width*i], linelen*sizeof(unsigned long));
targ+=buf_width;
targ+=buf_pitch/4;
}
delete [] out;
}
delete [] in;
GenTime=r_FrameTime;
return ret;
}
@ -837,10 +816,9 @@ void FBrightmapTexture::Unload ()
{
}
int FBrightmapTexture::CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y)
int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
SetTranslationInfo(CM_BRIGHTMAP, 0);
SourcePic->CopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
SourcePic->CopyTrueColorTranslated(bmp, x, y, rotate, &GlobalBrightmap);
return 0;
}
@ -1198,13 +1176,12 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
unsigned char * buffer;
intptr_t cm = _cm;
SetTranslationInfo(cm, translation);
// Textures that are already scaled in the texture lump will not get replaced
// by hires textures
if (gl_texture_usehires && allowhires && scalex==1.f && scaley==1.f)
{
buffer = LoadHiresTexture (&w, &h);
buffer = LoadHiresTexture (&w, &h, _cm);
if (buffer)
{
return buffer;
@ -1214,14 +1191,32 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
w=Width;
h=Height;
buffer=new unsigned char[Width*(Height+1)*4];
memset(buffer, 0, Width * (Height+1) * 4);
if (translation<=0)
FGLBitmap bmp(buffer, Width*4, Width, Height);
bmp.SetTranslationInfo(cm, translation);
if (tex->bComplex)
{
FBitmap imgCreate;
// The texture contains special processing so it must be composited using with the
// base bitmap class and then be converted as a whole.
if (imgCreate.Create(Width, Height))
{
memset(imgCreate.GetPixels(), 0, Width * Height * 4);
int trans =
tex->CopyTrueColorPixels(&imgCreate, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), Width, Height, 4, Width*4, 0, CF_BGRA);
CheckTrans(buffer, w*h, trans);
}
}
else if (translation<=0)
{
int trans =
tex->CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
GetTopOffset() - tex->TopOffset);
tex->CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
CheckTrans(buffer, w*h, trans);
@ -1231,8 +1226,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
// When using translations everything must be mapped to the base palette.
// Since FTexture's method is doing exactly that by calling GetPixels let's use that here
// to do all the dirty work for us. ;)
tex->FTexture::CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
GetTopOffset() - tex->TopOffset);
tex->FTexture::CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
}
return buffer;

View file

@ -5,6 +5,7 @@
#include "gl/gltexture.h"
#include "r_data.h"
#include "i_system.h"
#include "textures/bitmap.h"
EXTERN_CVAR(Bool, gl_precache)
EXTERN_CVAR(Bool, gl_brightmap_shader)
@ -14,6 +15,31 @@ struct GL_RECT;
void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count);
void CopyColorsRGBA(unsigned char * pout, const unsigned char * pin, int cm, int count, int step);
class FGLBitmap : public FBitmap
{
int cm;
int translation;
public:
FGLBitmap() {}
FGLBitmap(BYTE *buffer, int pitch, int width, int height)
: FBitmap(buffer, pitch, width, height)
{}
void SetTranslationInfo(int _cm, int _trans=-1337)
{
if (_cm != -1) cm = _cm;
if (_trans != -1337) translation = _trans;
}
virtual void CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth,
int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL);
virtual void CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight,
int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf = NULL);
};
// Two intermediate classes which wrap the low level textures.
// These ones are returned by the Bind* functions to ensure
// that the coordinate functions aren't used without the texture
@ -125,7 +151,7 @@ private:
static bool SmoothEdges(unsigned char * buffer,int w, int h, bool clampsides);
int CheckDDPK3();
int CheckExternalFile(bool & hascolorkey);
unsigned char * LoadHiresTexture(int *width, int *height);
unsigned char * LoadHiresTexture(int *width, int *height, int cm);
void SetSize(int w, int h)
@ -247,7 +273,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf);
bool UseBasePalette() { return false; }
protected:

View file

@ -215,7 +215,7 @@ typedef struct fm_opl_f {
UINT32 eg_cnt; /* global envelope generator counter */
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
UINT32 eg_timer_add; /* step of eg_timer */
UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
UINT32 eg_timer_overflow; /* envelope generator timer overflows every 1 sample (on real chip) */
UINT32 fn_tab[1024]; /* fnumber->increment counter */

View file

@ -5339,7 +5339,21 @@ int DLevelScript::RunScript ()
static_cast<DSBarInfo*>(StatusBar)->SetMugShotState(FBehavior::StaticLookupString(STACK(1)));
}
break;
case PCD_CHECKPLAYERCAMERA:
{
int playernum = STACK(1);
if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL)
{
STACK(1) = -1;
}
else
{
STACK(1) = players[playernum].camera->tid;
}
}
break;
}
}

View file

@ -550,6 +550,7 @@ public:
PCD_SETMUGSHOTSTATE,
PCD_THINGCOUNTSECTOR,
PCD_THINGCOUNTNAMESECTOR,
PCD_CHECKPLAYERCAMERA, // [TN]
PCODE_COMMAND_COUNT
};

View file

@ -283,14 +283,6 @@ public:
void Reset() { StartBlock(minx, miny); }
};
class FRadiusThingsIterator : public FBlockThingsIterator
{
fixed_t X, Y, Radius;
public:
FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius);
AActor *Next();
};
class FPathTraverse
{
static TArray<intercept_t> intercepts;

View file

@ -254,7 +254,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
FRadiusThingsIterator it2(x, y, thing->radius);
FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
AActor *th;
while ((th = it2.Next()))
@ -266,6 +266,10 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
if (th == thing)
continue;
fixed_t blockdist = th->radius + tmf.thing->radius;
if ( abs(th->x - tmf.x) >= blockdist || abs(th->y - tmf.y) >= blockdist)
continue;
// [RH] Z-Check
// But not if not MF2_PASSMOBJ or MF3_DONTOVERLAP are set!
// Otherwise those things would get stuck inside each other.
@ -326,7 +330,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
void P_PlayerStartStomp (AActor *actor)
{
AActor *th;
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((th = it.Next()))
{
@ -337,6 +341,9 @@ void P_PlayerStartStomp (AActor *actor)
if (th == actor || (th->player == actor->player && th->player != NULL))
continue;
if (!th->intersects(actor))
continue;
// only kill monsters and other players
if (th->player == NULL && !(th->flags3 & MF3_ISMONSTER))
continue;
@ -672,7 +679,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
fixed_t topz;
bool solid;
int damage;
// don't clip against self
if (thing == tm.thing)
return true;
@ -680,6 +687,10 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true; // can't hit thing
fixed_t blockdist = thing->radius + tm.thing->radius;
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
return true;
tm.thing->BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
@ -1025,6 +1036,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
tm.x = x;
tm.y = y;
tm.z = thing->z;
FBoundingBox box(x, y, thing->radius);
@ -1097,7 +1109,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
tm.stepthing = NULL;
FRadiusThingsIterator it2(x, y, thing->radius);
FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
AActor *th;
while ((th = it2.Next()))
{
@ -1228,11 +1240,15 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj)
return true;
}
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
AActor *thing;
while ((thing = it.Next()))
{
if (!thing->intersects(actor))
{
continue;
}
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;
@ -3659,7 +3675,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
float bombdamagefloat = (float)bombdamage;
FVector3 bombvec(FIXED2FLOAT(bombspot->x), FIXED2FLOAT(bombspot->y), FIXED2FLOAT(bombspot->z));
FRadiusThingsIterator it(bombspot->x, bombspot->y, bombdistance<<FRACBITS);
FBlockThingsIterator it(FBoundingBox(bombspot->x, bombspot->y, bombdistance<<FRACBITS));
AActor *thing;
while ((thing = it.Next()))
@ -3894,9 +3910,13 @@ void P_FindAboveIntersectors (AActor *actor)
return;
AActor *thing;
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
if (!thing->intersects(actor))
{
continue;
}
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;
@ -3932,9 +3952,13 @@ void P_FindBelowIntersectors (AActor *actor)
return;
AActor *thing;
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
if (!thing->intersects(actor))
{
continue;
}
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;

View file

@ -865,39 +865,6 @@ AActor *FBlockThingsIterator::Next()
}
//===========================================================================
//
// FRadiusThingsIterator :: Next
//
//===========================================================================
FRadiusThingsIterator::FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius)
: FBlockThingsIterator(FBoundingBox(x, y, radius))
{
X = x;
Y = y;
Radius = radius;
}
//===========================================================================
//
// FRadiusThingsIterator :: Next
//
//===========================================================================
AActor *FRadiusThingsIterator::Next()
{
AActor *actor;
while ((actor = FBlockThingsIterator::Next()))
{
fixed_t blockdist = actor->radius + Radius;
if ( abs(actor->x - X) < blockdist && abs(actor->y - Y) < blockdist)
return actor;
}
return NULL;
}
//===========================================================================
//
// FPathTraverse :: Intercepts

View file

@ -1056,6 +1056,10 @@ void APlayerPawn::ActivateMorphWeapon ()
if (player->ReadyWeapon == NULL)
{
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon));
if (player->ReadyWeapon != NULL)
{
player->ReadyWeapon->GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in P_UndoPlayerMorph
}
}
if (player->ReadyWeapon != NULL)
{

View file

@ -94,7 +94,7 @@ public:
void Unload ();
virtual void SetFrontSkyLayer ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
int GetSourceLump() { return DefinitionLump; }
protected:
@ -107,10 +107,11 @@ protected:
SWORD OriginX, OriginY;
BYTE Rotate;
bool textureOwned;
FRemapTable *Translation;
PalEntry Blend;
FTexture *Texture;
TexPart();
~TexPart();
};
int NumParts;
@ -261,7 +262,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@ -329,7 +330,7 @@ protected:
void DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
void DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
friend class FTexture;
@ -345,7 +346,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@ -397,7 +398,7 @@ public:
void Unload ();
FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@ -454,7 +455,7 @@ public:
void Unload ();
FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@ -492,7 +493,7 @@ public:
bool CheckModified ();
// [OpenGL]
int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette() { return false; }
int GetSourceLump() { return SourcePic->GetSourceLump(); }
@ -512,7 +513,7 @@ public:
FWarp2Texture (FTexture *source);
// [OpenGL]
int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y, int rotate);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette() { return false; }
protected:

View file

@ -87,6 +87,8 @@ struct line_t;
class player_s;
class FScanner;
class FBitmap;
struct FCopyInfo;
//
// The SECTORS record, at runtime.
@ -824,8 +826,8 @@ public:
// Returns the whole texture, stored in column-major order
virtual const BYTE *GetPixels () = 0;
virtual int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate=0);
int CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap);
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL);
int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap);
virtual bool UseBasePalette();
virtual int GetSourceLump() { return -1; }

View file

@ -46,6 +46,26 @@
TAutoGrowArray<FRemapTablePtr, FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
const BYTE IcePalette[16][3] =
{
{ 10, 8, 18 },
{ 15, 15, 26 },
{ 20, 16, 36 },
{ 30, 26, 46 },
{ 40, 36, 57 },
{ 50, 46, 67 },
{ 59, 57, 78 },
{ 69, 67, 88 },
{ 79, 77, 99 },
{ 89, 87,109 },
{ 99, 97,120 },
{ 109,107,130 },
{ 118,118,141 },
{ 128,128,151 },
{ 138,138,162 },
{ 148,148,172 }
};
/****************************************************/
/****************************************************/
@ -428,25 +448,6 @@ void R_InitTranslationTables ()
// Doom palette has no good substitutes for these bluish-tinted grays, so
// they will just look gray unless you use a different PLAYPAL with Doom.
static const BYTE IcePalette[16][3] =
{
{ 10, 8, 18 },
{ 15, 15, 26 },
{ 20, 16, 36 },
{ 30, 26, 46 },
{ 40, 36, 57 },
{ 50, 46, 67 },
{ 59, 57, 78 },
{ 69, 67, 88 },
{ 79, 77, 99 },
{ 89, 87,109 },
{ 99, 97,120 },
{ 109,107,130 },
{ 118,118,141 },
{ 128,128,151 },
{ 138,138,162 },
{ 148,148,172 }
};
BYTE IcePaletteRemap[16];
for (i = 0; i < 16; ++i)
{

View file

@ -97,6 +97,8 @@ void R_DeinitTranslationTables();
// [RH] Actually create a player's translation table.
void R_BuildPlayerTranslation (int player);
extern const BYTE IcePalette[16][3];
#endif // __R_TRANSLATE_H

View file

@ -18,6 +18,7 @@ struct FMOD_CHANNELGROUP {};
struct FMOD_SOUNDGROUP {};
struct FMOD_REVERB {};
struct FMOD_DSP {};
struct FMOD_DSPCONNECTION {};
struct FMOD_POLYGON {};
struct FMOD_GEOMETRY {};
struct FMOD_SYNCPOINT {};
@ -39,6 +40,7 @@ namespace FMOD
class SoundGroup;
class Reverb;
class DSP;
class DSPConnection;
class Geometry;
/*
@ -159,7 +161,7 @@ namespace FMOD
// System level DSP access.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_System_GetDSPHead(this, (FMOD_DSP **)dsp); }
FMOD_RESULT addDSP (DSP *dsp) { return FMOD_System_AddDSP(this, (FMOD_DSP *)dsp); }
FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_System_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION**)dsp); }
FMOD_RESULT lockDSP () { return FMOD_System_LockDSP(this); }
FMOD_RESULT unlockDSP () { return FMOD_System_UnlockDSP(this); }
@ -277,8 +279,8 @@ namespace FMOD
FMOD_RESULT getFrequency (float *frequency) { return FMOD_Channel_GetFrequency(this, frequency); }
FMOD_RESULT setPan (float pan) { return FMOD_Channel_SetPan(this, pan); }
FMOD_RESULT getPan (float *pan) { return FMOD_Channel_GetPan(this, pan); }
FMOD_RESULT setDelay (unsigned int startdelay, unsigned int enddelay) { return FMOD_Channel_SetDelay(this, startdelay, enddelay); }
FMOD_RESULT getDelay (unsigned int *startdelay, unsigned int *enddelay) { return FMOD_Channel_GetDelay(this, startdelay, enddelay); }
FMOD_RESULT setDelay (FMOD_DELAYTYPE delaytype, unsigned int delayhi, unsigned int delaylo) { return FMOD_Channel_SetDelay(this, delaytype, delaylo, delayhi); }
FMOD_RESULT getDelay (FMOD_DELAYTYPE delaytype, unsigned int *delayhi, unsigned int *delaylo) { return FMOD_Channel_GetDelay(this, delaytype, delaylo, delayhi); }
FMOD_RESULT setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright) { return FMOD_Channel_SetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); }
FMOD_RESULT getSpeakerMix (float *frontleft, float *frontright, float *center, float *lfe, float *backleft, float *backright, float *sideleft, float *sideright) { return FMOD_Channel_GetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); }
FMOD_RESULT setSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_Channel_SetSpeakerLevels(this, speaker, levels, numlevels); }
@ -320,7 +322,7 @@ namespace FMOD
// DSP functionality only for channels playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_Channel_GetDSPHead(this, (FMOD_DSP **)dsp); }
FMOD_RESULT addDSP (DSP *dsp) { return FMOD_Channel_AddDSP(this, (FMOD_DSP *)dsp); }
FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_Channel_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); }
// Information only functions.
FMOD_RESULT isPlaying (bool *isplaying) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_IsPlaying(this, &b); *isplaying = b; return res; }
@ -387,7 +389,7 @@ namespace FMOD
// DSP functionality only for channel groups playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_ChannelGroup_GetDSPHead(this, (FMOD_DSP **)dsp); }
FMOD_RESULT addDSP (DSP *dsp) { return FMOD_ChannelGroup_AddDSP(this, (FMOD_DSP *)dsp); }
FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_ChannelGroup_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); }
// Information only functions.
FMOD_RESULT getName (char *name, int namelen) { return FMOD_ChannelGroup_GetName(this, name, namelen); }
@ -452,22 +454,14 @@ namespace FMOD
FMOD_RESULT getSystemObject (System **system) { return FMOD_DSP_GetSystemObject(this, (FMOD_SYSTEM **)system); }
// Connection / disconnection / input and output enumeration.
FMOD_RESULT addInput (DSP *target) { return FMOD_DSP_AddInput(this, target); }
FMOD_RESULT addInput (DSP *target, DSPConnection **connection) { return FMOD_DSP_AddInput(this, target, (FMOD_DSPCONNECTION **)connection); }
FMOD_RESULT disconnectFrom (DSP *target) { return FMOD_DSP_DisconnectFrom(this, target); }
FMOD_RESULT disconnectAll (bool inputs, bool outputs) { return FMOD_DSP_DisconnectAll(this, inputs, outputs); }
FMOD_RESULT remove () { return FMOD_DSP_Remove(this); }
FMOD_RESULT getNumInputs (int *numinputs) { return FMOD_DSP_GetNumInputs(this, numinputs); }
FMOD_RESULT getNumOutputs (int *numoutputs) { return FMOD_DSP_GetNumOutputs(this, numoutputs); }
FMOD_RESULT getInput (int index, DSP **input) { return FMOD_DSP_GetInput(this, index, (FMOD_DSP **)input); }
FMOD_RESULT getOutput (int index, DSP **output) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output); }
FMOD_RESULT setInputMix (int index, float volume) { return FMOD_DSP_SetInputMix(this, index, volume); }
FMOD_RESULT getInputMix (int index, float *volume) { return FMOD_DSP_GetInputMix(this, index, volume); }
FMOD_RESULT setInputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_SetInputLevels(this, index, speaker, levels, numlevels); }
FMOD_RESULT getInputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_GetInputLevels(this, index, speaker, levels, numlevels); }
FMOD_RESULT setOutputMix (int index, float volume) { return FMOD_DSP_SetOutputMix(this, index, volume); }
FMOD_RESULT getOutputMix (int index, float *volume) { return FMOD_DSP_GetOutputMix(this, index, volume); }
FMOD_RESULT setOutputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_SetOutputLevels(this, index, speaker, levels, numlevels); }
FMOD_RESULT getOutputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_GetOutputLevels(this, index, speaker, levels, numlevels); }
FMOD_RESULT getInput (int index, DSP **input, DSPConnection **inputconnection) { return FMOD_DSP_GetInput(this, index, (FMOD_DSP **)input, (FMOD_DSPCONNECTION **)inputconnection); }
FMOD_RESULT getOutput (int index, DSP **output, DSPConnection **outputconnection) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output, (FMOD_DSPCONNECTION **)outputconnection); }
// DSP unit control.
FMOD_RESULT setActive (bool active) { return FMOD_DSP_SetActive(this, active); }
@ -488,13 +482,38 @@ namespace FMOD
FMOD_RESULT getType (FMOD_DSP_TYPE *type) { return FMOD_DSP_GetType(this, type); }
FMOD_RESULT setDefaults (float frequency, float volume, float pan, int priority) { return FMOD_DSP_SetDefaults(this, frequency, volume, pan, priority); }
FMOD_RESULT getDefaults (float *frequency, float *volume, float *pan, int *priority) { return FMOD_DSP_GetDefaults(this, frequency, volume, pan, priority) ;}
// Userdata set/get.
FMOD_RESULT setUserData (void *userdata) { return FMOD_DSP_SetUserData(this, userdata); }
FMOD_RESULT getUserData (void **userdata) { return FMOD_DSP_GetUserData(this, userdata); }
};
/*
'DSPConnection' API
*/
class DSPConnection : FMOD_DSPCONNECTION
{
private:
DSPConnection(); /* Constructor made private so user cannot statically instance a DSPConnection class.
Appropriate DSPConnection creation or retrieval function must be used. */
public:
FMOD_RESULT F_API getInput (DSP **input) { return FMOD_DSPConnection_GetInput(this, (FMOD_DSP **)input); }
FMOD_RESULT F_API getOutput (DSP **output) { return FMOD_DSPConnection_GetOutput(this, (FMOD_DSP **)output); }
FMOD_RESULT F_API setMix (float volume) { return FMOD_DSPConnection_SetMix(this, volume); }
FMOD_RESULT F_API getMix (float *volume) { return FMOD_DSPConnection_GetMix(this, volume); }
FMOD_RESULT F_API setLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_SetLevels(this, speaker, levels, numlevels); }
FMOD_RESULT F_API getLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_GetLevels(this, speaker, levels, numlevels); }
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata) { return FMOD_DSPConnection_SetUserData(this, userdata); }
FMOD_RESULT F_API getUserData (void **userdata) { return FMOD_DSPConnection_GetUserData(this, userdata); }
};
/*
'Geometry' API
*/

View file

@ -70,8 +70,6 @@ extern HWND Window;
#define MAX_CHANNELS 256
#define ERRCHECK(x)
#define SPECTRUM_SIZE 256
@ -262,7 +260,7 @@ static const char *Enum_NameForNum(const FEnumList *list, int num)
//==========================================================================
//
// The container for a FSOUND_STREAM.
// The container for a streaming FMOD::Sound, for playing music.
//
//==========================================================================
@ -270,15 +268,15 @@ class FMODStreamCapsule : public SoundStream
{
public:
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner)
: Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL),
UserData(NULL), Callback(NULL)
: Owner(owner), Stream(NULL), Channel(NULL),
UserData(NULL), Callback(NULL), Ended(false)
{
SetStream(stream);
}
FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner)
: Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL),
UserData(udata), Callback(callback)
: Owner(owner), Stream(NULL), Channel(NULL),
UserData(udata), Callback(callback), Ended(false)
{}
~FMODStreamCapsule()
@ -333,11 +331,6 @@ public:
Channel->stop();
Channel = NULL;
}
if (DSP != NULL)
{
DSP->release();
DSP = NULL;
}
}
bool SetPaused(bool paused)
@ -411,20 +404,16 @@ public:
FMODStreamCapsule *self;
result = ((FMOD::Sound *)sound)->getUserData((void **)&self);
if (result != FMOD_OK || self == NULL || self->Callback == NULL)
{
return FMOD_ERR_INVALID_PARAM;
}
if (self->Callback(self, data, datalen, self->UserData))
if (result != FMOD_OK || self == NULL || self->Callback == NULL || self->Ended)
{
// Contrary to the docs, this return value is completely ignored.
return FMOD_OK;
}
else
if (!self->Callback(self, data, datalen, self->UserData))
{
self->Channel->stop();
// Contrary to the docs, this return value is completely ignored.
return FMOD_ERR_INVALID_PARAM;
self->Ended = true;
}
return FMOD_OK;
}
static FMOD_RESULT F_CALLBACK PCMSetPosCallback(FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype)
@ -438,9 +427,9 @@ private:
FMODSoundRenderer *Owner;
FMOD::Sound *Stream;
FMOD::Channel *Channel;
FMOD::DSP *DSP;
void *UserData;
SoundStreamCallback Callback;
bool Ended;
};
//==========================================================================
@ -490,18 +479,22 @@ bool FMODSoundRenderer::Init()
PrevEnvironment = DefaultEnvironments[0];
Printf("I_InitSound: Initializing FMOD\n");
if (!ShowedBanner)
{
Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2007.\n");
ShowedBanner = true;
}
// Create a System object and initialize.
result = FMOD::System_Create(&Sys);
ERRCHECK(result);
if (result != FMOD_OK)
{
Sys = NULL;
Printf(TEXTCOLOR_ORANGE"Failed to create FMOD system object: Error %d\n", result);
return false;
}
result = Sys->getVersion(&version);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_ORANGE"Could not validate FMOD version: Error %d\n", result);
return false;
}
if (version < FMOD_VERSION)
{
@ -512,6 +505,11 @@ bool FMODSoundRenderer::Init()
return false;
}
if (!ShowedBanner)
{
Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2008.\n");
ShowedBanner = true;
}
#ifdef _WIN32
if (OSPlatform == os_WinNT4)
{
@ -554,7 +552,11 @@ bool FMODSoundRenderer::Init()
if (eval >= 0)
{
result = Sys->setOutput(FMOD_OUTPUTTYPE(eval));
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Setting output type '%s' failed. Using default instead. (Error %d)\n", *snd_output, result);
Sys->setOutput(FMOD_OUTPUTTYPE_AUTODETECT);
}
}
result = Sys->getNumDrivers(&driver);
@ -562,7 +564,7 @@ bool FMODSoundRenderer::Init()
{
if (snd_driver >= driver)
{
Printf (TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver);
Printf(TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver);
driver = 0;
}
else
@ -573,7 +575,16 @@ bool FMODSoundRenderer::Init()
}
result = Sys->getDriver(&driver);
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result);
// Fill in some default to pretend it worked. (But as long as we specify a valid driver,
// can this call actually fail?)
Driver_Caps = 0;
Driver_MinFrequency = 4000;
Driver_MaxFrequency = 48000;
speakermode = FMOD_SPEAKERMODE_STEREO;
}
// Set the user selected speaker mode.
eval = Enum_NumForName(SpeakerModeNames, snd_speakermode);
@ -581,8 +592,11 @@ bool FMODSoundRenderer::Init()
{
speakermode = FMOD_SPEAKERMODE(eval);
}
result = Sys->setSpeakerMode(speakermode < 9000 ? speakermode : FMOD_SPEAKERMODE_STEREO);
ERRCHECK(result);
result = Sys->setSpeakerMode(speakermode);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Could not set speaker mode to '%s'. (Error %d)\n", *snd_speakermode, result);
}
// Set software format
eval = Enum_NumForName(SoundFormatNames, snd_output_format);
@ -599,13 +613,20 @@ bool FMODSoundRenderer::Init()
}
if (samplerate != snd_samplerate && snd_samplerate != 0)
{
Printf(TEXTCOLOR_BLUE"Sample rate %d is unsupported. Trying %d\n", *snd_samplerate, samplerate);
Printf(TEXTCOLOR_BLUE"Sample rate %d is unsupported. Trying %d.\n", *snd_samplerate, samplerate);
}
result = Sys->setSoftwareFormat(samplerate, format, 0, 0, resampler);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Could not set mixing format. Defaults will be used. (Error %d)\n", result);
}
// Set software channels according to snd_channels
result = Sys->setSoftwareChannels(snd_channels + NUM_EXTRA_SOFTWARE_CHANNELS);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Failed to set the preferred number of channels. (Error %d)\n", result);
}
if (Driver_Caps & FMOD_CAPS_HARDWARE_EMULATED)
{ // The user has the 'Acceleration' slider set to off!
@ -613,7 +634,6 @@ bool FMODSoundRenderer::Init()
Printf (TEXTCOLOR_BLUE"Warning: The sound acceleration slider has been set to off.\n");
Printf (TEXTCOLOR_BLUE"Please turn it back on if you want decent sound.\n");
result = Sys->setDSPBufferSize(1024, 10); // At 48khz, the latency between issuing an fmod command and hearing it will now be about 213ms.
ERRCHECK(result);
}
else if (snd_buffersize != 0 || snd_buffercount != 0)
{
@ -621,6 +641,14 @@ bool FMODSoundRenderer::Init()
int buffercount = snd_buffercount ? snd_buffercount : 4;
result = Sys->setDSPBufferSize(buffersize, buffercount);
}
else
{
result = FMOD_OK;
}
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Setting DSP buffer size failed. (Error %d)\n", result);
}
// Try to init
initflags = FMOD_INIT_NORMAL;
@ -663,24 +691,43 @@ bool FMODSoundRenderer::Init()
}
if (result != FMOD_OK)
{ // Initializing FMOD failed. Cry cry.
Printf (" System::init returned error code %d\n", result);
Printf(TEXTCOLOR_ORANGE" System::init returned error code %d\n", result);
return false;
}
// Create channel groups
result = Sys->createChannelGroup("Music", &MusicGroup);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_ORANGE" Could not create music channel group. (Error %d)\n", result);
return false;
}
result = Sys->createChannelGroup("SFX", &SfxGroup);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_ORANGE" Could not create sfx channel group. (Error %d)\n", result);
return false;
}
result = Sys->createChannelGroup("Pausable SFX", &PausableSfx);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_ORANGE" Could not create pausable sfx channel group. (Error %d)\n", result);
return false;
}
result = SfxGroup->addGroup(PausableSfx);
ERRCHECK(result);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE" Could not create attach pausable sfx to sfx channel group. (Error %d)\n", result);
}
result = SPC_CreateCodec(Sys);
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE" Could not register SPC codec. (Error %d)\n", result);
}
Sys->set3DSettings(0.5f, 96.f, 1.f);
Sys->set3DRolloffCallback(RolloffCallback);
@ -729,6 +776,7 @@ void FMODSoundRenderer::Shutdown()
}
Sys->close();
Sys->release();
Sys = NULL;
}
}

View file

@ -655,11 +655,11 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
{
InitialPlayback = false;
// Send the full master volume SysEx message.
events[0] = 0; // dwDeltaTime
events[1] = 0; // dwStreamID
events[2] = (MEVT_LONGMSG << 24) | 8; // dwEvent
events[3] = 0x047f7ff0; // dwParms[0]
events[4] = 0xf77f7f01; // dwParms[1]
events[0] = 0; // dwDeltaTime
events[1] = 0; // dwStreamID
events[2] = (MEVT_LONGMSG << 24) | 8; // dwEvent
events[3] = MAKE_ID(0xf0,0x7f,0x7f,0x04); // dwParms[0]
events[4] = MAKE_ID(0x01,0x7f,0x7f,0xf7); // dwParms[1]
events += 5;
DoInitialSetup();
}

View file

@ -484,7 +484,7 @@ bool TimidityMIDIDevice::ServiceStream (void *buff, int numbytes)
memset(buff, 0, numbytes);
CritSec.Enter();
while (numsamples > 0)
while (Events != NULL && numsamples > 0)
{
double ticky = NextTickIn;
int tick_in = int(NextTickIn);

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "912"
#define ZD_SVN_REVISION_NUMBER 912
#define ZD_SVN_REVISION_STRING "921"
#define ZD_SVN_REVISION_NUMBER 921

View file

@ -53,6 +53,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
#include "bitmap.h"
// Since we want this to compile under Linux too, we need to define this
// stuff ourselves instead of including a DirectX header.
@ -742,7 +743,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
//
//===========================================================================
int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
FWadLump lump = Wads.OpenLumpNum (SourceLump);
@ -768,7 +769,7 @@ int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
}
// All formats decompress to RGBA.
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA);
bmp->CopyPixelDataRGB(x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
delete [] TexBuffer;
return -1;
}

View file

@ -39,6 +39,7 @@
#include "r_jpeg.h"
#include "w_wad.h"
#include "v_text.h"
#include "bitmap.h"
void FLumpSourceMgr::InitSource (j_decompress_ptr cinfo)
{
@ -332,7 +333,7 @@ void FJPEGTexture::MakeTexture ()
//
//===========================================================================
int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
@ -375,19 +376,19 @@ int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_heigh
switch (cinfo.out_color_space)
{
case JCS_RGB:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB);
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf);
break;
case JCS_GRAYSCALE:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
1, cinfo.output_width, rotate, pe);
bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height,
1, cinfo.output_width, rotate, pe, inf);
break;
case JCS_CMYK:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK);
bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf);
break;
default:

View file

@ -44,6 +44,8 @@
#include "sc_man.h"
#include "templates.h"
#include "vectors.h"
#include "r_translate.h"
#include "bitmap.h"
// On the Alpha, accessing the shorts directly if they aren't aligned on a
// 4-byte boundary causes unaligned access warnings. Why it does this at
@ -177,6 +179,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
Unload ();
if (Parts != NULL)
{
for(int i=0; i<NumParts;i++)
{
if (Parts[i].textureOwned && Parts[i].Texture != NULL) delete Parts[i].Texture;
if (Parts[i].Translation != NULL) delete Parts[i].Translation;
}
delete[] Parts;
Parts = NULL;
}
@ -274,6 +281,70 @@ const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spa
return Pixels + column*Height;
}
//==========================================================================
//
// FMultiPatchTexture :: GetColumn
//
//==========================================================================
BYTE * GetBlendMap(PalEntry blend, BYTE *blendwork)
{
switch (blend.a==0 ? blend.r : -1)
{
case BLEND_INVERSEMAP:
return InverseColormap;
case BLEND_GOLDMAP:
return GoldColormap;
case BLEND_REDMAP:
return RedColormap;
case BLEND_GREENMAP:
return GreenColormap;
case BLEND_ICEMAP:
return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap;
default:
if (blend.r >= BLEND_DESATURATE1 && blend.r <= BLEND_DESATURATE31)
{
return DesaturateColormap[blend - BLEND_DESATURATE1];
}
else
{
blendwork[0]=0;
if (blend.a == 255)
{
for(int i=1;i<256;i++)
{
int rr = (blend.r * GPalette.BaseColors[i].r) / 255;
int gg = (blend.g * GPalette.BaseColors[i].g) / 255;
int bb = (blend.b * GPalette.BaseColors[i].b) / 255;
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
}
return blendwork;
}
else if (blend.a != 0)
{
for(int i=1;i<256;i++)
{
int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255;
int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255;
int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255;
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
}
return blendwork;
}
}
}
return NULL;
}
//==========================================================================
//
// FMultiPatchTexture :: MakeTexture
@ -285,14 +356,20 @@ void FMultiPatchTexture::MakeTexture ()
// Add a little extra space at the end if the texture's height is not
// a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height;
BYTE blendwork[256];
Pixels = new BYTE[numpix];
memset (Pixels, 0, numpix);
for (int i = 0; i < NumParts; ++i)
{
BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL;
if (Parts[i].Blend != BLEND_NONE)
{
trans = GetBlendMap(Parts[i].Blend, blendwork);
}
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate);
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
}
}
@ -304,14 +381,69 @@ void FMultiPatchTexture::MakeTexture ()
//
//===========================================================================
int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
int retv = -1;
FCopyInfo info;
for(int i=0;i<NumParts;i++)
{
int ret = Parts[i].Texture->CopyTrueColorPixels(buffer, buf_pitch, buf_height,
x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
int ret;
if (!Parts[i].Texture->bComplex || inf == NULL)
{
memset (&info, 0, sizeof (info));
if (Parts[i].Translation != NULL)
{
// Using a translation forces downconversion to the base palette
ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation);
}
else
{
PalEntry b = Parts[i].Blend;
if (b.a == 0 && b.r != BLEND_NONE)
{
info.blend = EBlend(b.r);
inf = &info;
}
else if (b.a != 0)
{
if (b.a == 255)
{
info.blendcolor[0] = b.r * FRACUNIT / 255;
info.blendcolor[1] = b.g * FRACUNIT / 255;
info.blendcolor[2] = b.b * FRACUNIT / 255;
info.blend = BLEND_MODULATE;
inf = &info;
}
else
{
info.blendcolor[3] = b.a * FRACUNIT / 255;
info.blendcolor[0] = b.r * (FRACUNIT-info.blendcolor[3]);
info.blendcolor[1] = b.g * (FRACUNIT-info.blendcolor[3]);
info.blendcolor[2] = b.b * (FRACUNIT-info.blendcolor[3]);
info.blend = BLEND_OVERLAY;
inf = &info;
}
}
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, inf);
}
}
else
{
// If the patch is a texture with some kind of processing involved
// and being drawn with additional processing
// the copying must be done in 2 steps: First create a complete image of the patch
// including all processing and then copy from that intermediate image to the destination
FBitmap bmp1;
if (bmp1.Create(Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight()))
{
Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0);
bmp->CopyPixelDataRGB(x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(),
bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf);
}
}
if (ret > retv) retv = ret;
}
@ -328,6 +460,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf
FTextureFormat FMultiPatchTexture::GetFormat()
{
if (bComplex) return TEX_RGB;
if (NumParts == 1) return Parts[0].Texture->GetFormat();
return UseBasePalette() ? TEX_Pal : TEX_RGB;
}
@ -344,6 +477,7 @@ FTextureFormat FMultiPatchTexture::GetFormat()
bool FMultiPatchTexture::UseBasePalette()
{
if (bComplex) return false;
for(int i=0;i<NumParts;i++)
{
if (!Parts[i].Texture->UseBasePalette()) return false;
@ -490,18 +624,8 @@ FMultiPatchTexture::TexPart::TexPart()
Rotate = 0;
textureOwned = false;
Texture = NULL;
}
//==========================================================================
//
// FMultiPatchTexture :: TexPart :: TexPart
//
//==========================================================================
FMultiPatchTexture::TexPart::~TexPart()
{
if (textureOwned && Texture != NULL) delete Texture;
Texture = NULL;
Translation = NULL;
Blend = 0;
}
//==========================================================================
@ -674,6 +798,17 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
}
static bool Check(char *& range, char c)
{
while (isspace(*range)) range++;
if (*range==c)
{
range++;
return true;
}
return false;
}
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
{
FString patchname;
@ -690,10 +825,20 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
part.textureOwned = true;
}
else if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./"))
{
int lumpnum = Wads.CheckNumForName(sc.String, ns_patches);
if (lumpnum >= 0)
{
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
TexMan.AddTexture(part.Texture);
}
}
}
else
{
part.Texture = TexMan[texno];
bComplex |= part.Texture->bComplex;
}
if (part.Texture == NULL)
{
@ -728,6 +873,113 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
}
part.Rotate = (sc.Number / 90) & 3;
}
else if (sc.Compare("Translation"))
{
bComplex = true;
if (part.Translation != NULL) delete part.Translation;
part.Translation = NULL;
part.Blend = 0;
static const char *maps[] = { "inverse", "gold", "red", "green", "ice", "desaturate", NULL };
sc.MustGetString();
int match = sc.MatchString(maps);
if (match >= 0)
{
part.Blend.r = 1 + match;
if (part.Blend.r == BLEND_DESATURATE1)
{
sc.MustGetStringName(",");
sc.MustGetNumber();
part.Blend.r += clamp(sc.Number-1, 0, 30);
}
}
else
{
sc.UnGet();
part.Translation = new FRemapTable;
part.Translation->MakeIdentity();
do
{
sc.MustGetString();
char *range = sc.String;
int start,end;
start=strtol(range, &range, 10);
if (!Check(range, ':')) return;
end=strtol(range, &range, 10);
if (!Check(range, '=')) return;
if (!Check(range, '['))
{
int pal1,pal2;
pal1=strtol(range, &range, 10);
if (!Check(range, ':')) return;
pal2=strtol(range, &range, 10);
part.Translation->AddIndexRange(start, end, pal1, pal2);
}
else
{
// translation using RGB values
int r1,g1,b1,r2,g2,b2;
r1=strtol(range, &range, 10);
if (!Check(range, ',')) return;
g1=strtol(range, &range, 10);
if (!Check(range, ',')) return;
b1=strtol(range, &range, 10);
if (!Check(range, ']')) return;
if (!Check(range, ':')) return;
if (!Check(range, '[')) return;
r2=strtol(range, &range, 10);
if (!Check(range, ',')) return;
g2=strtol(range, &range, 10);
if (!Check(range, ',')) return;
b2=strtol(range, &range, 10);
if (!Check(range, ']')) return;
part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
}
}
while (sc.CheckString(","));
}
}
else if (sc.Compare("Blend"))
{
bComplex = true;
if (part.Translation != NULL) delete part.Translation;
part.Translation = NULL;
part.Blend = 0;
if (!sc.CheckNumber())
{
sc.MustGetString();
part.Blend = V_GetColor(NULL, sc.String);
}
else
{
int r,g,b;
sc.MustGetNumber();
sc.MustGetStringName(",");
r = sc.Number;
sc.MustGetNumber();
sc.MustGetStringName(",");
g = sc.Number;
sc.MustGetNumber();
sc.MustGetStringName(",");
b = sc.Number;
part.Blend = MAKERGB(r, g, b);
}
if (sc.CheckString(","))
{
sc.MustGetFloat();
part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
}
else part.Blend.a = 255;
bComplex = true;
}
}
}
if (Mirror & 2)
@ -790,7 +1042,9 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
{
TexPart part;
ParsePatch(sc, part);
parts.Push(part);
if (part.Texture != NULL) parts.Push(part);
part.Texture = NULL;
part.Translation = NULL;
}
}

View file

@ -39,6 +39,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
#include "bitmap.h"
bool FPCXTexture::Check(FileReader & file)
@ -418,7 +419,7 @@ void FPCXTexture::MakeTexture()
//
//===========================================================================
int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
PCXHeader header;
@ -472,14 +473,13 @@ int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
lump.Seek(sizeof(header), SEEK_SET);
ReadPCX8bits (Pixels, lump, &header);
}
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf);
}
else
{
Pixels = new BYTE[Width*Height * 3];
BYTE * row = buffer;
ReadPCX24bits (Pixels, lump, &header, 3);
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB);
bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB, inf);
}
delete [] Pixels;
return 0;

View file

@ -39,6 +39,7 @@
#include "w_wad.h"
#include "templates.h"
#include "m_png.h"
#include "bitmap.h"
bool FPNGTexture::Check(FileReader & file)
@ -490,7 +491,7 @@ void FPNGTexture::MakeTexture ()
//
//===========================================================================
int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
// Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
PalEntry pe[256];
@ -554,20 +555,20 @@ int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 0:
case 3:
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf);
break;
case 2:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB);
bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB, inf);
break;
case 4:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA);
bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA, inf);
transpal = -1;
break;
case 6:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA);
bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA, inf);
transpal = -1;
break;

View file

@ -40,6 +40,7 @@
#include "templates.h"
#include "i_system.h"
#include "r_translate.h"
#include "bitmap.h"
typedef bool (*CheckFunc)(FileReader & file);
typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum);
@ -120,7 +121,7 @@ FTexture::FTexture ()
: LeftOffset(0), TopOffset(0),
WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT),
UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false),
bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bIsPatch(false),
bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bIsPatch(false), bComplex(false),
Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL)
{
*Name = 0;
@ -456,8 +457,11 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt)
break;
case TEX_RGB:
CopyTrueColorPixels(buff, pitch, height, 0, 0);
{
FBitmap bmp(buff, pitch, pitch/4, height);
CopyTrueColorPixels(&bmp, 0, 0);
break;
}
default:
I_Error("FTexture::FillBuffer: Unsupported format %d", fmt);
@ -476,25 +480,21 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt)
//
//===========================================================================
int FTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry *palette = screen->GetPalette();
palette[0].a=255; // temporarily modify the first color's alpha
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
GetPixels(), Width, Height, Height, 1,
rotate, palette);
bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf);
palette[0].a=0;
return 0;
}
int FTexture::CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap)
int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap)
{
PalEntry *palette = remap->Palette;
palette[0].a=255; // temporarily modify the first color's alpha
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
GetPixels(), Width, Height, Height, 1,
0, palette);
bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette);
palette[0].a=0;
return 0;

View file

@ -38,6 +38,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
#include "bitmap.h"
bool FTGATexture::Check(FileReader & data)
@ -384,7 +385,7 @@ void FTGATexture::MakeTexture ()
//
//===========================================================================
int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
FWadLump lump = Wads.OpenLumpNum (SourceLump);
@ -469,7 +470,7 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
switch (hdr.img_type & 7)
{
case 1: // paletted
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf);
break;
case 2: // RGB
@ -477,21 +478,21 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 15:
case 16:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555);
bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555, inf);
break;
case 24:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf);
break;
case 32:
if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel
{
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf);
}
else
{
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA);
bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA, inf);
transval = -1;
}
break;
@ -506,11 +507,11 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 8:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf);
break;
case 16:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16);
bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16, inf);
break;
default:

View file

@ -313,7 +313,7 @@ void A_PlaySoundEx (AActor *self)
int soundid = StateParameters[index];
ENamedName channel = ENamedName(StateParameters[index + 1]);
INTBOOL looping = StateParameters[index + 2];
INTBOOL looping = EvalExpressionI(StateParameters[index + 2], self);
int attenuation_raw = EvalExpressionI(StateParameters[index + 3], self);
int attenuation;

View file

@ -754,11 +754,11 @@ static int ParseMorphStyle (FScanner &sc)
{
static const char * morphstyles[]={
"MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
"MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", NULL};
"MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON", NULL};
static const int morphstyle_values[]={
MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE};
MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON};
// May be given flags by number...
if (sc.CheckNumber())

File diff suppressed because it is too large Load diff

View file

@ -1121,29 +1121,29 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
DLS_Region *rgn = &ins->regions[index];
DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
if (!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE))
{
sample->exclusiveClass = (SBYTE)rgn->header->usKeyGroup;
}
sample->self_nonexclusive = !!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE);
sample->key_group = (SBYTE)rgn->header->usKeyGroup;
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
sample->low_vel = rgn->header->RangeVelocity.usLow;
sample->high_vel = rgn->header->RangeVelocity.usHigh;
sample->modes = wave->format->wBitsPerSample == 8 ? MODES_UNSIGNED : MODES_16BIT;
sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16;
sample->sample_rate = wave->format->dwSamplesPerSec;
sample->data = NULL;
sample->data_length = wave->length;
convert_sample_data(sample, wave->data);
if (rgn->wsmp->cSampleLoops) {
sample->modes |= (MODES_LOOPING|MODES_SUSTAIN);
if (rgn->wsmp->cSampleLoops)
{
sample->modes |= (PATCH_LOOPEN | PATCH_SUSTAIN);
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
}
sample->volume = 1.0f;
if (sample->modes & MODES_SUSTAIN) {
if (sample->modes & PATCH_SUSTAIN)
{
int value;
double attack, hold, decay, release; int sustain;
CONNECTIONLIST *art = NULL;
@ -1192,12 +1192,7 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
sample->envelope_offset[RELEASEC] = to_offset(0);
sample->envelope_rate[RELEASEC] = to_offset(1);
sample->modes |= MODES_ENVELOPE;
}
for (int j = ATTACK; j < DELAY; j++)
{
sample->modulation_rate[j] = float(sample->envelope_rate[j]);
sample->modulation_offset[j] = float(sample->envelope_offset[j]);
sample->modes |= PATCH_NO_SRELEASE;
}
sample->data_length <<= FRACTION_BITS;
@ -1205,55 +1200,54 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
sample->loop_end <<= FRACTION_BITS;
}
InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
{
InstrumentLayer *layer;
Instrument *inst;
DWORD i;
DLS_Instrument *dls_ins = NULL;
if (song->patches == NULL)
{
return NULL;
}
drum = drum ? 0x80000000 : 0;
for (i = 0; i < song->patches->cInstruments; ++i) {
for (i = 0; i < song->patches->cInstruments; ++i)
{
dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break;
}
if (i == song->patches->cInstruments && !bank) {
for (i = 0; i < song->patches->cInstruments; ++i) {
if (i == song->patches->cInstruments && bank == 0)
{
for (i = 0; i < song->patches->cInstruments; ++i)
{
dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break;
}
}
if (i == song->patches->cInstruments) {
if (i == song->patches->cInstruments)
{
// SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
return NULL;
}
layer = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
layer->lo = 0;
layer->hi = 127;
layer->instrument = (Instrument *)safe_malloc(sizeof(Instrument));
layer->instrument->type = INST_DLS;
layer->instrument->samples = dls_ins->header->cRegions;
layer->instrument->sample = (Sample *)safe_malloc(layer->instrument->samples * sizeof(Sample));
layer->instrument->left_samples = layer->instrument->samples;
layer->instrument->left_sample = layer->instrument->sample;
layer->instrument->right_samples = 0;
layer->instrument->right_sample = NULL;
memset(layer->instrument->sample, 0, layer->instrument->samples * sizeof(Sample));
inst = (Instrument *)safe_malloc(sizeof(Instrument));
inst->type = INST_DLS;
inst->samples = dls_ins->header->cRegions;
inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
memset(inst->sample, 0, inst->samples * sizeof(Sample));
/*
printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples);
*/
for (i = 0; i < dls_ins->header->cRegions; ++i) {
load_region_dls(song, &layer->instrument->sample[i], dls_ins, i);
for (i = 0; i < dls_ins->header->cRegions; ++i)
{
load_region_dls(song, &inst->sample[i], dls_ins, i);
}
return layer;
return inst;
}
#endif /* !TEST_MAIN_DLS */

View file

@ -37,15 +37,14 @@ int recompute_envelope(Voice *v)
stage = v->envelope_stage;
if (stage >= DELAY)
if (stage > RELEASEC)
{
/* Envelope ran out. */
int tmp = (v->status == VOICE_DIE); /* Already displayed as dead */
v->status = VOICE_FREE;
return 1;
}
if (v->sample->modes & MODES_ENVELOPE)
if (v->sample->modes & PATCH_NO_SRELEASE)
{
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
{
@ -60,7 +59,9 @@ int recompute_envelope(Voice *v)
v->envelope_stage = stage + 1;
if (v->envelope_volume == v->sample->envelope_offset[stage])
{
return recompute_envelope(v);
}
v->envelope_target = v->sample->envelope_offset[stage];
v->envelope_increment = v->sample->envelope_rate[stage];
if (v->envelope_target < v->envelope_volume)
@ -75,28 +76,30 @@ void apply_envelope_to_amp(Voice *v)
{
ramp = v->right_amp;
if (v->tremolo_phase_increment)
if (v->tremolo_phase_increment != 0)
{
lamp *= v->tremolo_volume;
ramp *= v->tremolo_volume;
}
if (v->sample->modes & MODES_ENVELOPE)
if (v->sample->modes & PATCH_NO_SRELEASE)
{
double vol = calc_vol(v->envelope_volume / float(1 << 30));
lamp *= vol;
ramp *= vol;
}
v->left_mix = float(lamp);
v->right_mix = float(ramp);
}
else
{
if (v->tremolo_phase_increment)
if (v->tremolo_phase_increment != 0)
{
lamp *= v->tremolo_volume;
if (v->sample->modes & MODES_ENVELOPE)
}
if (v->sample->modes & PATCH_NO_SRELEASE)
{
lamp *= calc_vol(v->envelope_volume / float(1 << 30));
}
v->left_mix = float(lamp);
}
}
@ -104,13 +107,14 @@ void apply_envelope_to_amp(Voice *v)
static int update_envelope(Voice *v)
{
v->envelope_volume += v->envelope_increment;
/* Why is there no ^^ operator?? */
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
{
v->envelope_volume = v->envelope_target;
if (recompute_envelope(v))
{
return 1;
}
}
return 0;
}
@ -119,7 +123,7 @@ static void update_tremolo(Voice *v)
{
int depth = v->sample->tremolo_depth << 7;
if (v->tremolo_sweep)
if (v->tremolo_sweep != 0)
{
/* Update sweep position */
@ -151,12 +155,14 @@ static void update_tremolo(Voice *v)
/* Returns 1 if the note died */
static int update_signal(Voice *v)
{
if (v->envelope_increment && update_envelope(v))
if (v->envelope_increment != 0 && update_envelope(v))
{
return 1;
if (v->tremolo_phase_increment)
}
if (v->tremolo_phase_increment != 0)
{
update_tremolo(v);
}
apply_envelope_to_amp(v);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -215,12 +215,12 @@ static sample_t *rs_bidir(sample_t *resample_buffer, Voice *vp, int count)
/* We only need to compute one half of the vibrato sine cycle */
static int vib_phase_to_inc_ptr(int phase)
{
if (phase < VIBRATO_SAMPLE_INCREMENTS/2)
return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
if (phase < VIBRATO_SAMPLE_INCREMENTS / 2)
return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase;
else if (phase >= VIBRATO_SAMPLE_INCREMENTS * 3 / 2)
return VIBRATO_SAMPLE_INCREMENTS * 5 / 2 - 1 - phase;
else
return phase-VIBRATO_SAMPLE_INCREMENTS/2;
return phase - VIBRATO_SAMPLE_INCREMENTS / 2;
}
static int update_vibrato(float output_rate, Voice *vp, int sign)
@ -229,8 +229,8 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
int phase;
double a, pb;
if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1)
vp->vibrato_phase=0;
if (vp->vibrato_phase++ >= 2 * VIBRATO_SAMPLE_INCREMENTS - 1)
vp->vibrato_phase = 0;
phase = vib_phase_to_inc_ptr(vp->vibrato_phase);
if (vp->vibrato_sample_increment[phase])
@ -244,7 +244,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
/* Need to compute this sample increment. */
depth = vp->sample->vibrato_depth << 7;
if (vp->vibrato_sweep)
if (vp->vibrato_sweep != 0)
{
/* Need to update sweep */
vp->vibrato_sweep_position += vp->vibrato_sweep;
@ -265,7 +265,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS)))
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING);
a *= pow(2.0, pb / (8191 * 12.f));
a *= pow(2.0, pb / (8192 * 12.f));
/* If the sweep's over, we can store the newly computed sample_increment */
if (!vp->vibrato_sweep)
@ -511,11 +511,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
if (vp->vibrato_control_ratio)
{
if ((modes & MODES_LOOPING) &&
((modes & MODES_ENVELOPE) ||
if ((modes & PATCH_LOOPEN) &&
((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
{
if (modes & MODES_PINGPONG)
if (modes & PATCH_BIDIR)
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
else
return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr);
@ -527,11 +527,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
}
else
{
if ((modes & MODES_LOOPING) &&
((modes & MODES_ENVELOPE) ||
if ((modes & PATCH_LOOPEN) &&
((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
{
if (modes & MODES_PINGPONG)
if (modes & PATCH_BIDIR)
return rs_bidir(song->resample_buffer, vp, *countptr);
else
return rs_loop(song->resample_buffer, vp, *countptr);
@ -554,11 +554,14 @@ void pre_resample(Renderer *song, Sample *sp)
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
};
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
sp->note_to_use,
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
if (sp->scale_factor != 0)
return;
a = (sp->sample_rate * note_to_freq(sp->note_to_use)) / (sp->root_freq * song->rate);
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)\n",
sp->scale_note,
note_name[sp->scale_note % 12], (sp->scale_note & 0x7F) / 12);
a = (sp->sample_rate * note_to_freq(sp->scale_note)) / (sp->root_freq * song->rate);
if (a <= 0)
return;
newlen = (int)(sp->data_length / a);

View file

@ -413,6 +413,13 @@ void FreeAll()
int LoadConfig(const char *filename)
{
/* !!! FIXME: This may be ugly, but slightly less so than requiring the
* default search path to have only one element. I think.
*
* We only need to include the likely locations for the config
* file itself since that file should contain any other directory
* that needs to be added to the search path.
*/
clear_pathlist();
#ifdef _WIN32
add_to_pathlist("C:\\TIMIDITY");
@ -443,25 +450,21 @@ Renderer::Renderer(float sample_rate)
{
rate = sample_rate;
patches = NULL;
default_instrument = NULL;
#ifdef FAST_DECAY
fast_decay = true;
#else
fast_decay = false;
#endif
resample_buffer_size = 0;
resample_buffer = NULL;
adjust_panning_immediately = false;
control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO);
lost_notes = 0;
cut_notes = 0;
default_instrument = NULL;
default_program = DEFAULT_PROGRAM;
if (def_instr_name.IsNotEmpty())
set_default_instrument(def_instr_name);
voices = DEFAULT_VOICES;
memset(voice, 0, sizeof(voice));
memset(drumvolume, 0, sizeof(drumvolume));
memset(drumpanpot, 0, sizeof(drumpanpot));
memset(drumreverberation, 0, sizeof(drumreverberation));
memset(drumchorusdepth, 0, sizeof(drumchorusdepth));
drumchannels = DEFAULT_DRUMCHANNELS;
}
@ -492,22 +495,7 @@ void Renderer::ComputeOutput(float *buffer, int count)
{
if (v->status != VOICE_FREE)
{
if (v->sample_offset == 0 && v->echo_delay_count)
{
if (v->echo_delay_count >= count)
{
v->echo_delay_count -= count;
}
else
{
mix_voice(this, buffer + v->echo_delay_count, v, count - v->echo_delay_count);
v->echo_delay_count = 0;
}
}
else
{
mix_voice(this, buffer, v, count);
}
mix_voice(this, buffer, v, count);
}
}
}
@ -520,6 +508,11 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{
return;
}
if (banknum != 0)
{
/* Mark the standard bank in case it's not defined by this one. */
MarkInstrument(0, percussion, instr);
}
if (percussion)
{
bank = drumset[banknum];
@ -532,9 +525,9 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{
return;
}
if (bank->tone[instr].layer == NULL)
if (bank->instrument[instr] == NULL)
{
bank->tone[instr].layer = MAGIC_LOAD_INSTRUMENT;
bank->instrument[instr] = MAGIC_LOAD_INSTRUMENT;
}
}
@ -557,9 +550,6 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...)
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
size_t l = strlen(buf);
buf[l] = '\n';
buf[l+1] = '\0';
OutputDebugString(buf);
#endif
}

View file

@ -33,33 +33,27 @@ config.h
*/
/* Acoustic Grand Piano seems to be the usual default instrument. */
#define DEFAULT_PROGRAM 0
#define DEFAULT_PROGRAM 0
/* 9 here is MIDI channel 10, which is the standard percussion channel.
Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too.
On the other hand, some files know that 16 is not a drum channel and
try to play music on it. This is now a runtime option, so this isn't
a critical choice anymore. */
#define DEFAULT_DRUMCHANNELS (1<<9)
/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
#define DEFAULT_DRUMCHANNELS (1<<9)
/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
/* Default sampling rate, default polyphony, and maximum polyphony.
All but the last can be overridden from the command line. */
#define DEFAULT_RATE 32000
#define DEFAULT_VOICES 32
#define MAX_VOICES 256
#define MAXCHAN 16
#define MAXNOTE 128
/* Default polyphony, and maximum polyphony. */
#define DEFAULT_VOICES 32
#define MAX_VOICES 256
#define MAXCHAN 16
#define MAXNOTE 128
/* 1000 here will give a control ratio of 22:1 with 22 kHz output.
Higher CONTROLS_PER_SECOND values allow more accurate rendering
of envelopes and tremolo. The cost is CPU time. */
#define CONTROLS_PER_SECOND 1000
/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay
faster) and sounds more like a GUS. There is now a command line
option to toggle this as well. */
//#define FAST_DECAY
#define CONTROLS_PER_SECOND 1000
/* How many bits to use for the fractional part of sample positions.
This affects tonal accuracy. The entire position counter must fit
@ -67,7 +61,7 @@ config.h
a sample is 1048576 samples (2 megabytes in memory). The GUS gets
by with just 9 bits and a little help from its friends...
"The GUS does not SUCK!!!" -- a happy user :) */
#define FRACTION_BITS 12
#define FRACTION_BITS 12
/* For some reason the sample volume is always set to maximum in all
patch files. Define this for a crude adjustment that may help
@ -76,7 +70,7 @@ config.h
/* The number of samples to use for ramping out a dying note. Affects
click removal. */
#define MAX_DIE_TIME 20
#define MAX_DIE_TIME 20
/**************************************************************************/
/* Anything below this shouldn't need to be changed unless you're porting
@ -84,37 +78,37 @@ config.h
/**************************************************************************/
/* change FRACTION_BITS above, not these */
#define INTEGER_BITS (32 - FRACTION_BITS)
#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
#define FRACTION_MASK (~ INTEGER_MASK)
#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS)
#define INTEGER_BITS (32 - FRACTION_BITS)
#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
#define FRACTION_MASK (~ INTEGER_MASK)
#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS)
/* This is enforced by some computations that must fit in an int */
#define MAX_CONTROL_RATIO 255
#define MAX_CONTROL_RATIO 255
#define MAX_AMPLIFICATION 800
#define MAX_AMPLIFICATION 800
/* The TiMiditiy configuration file */
#define CONFIG_FILE "timidity.cfg"
typedef float sample_t;
typedef float final_volume_t;
#define FINAL_VOLUME(v) (v)
#define FINAL_VOLUME(v) (v)
#define FSCALE(a,b) ((a) * (float)(1<<(b)))
#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b))))
#define FSCALE(a,b) ((a) * (float)(1<<(b)))
#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b))))
/* Vibrato and tremolo Choices of the Day */
#define SWEEP_TUNING 38
#define VIBRATO_AMPLITUDE_TUNING 1.0L
#define VIBRATO_RATE_TUNING 38
#define TREMOLO_AMPLITUDE_TUNING 1.0L
#define TREMOLO_RATE_TUNING 38
#define SWEEP_TUNING 38
#define VIBRATO_AMPLITUDE_TUNING 1.0
#define VIBRATO_RATE_TUNING 38
#define TREMOLO_AMPLITUDE_TUNING 1.0
#define TREMOLO_RATE_TUNING 38
#define SWEEP_SHIFT 16
#define RATE_SHIFT 5
#define SWEEP_SHIFT 16
#define RATE_SHIFT 5
#define VIBRATO_SAMPLE_INCREMENTS 32
#define VIBRATO_SAMPLE_INCREMENTS 32
#ifndef PI
#define PI 3.14159265358979323846
@ -188,21 +182,20 @@ FileReader *open_filereader(const char *name, int open, int *plumpnum);
controls.h
*/
#define CMSG_INFO 0
#define CMSG_WARNING 1
#define CMSG_ERROR 2
#define CMSG_FATAL 3
#define CMSG_TRACE 4
#define CMSG_TIME 5
#define CMSG_TOTAL 6
#define CMSG_FILE 7
#define CMSG_TEXT 8
enum
{
CMSG_INFO,
CMSG_WARNING,
CMSG_ERROR
};
#define VERB_NORMAL 0
#define VERB_VERBOSE 1
#define VERB_NOISY 2
#define VERB_DEBUG 3
#define VERB_DEBUG_SILLY 4
enum
{
VERB_NORMAL,
VERB_VERBOSE,
VERB_NOISY,
VERB_DEBUG
};
void cmsg(int type, int verbosity_level, const char *fmt, ...);
@ -217,114 +210,174 @@ struct Sample
loop_start, loop_end, data_length,
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
SDWORD
envelope_rate[7], envelope_offset[7];
envelope_rate[6], envelope_offset[6];
float
modulation_rate[7], modulation_offset[7];
float
volume, resonance,
modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc;
volume;
sample_t *data;
SDWORD
tremolo_sweep_increment, tremolo_phase_increment,
lfo_sweep_increment, lfo_phase_increment,
vibrato_sweep_increment, vibrato_control_ratio,
cutoff_freq;
vibrato_sweep_increment, vibrato_control_ratio;
BYTE
reverberation, chorusdepth,
tremolo_depth, vibrato_depth,
modes,
attenuation;
modes;
WORD
freq_center, panning;
SBYTE
note_to_use, exclusiveClass;
panning, scale_factor;
SWORD
keyToModEnvHold, keyToModEnvDecay,
keyToVolEnvHold, keyToVolEnvDecay;
SDWORD
freq_scale;
scale_note;
bool
self_nonexclusive;
BYTE
key_group;
};
void convert_sample_data(Sample *sample, const void *data);
void free_instruments();
/* Bits in modes: */
#define MODES_16BIT (1<<0)
#define MODES_UNSIGNED (1<<1)
#define MODES_LOOPING (1<<2)
#define MODES_PINGPONG (1<<3)
#define MODES_REVERSE (1<<4)
#define MODES_SUSTAIN (1<<5)
#define MODES_ENVELOPE (1<<6)
#define MODES_FAST_RELEASE (1<<7)
/* Patch definition: */
enum
{
HEADER_SIZE = 12,
ID_SIZE = 10,
DESC_SIZE = 60,
RESERVED_SIZE = 40,
PATCH_HEADER_RESERVED_SIZE = 36,
LAYER_RESERVED_SIZE = 40,
PATCH_DATA_RESERVED_SIZE = 36,
INST_NAME_SIZE = 16,
ENVELOPES = 6,
MAX_LAYERS = 4
};
#define GF1_HEADER_TEXT "GF1PATCH110"
#define INST_GUS 0
#define INST_SF2 1
#define INST_DLS 2
enum
{
PATCH_16 = (1<<0),
PATCH_UNSIGNED = (1<<1),
PATCH_LOOPEN = (1<<2),
PATCH_BIDIR = (1<<3),
PATCH_BACKWARD = (1<<4),
PATCH_SUSTAIN = (1<<5),
PATCH_NO_SRELEASE = (1<<6),
PATCH_FAST_REL = (1<<7)
};
#ifdef _MSC_VER
#pragma pack(push, 1)
#define GCC_PACKED
#else
#define GCC_PACKED __attribute__((__packed__))
#endif
struct GF1PatchHeader
{
char Header[HEADER_SIZE];
char GravisID[ID_SIZE]; /* Id = "ID#000002" */
char Description[DESC_SIZE];
BYTE Instruments;
BYTE Voices;
BYTE Channels;
WORD WaveForms;
WORD MasterVolume;
DWORD DataSize;
BYTE Reserved[PATCH_HEADER_RESERVED_SIZE];
} GCC_PACKED;
struct GF1InstrumentData
{
WORD Instrument;
char InstrumentName[INST_NAME_SIZE];
int InstrumentSize;
BYTE Layers;
BYTE Reserved[RESERVED_SIZE];
} GCC_PACKED;
struct GF1LayerData
{
BYTE LayerDuplicate;
BYTE Layer;
int LayerSize;
BYTE Samples;
BYTE Reserved[LAYER_RESERVED_SIZE];
} GCC_PACKED;
struct GF1PatchData
{
char WaveName[7];
BYTE Fractions;
int WaveSize;
int StartLoop;
int EndLoop;
WORD SampleRate;
int LowFrequency;
int HighFrequency;
int RootFrequency;
SWORD Tune;
BYTE Balance;
BYTE EnvelopeRate[6];
BYTE EnvelopeOffset[6];
BYTE TremoloSweep;
BYTE TremoloRate;
BYTE TremoloDepth;
BYTE VibratoSweep;
BYTE VibratoRate;
BYTE VibratoDepth;
BYTE Modes;
SWORD ScaleFrequency;
WORD ScaleFactor; /* From 0 to 2048 or 0 to 2 */
BYTE Reserved[PATCH_DATA_RESERVED_SIZE];
} GCC_PACKED;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
#undef GCC_PACKED
enum
{
INST_GUS,
INST_DLS
};
struct Instrument
{
Instrument();
~Instrument();
int type;
int samples;
Sample *sample;
int left_samples;
Sample *left_sample;
int right_samples;
Sample *right_sample;
};
struct InstrumentLayer
{
BYTE lo, hi;
Instrument *instrument;
InstrumentLayer *next;
};
struct cfg_type
{
int font_code;
int num;
const char *name;
};
#define FONT_NORMAL 0
#define FONT_FFF 1
#define FONT_SBK 2
#define FONT_TONESET 3
#define FONT_DRUMSET 4
#define FONT_PRESET 5
struct ToneBankElement
{
ToneBankElement() : layer(NULL), font_type(0), sf_ix(0), tuning(0),
ToneBankElement() :
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
{}
FString name;
InstrumentLayer *layer;
int font_type, sf_ix, tuning;
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
};
/* A hack to delay instrument loading until after reading the
entire MIDI file. */
#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1))
#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
#define MAXPROG 128
#define MAXBANK 130
#define SFXBANK (MAXBANK-1)
#define SFXDRUM1 (MAXBANK-2)
#define SFXDRUM2 (MAXBANK-1)
#define XGDRUM 1
enum
{
MAXPROG = 128,
MAXBANK = 128
};
struct ToneBank
{
FString name;
ToneBankElement tone[MAXPROG];
ToneBank();
~ToneBank();
ToneBankElement *tone;
Instrument *instrument[MAXPROG];
};
#define SPECIAL_PROGRAM -1
#define SPECIAL_PROGRAM -1
extern void pcmap(int *b, int *v, int *p, int *drums);
@ -341,60 +394,55 @@ playmidi.h
*/
/* Midi events */
#define ME_NOTEOFF 0x80
#define ME_NOTEON 0x90
#define ME_KEYPRESSURE 0xA0
#define ME_CONTROLCHANGE 0xB0
#define ME_PROGRAM 0xC0
#define ME_CHANNELPRESSURE 0xD0
#define ME_PITCHWHEEL 0xE0
enum
{
ME_NOTEOFF = 0x80,
ME_NOTEON = 0x90,
ME_KEYPRESSURE = 0xA0,
ME_CONTROLCHANGE = 0xB0,
ME_PROGRAM = 0xC0,
ME_CHANNELPRESSURE = 0xD0,
ME_PITCHWHEEL = 0xE0
};
/* Controllers */
#define CTRL_BANK_SELECT 0
#define CTRL_DATA_ENTRY 6
#define CTRL_VOLUME 7
#define CTRL_PAN 10
#define CTRL_EXPRESSION 11
#define CTRL_SUSTAIN 64
#define CTRL_HARMONICCONTENT 71
#define CTRL_RELEASETIME 72
#define CTRL_ATTACKTIME 73
#define CTRL_BRIGHTNESS 74
#define CTRL_REVERBERATION 91
#define CTRL_CHORUSDEPTH 93
#define CTRL_NRPN_LSB 98
#define CTRL_NRPN_MSB 99
#define CTRL_RPN_LSB 100
#define CTRL_RPN_MSB 101
#define CTRL_ALL_SOUNDS_OFF 120
#define CTRL_RESET_CONTROLLERS 121
#define CTRL_ALL_NOTES_OFF 123
/* NRPNs */
#define NRPN_BRIGHTNESS 0x00A0
#define NRPN_HARMONICCONTENT 0x00A1
#define NRPN_DRUMVOLUME (26<<7) // drum number in low 7 bits
#define NRPN_DRUMPANPOT (28<<7) // "
#define NRPN_DRUMREVERBERATION (29<<7) // "
#define NRPN_DRUMCHORUSDEPTH (30<<7) // "
enum
{
CTRL_BANK_SELECT = 0,
CTRL_DATA_ENTRY = 6,
CTRL_VOLUME = 7,
CTRL_PAN = 10,
CTRL_EXPRESSION = 11,
CTRL_SUSTAIN = 64,
CTRL_HARMONICCONTENT = 71,
CTRL_RELEASETIME = 72,
CTRL_ATTACKTIME = 73,
CTRL_BRIGHTNESS = 74,
CTRL_REVERBERATION = 91,
CTRL_CHORUSDEPTH = 93,
CTRL_NRPN_LSB = 98,
CTRL_NRPN_MSB = 99,
CTRL_RPN_LSB = 100,
CTRL_RPN_MSB = 101,
CTRL_ALL_SOUNDS_OFF = 120,
CTRL_RESET_CONTROLLERS = 121,
CTRL_ALL_NOTES_OFF = 123
};
/* RPNs */
#define RPN_PITCH_SENS 0x0000
#define RPN_FINE_TUNING 0x0001
#define RPN_COARSE_TUNING 0x0002
#define RPN_RESET 0x3fff
#define SFX_BANKTYPE 64
enum
{
RPN_PITCH_SENS = 0x0000,
RPN_FINE_TUNING = 0x0001,
RPN_COARSE_TUNING = 0x0002,
RPN_RESET = 0x3fff
};
struct Channel
{
int
bank, program, sustain, pitchbend,
mono, /* one note only on this channel -- not implemented yet */
/* new stuff */
variationbank, reverberation, chorusdepth, harmoniccontent,
releasetime, attacktime, brightness, kit, sfx,
/* end new */
pitchsens;
WORD
volume, expression;
@ -404,84 +452,71 @@ struct Channel
rpn, nrpn;
bool
nrpn_mode;
char
transpose;
float
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
};
/* Causes the instrument's default panning to be used. */
#define NO_PANNING -1
#define NO_PANNING -1
/* envelope points */
#define MAXPOINT 7
#define MAXPOINT 6
struct Voice
{
BYTE
status, channel, note, velocity, clone_type;
status, channel, note, velocity;
Sample *sample;
Sample *left_sample;
Sample *right_sample;
int clone_voice;
float
orig_frequency, frequency;
int
sample_offset, loop_start, loop_end;
int
envelope_volume, modulation_volume;
int
envelope_target, modulation_target;
int
tremolo_sweep, tremolo_sweep_position, tremolo_phase,
lfo_sweep, lfo_sweep_position, lfo_phase,
vibrato_sweep, vibrato_sweep_position, vibrato_depth,
echo_delay_count;
int
echo_delay,
sample_increment,
envelope_increment,
modulation_increment,
tremolo_phase_increment,
lfo_phase_increment;
sample_offset, sample_increment,
envelope_volume, envelope_target, envelope_increment,
tremolo_sweep, tremolo_sweep_position,
tremolo_phase, tremolo_phase_increment,
vibrato_sweep, vibrato_sweep_position;
final_volume_t left_mix, right_mix;
float
left_amp, right_amp,
volume, tremolo_volume, lfo_volume;
left_amp, right_amp, tremolo_volume;
int
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
int
envelope_rate[MAXPOINT], envelope_offset[MAXPOINT];
int
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
envelope_stage, modulation_stage, control_counter,
modulation_delay, modulation_counter, panning, panned;
envelope_stage, control_counter, panning, panned;
};
/* Voice status options: */
#define VOICE_FREE 0
#define VOICE_ON 1
#define VOICE_SUSTAINED 2
#define VOICE_OFF 3
#define VOICE_DIE 4
enum
{
VOICE_FREE,
VOICE_ON,
VOICE_SUSTAINED,
VOICE_OFF,
VOICE_DIE
};
/* Voice panned options: */
#define PANNED_MYSTERY 0
#define PANNED_LEFT 1
#define PANNED_RIGHT 2
#define PANNED_CENTER 3
enum
{
PANNED_MYSTERY,
PANNED_LEFT,
PANNED_RIGHT,
PANNED_CENTER
};
/* Anything but PANNED_MYSTERY only uses the left volume */
/* Envelope stages: */
#define ATTACK 0
#define HOLD 1
#define DECAY 2
#define RELEASE 3
#define RELEASEB 4
#define RELEASEC 5
#define DELAY 6
enum
{
ATTACK,
HOLD,
DECAY,
RELEASE,
RELEASEB,
RELEASEC
};
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
@ -498,9 +533,7 @@ tables.h
#define sine(x) (sin((2*PI/1024.0) * (x)))
#define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0)))
#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
#define XMAPMAX 800
#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
/*
timidity.h
@ -517,27 +550,16 @@ struct Renderer
{
float rate;
DLS_Data *patches;
InstrumentLayer *default_instrument;
Instrument *default_instrument;
int default_program;
bool fast_decay;
int resample_buffer_size;
sample_t *resample_buffer;
Channel channel[16];
Voice voice[MAX_VOICES];
signed char drumvolume[MAXCHAN][MAXNOTE];
signed char drumpanpot[MAXCHAN][MAXNOTE];
signed char drumreverberation[MAXCHAN][MAXNOTE];
signed char drumchorusdepth[MAXCHAN][MAXNOTE];
int control_ratio, amp_with_poly;
int drumchannels;
int adjust_panning_immediately;
int voices;
int GM_System_On;
int XG_System_On;
int GS_System_On;
int XG_System_reverb_type;
int XG_System_chorus_type;
int XG_System_variation_type;
int lost_notes, cut_notes;
Renderer(float sample_rate);
@ -558,10 +580,8 @@ struct Renderer
int convert_vibrato_rate(BYTE rate);
void recompute_amp(Voice *v);
int vc_alloc(int not_this_voice);
void kill_others(int voice);
void clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank);
void xremap(int *banknumpt, int *this_notept, int this_kit);
void kill_key_group(int voice);
float calculate_scaled_frequency(Sample *sample, int note);
void start_note(int chan, int note, int vel, int voice);
void note_on(int chan, int note, int vel);
@ -579,7 +599,6 @@ struct Renderer
void reset_midi();
void select_sample(int voice, Instrument *instr, int vel);
void select_stereo_samples(int voice, InstrumentLayer *layer, int vel);
void recompute_freq(int voice);
void kill_note(int voice);

View file

@ -64,6 +64,7 @@ BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
BYTE RedColormap[256];
BYTE GreenColormap[256];
BYTE DesaturateColormap[31][256];
static void FreeSpecialLights();;
@ -433,6 +434,24 @@ void InitPalette ()
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
intensity>>8 );
}
// desaturated colormaps
for(int m = 0; m < 31; m++)
{
shade = DesaturateColormap[m];
for (c = 0; c < 256; c++)
{
intensity = GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37;
int r = (GPalette.BaseColors[c].r * (31-m) + intensity *m) / 31;
int g = (GPalette.BaseColors[c].g * (31-m) + intensity *m) / 31;
int b = (GPalette.BaseColors[c].b * (31-m) + intensity *m) / 31;
shade[c] = ColorMatcher.Pick (r, g, b);
}
}
}
extern "C"

View file

@ -85,6 +85,7 @@ extern BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
extern BYTE RedColormap[256];
extern BYTE GreenColormap[256];
extern BYTE DesaturateColormap[31][256];
extern FPalette GPalette;
extern "C" {
extern FDynamicColormap NormalLight;

View file

@ -1157,216 +1157,6 @@ void DFrameBuffer::WipeCleanup()
wipe_Cleanup();
}
//===========================================================================
//
// multi-format pixel copy with colormap application
// requires one of the previously defined conversion classes to work
//
//===========================================================================
template<class T>
void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step)
{
for(int i=0;i<count;i++)
{
pout[0]=T::B(pin);
pout[1]=T::G(pin);
pout[2]=T::R(pin);
pout[3]=T::A(pin);
pout+=4;
pin+=step;
}
}
typedef void (*CopyFunc)(BYTE *pout, const BYTE *pin, int count, int step);
static CopyFunc copyfuncs[]={
iCopyColors<cRGB>,
iCopyColors<cRGBA>,
iCopyColors<cIA>,
iCopyColors<cCMYK>,
iCopyColors<cBGR>,
iCopyColors<cBGRA>,
iCopyColors<cI16>,
iCopyColors<cRGB555>,
iCopyColors<cPalEntry>
};
//===========================================================================
//
// Clips the copy area for CopyPixelData functions
//
//===========================================================================
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight,
int &pstep_x, int &pstep_y, int rotate)
{
int pixxoffset;
int pixyoffset;
int step_x;
int step_y;
// First adjust the settings for the intended rotation
switch (rotate)
{
default:
case 0: // normal
pixxoffset = 0;
pixyoffset = 0;
step_x = pstep_x;
step_y = pstep_y;
break;
case 1: // rotate 90° right
pixxoffset = 0;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
step_y = pstep_x;
break;
case 2: // rotate 180°
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_x;
step_y = -pstep_y;
break;
case 3: // rotate 90° left
pixxoffset = srcwidth - 1;
pixyoffset = 0;
step_x = pstep_y;
step_y = -pstep_x;
break;
case 4: // flip horizontally
pixxoffset = srcwidth - 1;
pixyoffset = 0;
step_x = -pstep_x;
step_y = pstep_y;
break;
case 5: // flip horizontally and rotate 90° right
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
step_y = -pstep_x;
break;
case 6: // flip vertically
pixxoffset = 0;
pixyoffset = srcheight - 1;
step_x = pstep_x;
step_y = -pstep_y;
break;
case 7: // flip horizontally and rotate 90° left
pixxoffset = 0;
pixyoffset = 0;
step_x = pstep_y;
step_y = pstep_x;
break;
}
if (rotate&1)
{
int v = srcwidth;
srcwidth = srcheight;
srcheight = v;
}
patch += pixxoffset * pstep_x + pixyoffset * pstep_y;
pstep_x = step_x;
pstep_y = step_y;
// clip source rectangle to destination
if (originx<0)
{
srcwidth+=originx;
patch-=originx*step_x;
originx=0;
if (srcwidth<=0) return false;
}
if (originx+srcwidth>texwidth)
{
srcwidth=texwidth-originx;
if (srcwidth<=0) return false;
}
if (originy<0)
{
srcheight+=originy;
patch-=originy*step_y;
originy=0;
if (srcheight<=0) return false;
}
if (originy+srcheight>texheight)
{
srcheight=texheight-originy;
if (srcheight<=0) return false;
}
return true;
}
//===========================================================================
//
// True Color texture copy function
//
//===========================================================================
void DFrameBuffer::CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y,
int rotate, int ct)
{
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
buffer+=4*originx + texpitch*originy;
for (int y=0;y<srcheight;y++)
{
copyfuncs[ct](&buffer[y*texpitch], &patch[y*step_y], srcwidth, step_x);
}
}
}
//===========================================================================
//
// Paletted to True Color texture copy function
//
//===========================================================================
void DFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight,
int step_x, int step_y, int rotate, PalEntry * palette)
{
int x,y,pos;
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
buffer+=4*originx + texpitch*originy;
for (y=0;y<srcheight;y++)
{
pos=y*texpitch;
for (x=0;x<srcwidth;x++,pos+=4)
{
int v=(unsigned char)patch[y*step_y+x*step_x];
if (palette[v].a==0)
{
buffer[pos]=palette[v].b;
buffer[pos+1]=palette[v].g;
buffer[pos+2]=palette[v].r;
buffer[pos+3]=255;
}
else if (palette[v].a!=255)
{
// [RH] Err... This can't be right, can it?
buffer[pos ] = (buffer[pos ] * palette[v].a + palette[v].b * (1-palette[v].a)) / 255;
buffer[pos+1] = (buffer[pos+1] * palette[v].a + palette[v].g * (1-palette[v].a)) / 255;
buffer[pos+2] = (buffer[pos+2] * palette[v].a + palette[v].r * (1-palette[v].a)) / 255;
buffer[pos+3] = clamp<int>(buffer[pos+3] + (( 255-buffer[pos+3]) * (255-palette[v].a))/255, 0, 255);
}
}
}
}
}
//===========================================================================
//
// Texture precaching

View file

@ -372,15 +372,6 @@ public:
// Create a palette texture from a remap/palette table.
virtual FNativePalette *CreatePalette(FRemapTable *remap);
// texture copy functions
virtual void CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int pix_width, int pix_height, int step_x, int step_y,
int rotate, int ct);
virtual void CopyPixelData(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int pix_width, int pix_height,
int step_x, int step_y, int rotate, PalEntry * palette);
// Precaches or unloads a texture
virtual void PrecacheTexture(FTexture *tex, int cache);
@ -405,9 +396,6 @@ private:
DWORD LastMS, LastSec, FrameCount, LastCount, LastTic;
};
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight,
int &step_x, int &step_y, int rotate);
extern FColorMatcher ColorMatcher;
@ -478,106 +466,5 @@ int CheckRatio (int width, int height);
extern const int BaseRatioSizes[5][4];
//===========================================================================
//
// True color conversion classes for the different pixel formats
// used by the supported texture formats
//
//===========================================================================
struct cRGB
{
static unsigned char R(const unsigned char * p) { return p[0]; }
static unsigned char G(const unsigned char * p) { return p[1]; }
static unsigned char B(const unsigned char * p) { return p[2]; }
static unsigned char A(const unsigned char * p) { return 255; }
static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
};
struct cRGBA
{
static unsigned char R(const unsigned char * p) { return p[0]; }
static unsigned char G(const unsigned char * p) { return p[1]; }
static unsigned char B(const unsigned char * p) { return p[2]; }
static unsigned char A(const unsigned char * p) { return p[3]; }
static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
};
struct cIA
{
static unsigned char R(const unsigned char * p) { return p[0]; }
static unsigned char G(const unsigned char * p) { return p[0]; }
static unsigned char B(const unsigned char * p) { return p[0]; }
static unsigned char A(const unsigned char * p) { return p[1]; }
static int Gray(const unsigned char * p) { return p[0]; }
};
struct cCMYK
{
static unsigned char R(const unsigned char * p) { return p[3] - (((256-p[0])*p[3]) >> 8); }
static unsigned char G(const unsigned char * p) { return p[3] - (((256-p[1])*p[3]) >> 8); }
static unsigned char B(const unsigned char * p) { return p[3] - (((256-p[2])*p[3]) >> 8); }
static unsigned char A(const unsigned char * p) { return 255; }
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
};
struct cBGR
{
static unsigned char R(const unsigned char * p) { return p[2]; }
static unsigned char G(const unsigned char * p) { return p[1]; }
static unsigned char B(const unsigned char * p) { return p[0]; }
static unsigned char A(const unsigned char * p) { return 255; }
static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
};
struct cBGRA
{
static unsigned char R(const unsigned char * p) { return p[2]; }
static unsigned char G(const unsigned char * p) { return p[1]; }
static unsigned char B(const unsigned char * p) { return p[0]; }
static unsigned char A(const unsigned char * p) { return p[3]; }
static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
};
struct cI16
{
static unsigned char R(const unsigned char * p) { return p[1]; }
static unsigned char G(const unsigned char * p) { return p[1]; }
static unsigned char B(const unsigned char * p) { return p[1]; }
static unsigned char A(const unsigned char * p) { return 255; }
static int Gray(const unsigned char * p) { return p[1]; }
};
struct cRGB555
{
static unsigned char R(const unsigned char * p) { return (((*(WORD*)p)&0x1f)<<3); }
static unsigned char G(const unsigned char * p) { return (((*(WORD*)p)&0x3e0)>>2); }
static unsigned char B(const unsigned char * p) { return (((*(WORD*)p)&0x7c00)>>7); }
static unsigned char A(const unsigned char * p) { return p[1]; }
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
};
struct cPalEntry
{
static unsigned char R(const unsigned char * p) { return ((PalEntry*)p)->r; }
static unsigned char G(const unsigned char * p) { return ((PalEntry*)p)->g; }
static unsigned char B(const unsigned char * p) { return ((PalEntry*)p)->b; }
static unsigned char A(const unsigned char * p) { return ((PalEntry*)p)->a; }
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
};
enum ColorType
{
CF_RGB,
CF_RGBA,
CF_IA,
CF_CMYK,
CF_BGR,
CF_BGRA,
CF_I16,
CF_RGB555,
CF_PalEntry
};
#endif // __V_VIDEO_H__

View file

@ -205,6 +205,7 @@ ACTOR WolfensteinSS 84
DeathSound "wolfss/death"
ActiveSound "wolfss/active"
AttackSound "wolfss/attack"
Obituary "$OB_WOLFSS"
Dropitem "Clip"
States
{

View file

@ -124,7 +124,7 @@ class Actor extends Thinker
action native A_FLoopActiveSound();
action native A_LoopActiveSound();
action native A_StopSound();
action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional bool looping, optional eval int attenuation);
action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional eval bool looping, optional eval int attenuation);
action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(eval int threshold, eval int turnmax);
action native A_Jump(eval int chance, state label, ...);
@ -174,8 +174,8 @@ class Actor extends Thinker
action native A_LookEx(optional eval int flags, optional eval float minseedist, optional eval float maxseedist, optional eval float maxheardist, optional eval float fov, optional state label);
action native A_ClearTarget();
action native A_JumpIfTargetInLOS (state label, optional eval float fov);
action native A_DamageMaster(int amount, optional name damagetype);
action native A_DamageChildren(int amount, optional name damagetype);
action native A_DamageMaster(eval int amount, optional name damagetype);
action native A_DamageChildren(eval int amount, optional name damagetype);
action native A_SelectWeapon(class<Weapon> whichweapon);
action native A_Punch();
}