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" RelativePath=".\src\textures\automaptexture.cpp"
> >
</File> </File>
<File
RelativePath=".\src\textures\bitmap.cpp"
>
</File>
<File
RelativePath=".\src\textures\bitmap.h"
>
</File>
<File <File
RelativePath=".\src\textures\buildtexture.cpp" RelativePath=".\src\textures\buildtexture.cpp"
> >

View file

@ -605,6 +605,12 @@ public:
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY); 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 // Calculate amount of missile damage
virtual int GetMissileDamage(int mask, int add); virtual int GetMissileDamage(int mask, int add);

View file

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

View file

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

View file

@ -535,6 +535,7 @@ void APowerStrength::InitEffect ()
void APowerStrength::Tick () void APowerStrength::Tick ()
{ {
// Strength counts up to diminish the fade. // 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; EffectTics += 2;
Super::Tick(); Super::Tick();
} }
@ -998,6 +999,7 @@ void APowerFlight::Tick ()
// The Wings of Wrath only expire in multiplayer and non-hub games // The Wings of Wrath only expire in multiplayer and non-hub games
if (!multiplayer && (level.flags & LEVEL_INFINITE_FLIGHT)) if (!multiplayer && (level.flags & LEVEL_INFINITE_FLIGHT))
{ {
assert(EffectTics < INT_MAX); // I can't see a game lasting nearly two years, but...
EffectTics++; 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); mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
const PClass *exit_flash = player->MorphExitFlash; const PClass *exit_flash = player->MorphExitFlash;
bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON);
player->morphTics = 0; player->morphTics = 0;
player->MorphedPlayerClass = 0; player->MorphedPlayerClass = 0;
@ -267,13 +268,32 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
{ {
player->ReadyWeapon = player->PendingWeapon = NULL; player->ReadyWeapon = player->PendingWeapon = NULL;
} }
if (beastweap != NULL) if (correctweapon)
{ // You don't get to keep your morphed weapon. { // Better "lose morphed weapon" semantics
if (beastweap->SisterWeapon != NULL) 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->tracer = NULL;
pmo->Destroy (); pmo->Destroy ();

View file

@ -17,7 +17,8 @@ enum
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails 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_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; struct PClass;

View file

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

View file

@ -52,7 +52,7 @@ void AWeapon::Serialize (FArchive &arc)
<< ProjectileType << AltProjectileType << ProjectileType << AltProjectileType
<< SelectionOrder << SelectionOrder
<< MoveCombatDist << MoveCombatDist
<< Ammo1 << Ammo2 << SisterWeapon << Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
<< bAltFire; << bAltFire;
} }
@ -230,6 +230,7 @@ void AWeapon::AttachToOwner (AActor *other)
StatusBar->ReceivedWeapon (this); 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 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); 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); void PrecacheTexture(FTexture *tex, bool cache);
// Create a native texture from a game texture. // Create a native texture from a game texture.
@ -81,13 +72,6 @@ public:
void RenderView (player_t* player); void RenderView (player_t* player);
void WriteSavePic (player_t *player, FILE *file, int width, int height); 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); bool WipeStartScreen(int type);
void WipeEndScreen(); void WipeEndScreen();
bool WipeDo(int ticks); bool WipeDo(int ticks);
@ -96,8 +80,12 @@ public:
private: private:
PalEntry Flash; PalEntry Flash;
// Texture creation info
int cm; int cm;
int translation; int translation;
bool iscomplex;
PalEntry SourcePalette[256]; PalEntry SourcePalette[256];
BYTE *ScreenshotBuffer; 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 #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 // 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) 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]; unsigned char * buffer=new unsigned char[w*(h+1)*4];
memset(buffer, 0, 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); CheckTrans(buffer, w*h, trans);
if (bHasColorkey) if (bHasColorkey)

View file

@ -76,9 +76,9 @@ public:
if (faces[0]) return faces[0]->GetPixels(); if (faces[0]) return faces[0]->GetPixels();
return NULL; 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; return 0;
} }
bool UseBasePalette() { return false; } // not really but here it's not important. bool UseBasePalette() { return false; } // not really but here it's not important.

View file

@ -48,6 +48,7 @@
#include "stats.h" #include "stats.h"
#include "templates.h" #include "templates.h"
#include "sc_man.h" #include "sc_man.h"
#include "r_translate.h"
#include "gl/gl_struct.h" #include "gl/gl_struct.h"
#include "gl/gl_framebuffer.h" #include "gl/gl_framebuffer.h"
@ -94,8 +95,8 @@ EXTERN_CVAR(Bool, gl_render_precise)
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE) CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
static char GlobalBrightmap[256];
static bool HasGlobalBrightmap; 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 *cmapdata = (const unsigned char *)cmap.GetMem();
const unsigned char *paldata = (const unsigned char *)palette.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 j=0;j<32;j++)
{ {
for(int i=0;i<256;i++) for(int i=0;i<256;i++)
@ -120,38 +127,18 @@ void gl_GenerateGlobalBrightmapFromColormap()
// and Hexen. // and Hexen.
if (cmapdata[i+j*256]!=i || (paldata[3*i]<10 && paldata[3*i+1]<10 && paldata[3*i+2]<10)) 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++) 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); //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 // multi-format pixel copy with colormap application
@ -300,16 +287,16 @@ static CopyFunc copyfuncs[]={
// base palette because they wouldn't be used anyway. // base palette because they wouldn't be used anyway.
// //
//=========================================================================== //===========================================================================
void OpenGLFrameBuffer::CopyPixelDataRGB(BYTE * buffer, int texpitch, int texheight, int originx, int originy, void FGLBitmap::CopyPixelDataRGB(int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y, const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
int rotate, int ct) 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++) 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 // Paletted to True Color texture copy function
// //
//=========================================================================== //===========================================================================
void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy, void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight,
const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf)
int step_x, int step_y, int rotate, PalEntry * palette)
{ {
PalEntry penew[256]; PalEntry penew[256];
int x,y,pos,i; 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 // CM_SHADE is an alpha map with 0==transparent and 1==opaque
if (cm == CM_SHADE) 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. 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 else
{ {
// apply any translation. // apply any translation.
@ -535,7 +499,7 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
// This can also handle full PNG translucency. // This can also handle full PNG translucency.
for (y=0;y<srcheight;y++) for (y=0;y<srcheight;y++)
{ {
pos=(y*texpitch); pos=(y*Pitch);
for (x=0;x<srcwidth;x++,pos+=4) for (x=0;x<srcwidth;x++,pos+=4)
{ {
int v=(unsigned char)patch[y*step_y+x*step_x]; 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; unsigned long * out;
bool direct; bool direct;
int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this); FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true; gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0) if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{ {
out = (unsigned long*)buffer; out = (unsigned long*)bmp->GetPixels();
direct=true; direct=true;
} }
else else
@ -595,9 +567,9 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
GenTime = r_FrameTime; GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long)); 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 timebase = r_FrameTime*23/28;
int xsize = Width; int xsize = Width;
int ysize = Height; int ysize = Height;
@ -638,7 +610,7 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
if (xx<0) xx=0; if (xx<0) xx=0;
if (yy<0) yy=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 linelen=MIN<int>(Width, buf_width-xx);
int linecount=MIN<int>(Height, buf_height-yy); 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 [] out;
} }
delete [] in;
GenTime=r_FrameTime; GenTime=r_FrameTime;
return ret; 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; unsigned long * out;
bool direct; bool direct;
int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this); FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true; gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0) if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{ {
out = (unsigned long*)buffer; out = (unsigned long*)bmp->GetPixels();
direct=true; direct=true;
} }
else else
@ -690,7 +669,7 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
GenTime = r_FrameTime; GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long)); 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 xsize = Width;
int ysize = Height; int ysize = Height;
@ -721,22 +700,22 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
if (!direct) 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 (xx<0) xx=0;
if (yy<0) yy=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 linelen=MIN<int>(Width, buf_width-xx);
int linecount=MIN<int>(Height, buf_height-yy); int linecount=MIN<int>(Height, buf_height-yy);
for(i=0;i<linecount;i++) for(i=0;i<linecount;i++)
{ {
memcpy(targ, &out[Width*i], linelen*sizeof(unsigned long)); memcpy(targ, &out[Width*i], linelen*sizeof(unsigned long));
targ+=buf_width; targ+=buf_pitch/4;
} }
delete [] out; delete [] out;
} }
delete [] in;
GenTime=r_FrameTime; GenTime=r_FrameTime;
return ret; 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->CopyTrueColorTranslated(bmp, x, y, rotate, &GlobalBrightmap);
SourcePic->CopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
return 0; return 0;
} }
@ -1198,13 +1176,12 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
unsigned char * buffer; unsigned char * buffer;
intptr_t cm = _cm; intptr_t cm = _cm;
SetTranslationInfo(cm, translation);
// Textures that are already scaled in the texture lump will not get replaced // Textures that are already scaled in the texture lump will not get replaced
// by hires textures // by hires textures
if (gl_texture_usehires && allowhires && scalex==1.f && scaley==1.f) if (gl_texture_usehires && allowhires && scalex==1.f && scaley==1.f)
{ {
buffer = LoadHiresTexture (&w, &h); buffer = LoadHiresTexture (&w, &h, _cm);
if (buffer) if (buffer)
{ {
return buffer; return buffer;
@ -1214,14 +1191,32 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
w=Width; w=Width;
h=Height; h=Height;
buffer=new unsigned char[Width*(Height+1)*4]; buffer=new unsigned char[Width*(Height+1)*4];
memset(buffer, 0, 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 = int trans =
tex->CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset, tex->CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
GetTopOffset() - tex->TopOffset);
CheckTrans(buffer, w*h, trans); 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. // 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 // Since FTexture's method is doing exactly that by calling GetPixels let's use that here
// to do all the dirty work for us. ;) // to do all the dirty work for us. ;)
tex->FTexture::CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset, tex->FTexture::CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
GetTopOffset() - tex->TopOffset);
} }
return buffer; return buffer;

View file

@ -5,6 +5,7 @@
#include "gl/gltexture.h" #include "gl/gltexture.h"
#include "r_data.h" #include "r_data.h"
#include "i_system.h" #include "i_system.h"
#include "textures/bitmap.h"
EXTERN_CVAR(Bool, gl_precache) EXTERN_CVAR(Bool, gl_precache)
EXTERN_CVAR(Bool, gl_brightmap_shader) EXTERN_CVAR(Bool, gl_brightmap_shader)
@ -14,6 +15,31 @@ struct GL_RECT;
void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count); 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); 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. // Two intermediate classes which wrap the low level textures.
// These ones are returned by the Bind* functions to ensure // These ones are returned by the Bind* functions to ensure
// that the coordinate functions aren't used without the texture // 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); static bool SmoothEdges(unsigned char * buffer,int w, int h, bool clampsides);
int CheckDDPK3(); int CheckDDPK3();
int CheckExternalFile(bool & hascolorkey); 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) void SetSize(int w, int h)
@ -247,7 +273,7 @@ public:
const BYTE *GetPixels (); const BYTE *GetPixels ();
void Unload (); 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; } bool UseBasePalette() { return false; }
protected: protected:

View file

@ -215,7 +215,7 @@ typedef struct fm_opl_f {
UINT32 eg_cnt; /* global envelope generator counter */ UINT32 eg_cnt; /* global envelope generator counter */
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */ UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
UINT32 eg_timer_add; /* step of eg_timer */ 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 */ 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))); static_cast<DSBarInfo*>(StatusBar)->SetMugShotState(FBehavior::StaticLookupString(STACK(1)));
} }
break; 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_SETMUGSHOTSTATE,
PCD_THINGCOUNTSECTOR, PCD_THINGCOUNTSECTOR,
PCD_THINGCOUNTNAMESECTOR, PCD_THINGCOUNTNAMESECTOR,
PCD_CHECKPLAYERCAMERA, // [TN]
PCODE_COMMAND_COUNT PCODE_COMMAND_COUNT
}; };

View file

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

View file

@ -1056,6 +1056,10 @@ void APlayerPawn::ActivateMorphWeapon ()
if (player->ReadyWeapon == NULL) if (player->ReadyWeapon == NULL)
{ {
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon)); 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) if (player->ReadyWeapon != NULL)
{ {

View file

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

View file

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

View file

@ -46,6 +46,26 @@
TAutoGrowArray<FRemapTablePtr, FRemapTable *> translationtables[NUM_TRANSLATION_TABLES]; 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 // 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. // 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]; BYTE IcePaletteRemap[16];
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {

View file

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

View file

@ -18,6 +18,7 @@ struct FMOD_CHANNELGROUP {};
struct FMOD_SOUNDGROUP {}; struct FMOD_SOUNDGROUP {};
struct FMOD_REVERB {}; struct FMOD_REVERB {};
struct FMOD_DSP {}; struct FMOD_DSP {};
struct FMOD_DSPCONNECTION {};
struct FMOD_POLYGON {}; struct FMOD_POLYGON {};
struct FMOD_GEOMETRY {}; struct FMOD_GEOMETRY {};
struct FMOD_SYNCPOINT {}; struct FMOD_SYNCPOINT {};
@ -39,6 +40,7 @@ namespace FMOD
class SoundGroup; class SoundGroup;
class Reverb; class Reverb;
class DSP; class DSP;
class DSPConnection;
class Geometry; class Geometry;
/* /*
@ -159,7 +161,7 @@ namespace FMOD
// System level DSP access. // System level DSP access.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_System_GetDSPHead(this, (FMOD_DSP **)dsp); } 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 lockDSP () { return FMOD_System_LockDSP(this); }
FMOD_RESULT unlockDSP () { return FMOD_System_UnlockDSP(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 getFrequency (float *frequency) { return FMOD_Channel_GetFrequency(this, frequency); }
FMOD_RESULT setPan (float pan) { return FMOD_Channel_SetPan(this, pan); } FMOD_RESULT setPan (float pan) { return FMOD_Channel_SetPan(this, pan); }
FMOD_RESULT getPan (float *pan) { return FMOD_Channel_GetPan(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 setDelay (FMOD_DELAYTYPE delaytype, unsigned int delayhi, unsigned int delaylo) { return FMOD_Channel_SetDelay(this, delaytype, delaylo, delayhi); }
FMOD_RESULT getDelay (unsigned int *startdelay, unsigned int *enddelay) { return FMOD_Channel_GetDelay(this, startdelay, enddelay); } 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 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 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); } 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. // 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 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. // Information only functions.
FMOD_RESULT isPlaying (bool *isplaying) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_IsPlaying(this, &b); *isplaying = b; return res; } 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. // 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 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. // Information only functions.
FMOD_RESULT getName (char *name, int namelen) { return FMOD_ChannelGroup_GetName(this, name, namelen); } 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); } FMOD_RESULT getSystemObject (System **system) { return FMOD_DSP_GetSystemObject(this, (FMOD_SYSTEM **)system); }
// Connection / disconnection / input and output enumeration. // 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 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 disconnectAll (bool inputs, bool outputs) { return FMOD_DSP_DisconnectAll(this, inputs, outputs); }
FMOD_RESULT remove () { return FMOD_DSP_Remove(this); } FMOD_RESULT remove () { return FMOD_DSP_Remove(this); }
FMOD_RESULT getNumInputs (int *numinputs) { return FMOD_DSP_GetNumInputs(this, numinputs); } FMOD_RESULT getNumInputs (int *numinputs) { return FMOD_DSP_GetNumInputs(this, numinputs); }
FMOD_RESULT getNumOutputs (int *numoutputs) { return FMOD_DSP_GetNumOutputs(this, numoutputs); } 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 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) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output); } FMOD_RESULT getOutput (int index, DSP **output, DSPConnection **outputconnection) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output, (FMOD_DSPCONNECTION **)outputconnection); }
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); }
// DSP unit control. // DSP unit control.
FMOD_RESULT setActive (bool active) { return FMOD_DSP_SetActive(this, active); } 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 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 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) ;} FMOD_RESULT getDefaults (float *frequency, float *volume, float *pan, int *priority) { return FMOD_DSP_GetDefaults(this, frequency, volume, pan, priority) ;}
// Userdata set/get. // Userdata set/get.
FMOD_RESULT setUserData (void *userdata) { return FMOD_DSP_SetUserData(this, userdata); } FMOD_RESULT setUserData (void *userdata) { return FMOD_DSP_SetUserData(this, userdata); }
FMOD_RESULT getUserData (void **userdata) { return FMOD_DSP_GetUserData(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 'Geometry' API
*/ */

View file

@ -70,8 +70,6 @@ extern HWND Window;
#define MAX_CHANNELS 256 #define MAX_CHANNELS 256
#define ERRCHECK(x)
#define SPECTRUM_SIZE 256 #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: public:
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner) FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner)
: Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL), : Owner(owner), Stream(NULL), Channel(NULL),
UserData(NULL), Callback(NULL) UserData(NULL), Callback(NULL), Ended(false)
{ {
SetStream(stream); SetStream(stream);
} }
FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner) FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner)
: Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL), : Owner(owner), Stream(NULL), Channel(NULL),
UserData(udata), Callback(callback) UserData(udata), Callback(callback), Ended(false)
{} {}
~FMODStreamCapsule() ~FMODStreamCapsule()
@ -333,11 +331,6 @@ public:
Channel->stop(); Channel->stop();
Channel = NULL; Channel = NULL;
} }
if (DSP != NULL)
{
DSP->release();
DSP = NULL;
}
} }
bool SetPaused(bool paused) bool SetPaused(bool paused)
@ -411,20 +404,16 @@ public:
FMODStreamCapsule *self; FMODStreamCapsule *self;
result = ((FMOD::Sound *)sound)->getUserData((void **)&self); result = ((FMOD::Sound *)sound)->getUserData((void **)&self);
if (result != FMOD_OK || self == NULL || self->Callback == NULL) if (result != FMOD_OK || self == NULL || self->Callback == NULL || self->Ended)
{
return FMOD_ERR_INVALID_PARAM;
}
if (self->Callback(self, data, datalen, self->UserData))
{ {
// Contrary to the docs, this return value is completely ignored.
return FMOD_OK; return FMOD_OK;
} }
else if (!self->Callback(self, data, datalen, self->UserData))
{ {
self->Channel->stop(); self->Ended = true;
// Contrary to the docs, this return value is completely ignored.
return FMOD_ERR_INVALID_PARAM;
} }
return FMOD_OK;
} }
static FMOD_RESULT F_CALLBACK PCMSetPosCallback(FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype) static FMOD_RESULT F_CALLBACK PCMSetPosCallback(FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype)
@ -438,9 +427,9 @@ private:
FMODSoundRenderer *Owner; FMODSoundRenderer *Owner;
FMOD::Sound *Stream; FMOD::Sound *Stream;
FMOD::Channel *Channel; FMOD::Channel *Channel;
FMOD::DSP *DSP;
void *UserData; void *UserData;
SoundStreamCallback Callback; SoundStreamCallback Callback;
bool Ended;
}; };
//========================================================================== //==========================================================================
@ -490,18 +479,22 @@ bool FMODSoundRenderer::Init()
PrevEnvironment = DefaultEnvironments[0]; PrevEnvironment = DefaultEnvironments[0];
Printf("I_InitSound: Initializing FMOD\n"); 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. // Create a System object and initialize.
result = FMOD::System_Create(&Sys); 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); 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) if (version < FMOD_VERSION)
{ {
@ -512,6 +505,11 @@ bool FMODSoundRenderer::Init()
return false; return false;
} }
if (!ShowedBanner)
{
Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2008.\n");
ShowedBanner = true;
}
#ifdef _WIN32 #ifdef _WIN32
if (OSPlatform == os_WinNT4) if (OSPlatform == os_WinNT4)
{ {
@ -554,7 +552,11 @@ bool FMODSoundRenderer::Init()
if (eval >= 0) if (eval >= 0)
{ {
result = Sys->setOutput(FMOD_OUTPUTTYPE(eval)); 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); result = Sys->getNumDrivers(&driver);
@ -562,7 +564,7 @@ bool FMODSoundRenderer::Init()
{ {
if (snd_driver >= driver) 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; driver = 0;
} }
else else
@ -573,7 +575,16 @@ bool FMODSoundRenderer::Init()
} }
result = Sys->getDriver(&driver); result = Sys->getDriver(&driver);
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode); 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. // Set the user selected speaker mode.
eval = Enum_NumForName(SpeakerModeNames, snd_speakermode); eval = Enum_NumForName(SpeakerModeNames, snd_speakermode);
@ -581,8 +592,11 @@ bool FMODSoundRenderer::Init()
{ {
speakermode = FMOD_SPEAKERMODE(eval); speakermode = FMOD_SPEAKERMODE(eval);
} }
result = Sys->setSpeakerMode(speakermode < 9000 ? speakermode : FMOD_SPEAKERMODE_STEREO); result = Sys->setSpeakerMode(speakermode);
ERRCHECK(result); if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Could not set speaker mode to '%s'. (Error %d)\n", *snd_speakermode, result);
}
// Set software format // Set software format
eval = Enum_NumForName(SoundFormatNames, snd_output_format); eval = Enum_NumForName(SoundFormatNames, snd_output_format);
@ -599,13 +613,20 @@ bool FMODSoundRenderer::Init()
} }
if (samplerate != snd_samplerate && snd_samplerate != 0) 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); 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 // Set software channels according to snd_channels
result = Sys->setSoftwareChannels(snd_channels + NUM_EXTRA_SOFTWARE_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) if (Driver_Caps & FMOD_CAPS_HARDWARE_EMULATED)
{ // The user has the 'Acceleration' slider set to off! { // 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"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"); 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. 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) else if (snd_buffersize != 0 || snd_buffercount != 0)
{ {
@ -621,6 +641,14 @@ bool FMODSoundRenderer::Init()
int buffercount = snd_buffercount ? snd_buffercount : 4; int buffercount = snd_buffercount ? snd_buffercount : 4;
result = Sys->setDSPBufferSize(buffersize, buffercount); 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 // Try to init
initflags = FMOD_INIT_NORMAL; initflags = FMOD_INIT_NORMAL;
@ -663,24 +691,43 @@ bool FMODSoundRenderer::Init()
} }
if (result != FMOD_OK) if (result != FMOD_OK)
{ // Initializing FMOD failed. Cry cry. { // 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; return false;
} }
// Create channel groups // Create channel groups
result = Sys->createChannelGroup("Music", &MusicGroup); 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); 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); 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); 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); 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->set3DSettings(0.5f, 96.f, 1.f);
Sys->set3DRolloffCallback(RolloffCallback); Sys->set3DRolloffCallback(RolloffCallback);
@ -729,6 +776,7 @@ void FMODSoundRenderer::Shutdown()
} }
Sys->close(); Sys->close();
Sys->release();
Sys = NULL; Sys = NULL;
} }
} }

View file

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

View file

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

View file

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

View file

@ -53,6 +53,7 @@
#include "r_local.h" #include "r_local.h"
#include "w_wad.h" #include "w_wad.h"
#include "templates.h" #include "templates.h"
#include "bitmap.h"
// Since we want this to compile under Linux too, we need to define this // Since we want this to compile under Linux too, we need to define this
// stuff ourselves instead of including a DirectX header. // 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); 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. // 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; delete [] TexBuffer;
return -1; return -1;
} }

View file

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

View file

@ -44,6 +44,8 @@
#include "sc_man.h" #include "sc_man.h"
#include "templates.h" #include "templates.h"
#include "vectors.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 // 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 // 4-byte boundary causes unaligned access warnings. Why it does this at
@ -177,6 +179,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
Unload (); Unload ();
if (Parts != NULL) 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; delete[] Parts;
Parts = NULL; Parts = NULL;
} }
@ -274,6 +281,70 @@ const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spa
return Pixels + column*Height; 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 // FMultiPatchTexture :: MakeTexture
@ -285,14 +356,20 @@ void FMultiPatchTexture::MakeTexture ()
// Add a little extra space at the end if the texture's height is not // 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. // a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height; int numpix = Width * Height + (1 << HeightBits) - Height;
BYTE blendwork[256];
Pixels = new BYTE[numpix]; Pixels = new BYTE[numpix];
memset (Pixels, 0, numpix); memset (Pixels, 0, numpix);
for (int i = 0; i < NumParts; ++i) 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].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; int retv = -1;
FCopyInfo info;
for(int i=0;i<NumParts;i++) for(int i=0;i<NumParts;i++)
{ {
int ret = Parts[i].Texture->CopyTrueColorPixels(buffer, buf_pitch, buf_height, int ret;
x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
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; if (ret > retv) retv = ret;
} }
@ -328,6 +460,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf
FTextureFormat FMultiPatchTexture::GetFormat() FTextureFormat FMultiPatchTexture::GetFormat()
{ {
if (bComplex) return TEX_RGB;
if (NumParts == 1) return Parts[0].Texture->GetFormat(); if (NumParts == 1) return Parts[0].Texture->GetFormat();
return UseBasePalette() ? TEX_Pal : TEX_RGB; return UseBasePalette() ? TEX_Pal : TEX_RGB;
} }
@ -344,6 +477,7 @@ FTextureFormat FMultiPatchTexture::GetFormat()
bool FMultiPatchTexture::UseBasePalette() bool FMultiPatchTexture::UseBasePalette()
{ {
if (bComplex) return false;
for(int i=0;i<NumParts;i++) for(int i=0;i<NumParts;i++)
{ {
if (!Parts[i].Texture->UseBasePalette()) return false; if (!Parts[i].Texture->UseBasePalette()) return false;
@ -490,18 +624,8 @@ FMultiPatchTexture::TexPart::TexPart()
Rotate = 0; Rotate = 0;
textureOwned = false; textureOwned = false;
Texture = NULL; Texture = NULL;
} Translation = NULL;
Blend = 0;
//==========================================================================
//
// FMultiPatchTexture :: TexPart :: TexPart
//
//==========================================================================
FMultiPatchTexture::TexPart::~TexPart()
{
if (textureOwned && Texture != NULL) delete Texture;
Texture = NULL;
} }
//========================================================================== //==========================================================================
@ -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) void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
{ {
FString patchname; FString patchname;
@ -690,10 +825,20 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch); part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
part.textureOwned = true; 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 else
{ {
part.Texture = TexMan[texno]; part.Texture = TexMan[texno];
bComplex |= part.Texture->bComplex;
} }
if (part.Texture == NULL) if (part.Texture == NULL)
{ {
@ -728,6 +873,113 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
} }
part.Rotate = (sc.Number / 90) & 3; 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) if (Mirror & 2)
@ -790,7 +1042,9 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
{ {
TexPart part; TexPart part;
ParsePatch(sc, 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 "r_local.h"
#include "w_wad.h" #include "w_wad.h"
#include "templates.h" #include "templates.h"
#include "bitmap.h"
bool FPCXTexture::Check(FileReader & file) 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]; PalEntry pe[256];
PCXHeader header; PCXHeader header;
@ -472,14 +473,13 @@ int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
lump.Seek(sizeof(header), SEEK_SET); lump.Seek(sizeof(header), SEEK_SET);
ReadPCX8bits (Pixels, lump, &header); 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 else
{ {
Pixels = new BYTE[Width*Height * 3]; Pixels = new BYTE[Width*Height * 3];
BYTE * row = buffer;
ReadPCX24bits (Pixels, lump, &header, 3); 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; delete [] Pixels;
return 0; return 0;

View file

@ -39,6 +39,7 @@
#include "w_wad.h" #include "w_wad.h"
#include "templates.h" #include "templates.h"
#include "m_png.h" #include "m_png.h"
#include "bitmap.h"
bool FPNGTexture::Check(FileReader & file) 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? // Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
PalEntry pe[256]; PalEntry pe[256];
@ -554,20 +555,20 @@ int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 0: case 0:
case 3: 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; break;
case 2: 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; break;
case 4: 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; transpal = -1;
break; break;
case 6: 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; transpal = -1;
break; break;

View file

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

View file

@ -38,6 +38,7 @@
#include "r_local.h" #include "r_local.h"
#include "w_wad.h" #include "w_wad.h"
#include "templates.h" #include "templates.h"
#include "bitmap.h"
bool FTGATexture::Check(FileReader & data) 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]; PalEntry pe[256];
FWadLump lump = Wads.OpenLumpNum (SourceLump); 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) switch (hdr.img_type & 7)
{ {
case 1: // paletted 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; break;
case 2: // RGB case 2: // RGB
@ -477,21 +478,21 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 15: case 15:
case 16: 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; break;
case 24: 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; break;
case 32: case 32:
if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel 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 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; transval = -1;
} }
break; break;
@ -506,11 +507,11 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 8: case 8:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map 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; break;
case 16: 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; break;
default: default:

View file

@ -313,7 +313,7 @@ void A_PlaySoundEx (AActor *self)
int soundid = StateParameters[index]; int soundid = StateParameters[index];
ENamedName channel = ENamedName(StateParameters[index + 1]); 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_raw = EvalExpressionI(StateParameters[index + 3], self);
int attenuation; int attenuation;

View file

@ -754,11 +754,11 @@ static int ParseMorphStyle (FScanner &sc)
{ {
static const char * morphstyles[]={ static const char * morphstyles[]={
"MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE", "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[]={ static const int morphstyle_values[]={
MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE, 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... // May be given flags by number...
if (sc.CheckNumber()) 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_Region *rgn = &ins->regions[index];
DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex]; DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
if (!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE)) sample->self_nonexclusive = !!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE);
{ sample->key_group = (SBYTE)rgn->header->usKeyGroup;
sample->exclusiveClass = (SBYTE)rgn->header->usKeyGroup;
}
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow)); sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh)); sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote)); sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
sample->low_vel = rgn->header->RangeVelocity.usLow; sample->low_vel = rgn->header->RangeVelocity.usLow;
sample->high_vel = rgn->header->RangeVelocity.usHigh; 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->sample_rate = wave->format->dwSamplesPerSec;
sample->data = NULL; sample->data = NULL;
sample->data_length = wave->length; sample->data_length = wave->length;
convert_sample_data(sample, wave->data); convert_sample_data(sample, wave->data);
if (rgn->wsmp->cSampleLoops) { if (rgn->wsmp->cSampleLoops)
sample->modes |= (MODES_LOOPING|MODES_SUSTAIN); {
sample->modes |= (PATCH_LOOPEN | PATCH_SUSTAIN);
sample->loop_start = rgn->wsmp_loop->ulStart / 2; sample->loop_start = rgn->wsmp_loop->ulStart / 2;
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2); sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
} }
sample->volume = 1.0f; sample->volume = 1.0f;
if (sample->modes & MODES_SUSTAIN) { if (sample->modes & PATCH_SUSTAIN)
{
int value; int value;
double attack, hold, decay, release; int sustain; double attack, hold, decay, release; int sustain;
CONNECTIONLIST *art = NULL; 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_offset[RELEASEC] = to_offset(0);
sample->envelope_rate[RELEASEC] = to_offset(1); sample->envelope_rate[RELEASEC] = to_offset(1);
sample->modes |= MODES_ENVELOPE; sample->modes |= PATCH_NO_SRELEASE;
}
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->data_length <<= FRACTION_BITS; 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; 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; DWORD i;
DLS_Instrument *dls_ins = NULL; DLS_Instrument *dls_ins = NULL;
if (song->patches == NULL) if (song->patches == NULL)
{
return NULL; return NULL;
}
drum = drum ? 0x80000000 : 0; 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]; dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum && if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank && ((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument) dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break; break;
} }
if (i == song->patches->cInstruments && !bank) { if (i == song->patches->cInstruments && bank == 0)
for (i = 0; i < song->patches->cInstruments; ++i) { {
for (i = 0; i < song->patches->cInstruments; ++i)
{
dls_ins = &song->patches->instruments[i]; dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum && if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument) dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break; 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)); // SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
return NULL; return NULL;
} }
layer = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer)); inst = (Instrument *)safe_malloc(sizeof(Instrument));
layer->lo = 0; inst->type = INST_DLS;
layer->hi = 127; inst->samples = dls_ins->header->cRegions;
layer->instrument = (Instrument *)safe_malloc(sizeof(Instrument)); inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
layer->instrument->type = INST_DLS; memset(inst->sample, 0, inst->samples * sizeof(Sample));
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));
/* /*
printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples); 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) { for (i = 0; i < dls_ins->header->cRegions; ++i)
load_region_dls(song, &layer->instrument->sample[i], dls_ins, i); {
load_region_dls(song, &inst->sample[i], dls_ins, i);
} }
return layer; return inst;
} }
#endif /* !TEST_MAIN_DLS */ #endif /* !TEST_MAIN_DLS */

View file

@ -37,15 +37,14 @@ int recompute_envelope(Voice *v)
stage = v->envelope_stage; stage = v->envelope_stage;
if (stage >= DELAY) if (stage > RELEASEC)
{ {
/* Envelope ran out. */ /* Envelope ran out. */
int tmp = (v->status == VOICE_DIE); /* Already displayed as dead */
v->status = VOICE_FREE; v->status = VOICE_FREE;
return 1; return 1;
} }
if (v->sample->modes & MODES_ENVELOPE) if (v->sample->modes & PATCH_NO_SRELEASE)
{ {
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED) if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
{ {
@ -60,7 +59,9 @@ int recompute_envelope(Voice *v)
v->envelope_stage = stage + 1; v->envelope_stage = stage + 1;
if (v->envelope_volume == v->sample->envelope_offset[stage]) if (v->envelope_volume == v->sample->envelope_offset[stage])
{
return recompute_envelope(v); return recompute_envelope(v);
}
v->envelope_target = v->sample->envelope_offset[stage]; v->envelope_target = v->sample->envelope_offset[stage];
v->envelope_increment = v->sample->envelope_rate[stage]; v->envelope_increment = v->sample->envelope_rate[stage];
if (v->envelope_target < v->envelope_volume) if (v->envelope_target < v->envelope_volume)
@ -75,28 +76,30 @@ void apply_envelope_to_amp(Voice *v)
{ {
ramp = v->right_amp; ramp = v->right_amp;
if (v->tremolo_phase_increment) if (v->tremolo_phase_increment != 0)
{ {
lamp *= v->tremolo_volume; lamp *= v->tremolo_volume;
ramp *= 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)); double vol = calc_vol(v->envelope_volume / float(1 << 30));
lamp *= vol; lamp *= vol;
ramp *= vol; ramp *= vol;
} }
v->left_mix = float(lamp); v->left_mix = float(lamp);
v->right_mix = float(ramp); v->right_mix = float(ramp);
} }
else else
{ {
if (v->tremolo_phase_increment) if (v->tremolo_phase_increment != 0)
{
lamp *= v->tremolo_volume; 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)); lamp *= calc_vol(v->envelope_volume / float(1 << 30));
}
v->left_mix = float(lamp); v->left_mix = float(lamp);
} }
} }
@ -104,13 +107,14 @@ void apply_envelope_to_amp(Voice *v)
static int update_envelope(Voice *v) static int update_envelope(Voice *v)
{ {
v->envelope_volume += v->envelope_increment; v->envelope_volume += v->envelope_increment;
/* Why is there no ^^ operator?? */
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) || if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
((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; v->envelope_volume = v->envelope_target;
if (recompute_envelope(v)) if (recompute_envelope(v))
{
return 1; return 1;
}
} }
return 0; return 0;
} }
@ -119,7 +123,7 @@ static void update_tremolo(Voice *v)
{ {
int depth = v->sample->tremolo_depth << 7; int depth = v->sample->tremolo_depth << 7;
if (v->tremolo_sweep) if (v->tremolo_sweep != 0)
{ {
/* Update sweep position */ /* Update sweep position */
@ -151,12 +155,14 @@ static void update_tremolo(Voice *v)
/* Returns 1 if the note died */ /* Returns 1 if the note died */
static int update_signal(Voice *v) static int update_signal(Voice *v)
{ {
if (v->envelope_increment && update_envelope(v)) if (v->envelope_increment != 0 && update_envelope(v))
{
return 1; return 1;
}
if (v->tremolo_phase_increment) if (v->tremolo_phase_increment != 0)
{
update_tremolo(v); update_tremolo(v);
}
apply_envelope_to_amp(v); apply_envelope_to_amp(v);
return 0; 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 */ /* We only need to compute one half of the vibrato sine cycle */
static int vib_phase_to_inc_ptr(int phase) static int vib_phase_to_inc_ptr(int phase)
{ {
if (phase < VIBRATO_SAMPLE_INCREMENTS/2) if (phase < VIBRATO_SAMPLE_INCREMENTS / 2)
return VIBRATO_SAMPLE_INCREMENTS/2-1-phase; return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase;
else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2) else if (phase >= VIBRATO_SAMPLE_INCREMENTS * 3 / 2)
return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase; return VIBRATO_SAMPLE_INCREMENTS * 5 / 2 - 1 - phase;
else else
return phase-VIBRATO_SAMPLE_INCREMENTS/2; return phase - VIBRATO_SAMPLE_INCREMENTS / 2;
} }
static int update_vibrato(float output_rate, Voice *vp, int sign) 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; int phase;
double a, pb; double a, pb;
if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1) if (vp->vibrato_phase++ >= 2 * VIBRATO_SAMPLE_INCREMENTS - 1)
vp->vibrato_phase=0; vp->vibrato_phase = 0;
phase = vib_phase_to_inc_ptr(vp->vibrato_phase); phase = vib_phase_to_inc_ptr(vp->vibrato_phase);
if (vp->vibrato_sample_increment[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. */ /* Need to compute this sample increment. */
depth = vp->sample->vibrato_depth << 7; depth = vp->sample->vibrato_depth << 7;
if (vp->vibrato_sweep) if (vp->vibrato_sweep != 0)
{ {
/* Need to update sweep */ /* Need to update sweep */
vp->vibrato_sweep_position += vp->vibrato_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))) pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS)))
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING); * (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 the sweep's over, we can store the newly computed sample_increment */
if (!vp->vibrato_sweep) if (!vp->vibrato_sweep)
@ -511,11 +511,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
if (vp->vibrato_control_ratio) if (vp->vibrato_control_ratio)
{ {
if ((modes & MODES_LOOPING) && if ((modes & PATCH_LOOPEN) &&
((modes & MODES_ENVELOPE) || ((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) (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); return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
else else
return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr); 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 else
{ {
if ((modes & MODES_LOOPING) && if ((modes & PATCH_LOOPEN) &&
((modes & MODES_ENVELOPE) || ((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) (vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
{ {
if (modes & MODES_PINGPONG) if (modes & PATCH_BIDIR)
return rs_bidir(song->resample_buffer, vp, *countptr); return rs_bidir(song->resample_buffer, vp, *countptr);
else else
return rs_loop(song->resample_buffer, vp, *countptr); 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" "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
}; };
cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)", if (sp->scale_factor != 0)
sp->note_to_use, return;
note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
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) if (a <= 0)
return; return;
newlen = (int)(sp->data_length / a); newlen = (int)(sp->data_length / a);

View file

@ -413,6 +413,13 @@ void FreeAll()
int LoadConfig(const char *filename) 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(); clear_pathlist();
#ifdef _WIN32 #ifdef _WIN32
add_to_pathlist("C:\\TIMIDITY"); add_to_pathlist("C:\\TIMIDITY");
@ -443,25 +450,21 @@ Renderer::Renderer(float sample_rate)
{ {
rate = sample_rate; rate = sample_rate;
patches = NULL; patches = NULL;
default_instrument = NULL;
#ifdef FAST_DECAY
fast_decay = true;
#else
fast_decay = false;
#endif
resample_buffer_size = 0; resample_buffer_size = 0;
resample_buffer = NULL; resample_buffer = NULL;
adjust_panning_immediately = false;
control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO); 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()) if (def_instr_name.IsNotEmpty())
set_default_instrument(def_instr_name); set_default_instrument(def_instr_name);
voices = DEFAULT_VOICES; 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; drumchannels = DEFAULT_DRUMCHANNELS;
} }
@ -492,22 +495,7 @@ void Renderer::ComputeOutput(float *buffer, int count)
{ {
if (v->status != VOICE_FREE) if (v->status != VOICE_FREE)
{ {
if (v->sample_offset == 0 && v->echo_delay_count) mix_voice(this, buffer, v, 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);
}
} }
} }
} }
@ -520,6 +508,11 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{ {
return; return;
} }
if (banknum != 0)
{
/* Mark the standard bank in case it's not defined by this one. */
MarkInstrument(0, percussion, instr);
}
if (percussion) if (percussion)
{ {
bank = drumset[banknum]; bank = drumset[banknum];
@ -532,9 +525,9 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{ {
return; 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); va_start(args, fmt);
vsprintf(buf, fmt, args); vsprintf(buf, fmt, args);
va_end(args); va_end(args);
size_t l = strlen(buf);
buf[l] = '\n';
buf[l+1] = '\0';
OutputDebugString(buf); OutputDebugString(buf);
#endif #endif
} }

View file

@ -33,33 +33,27 @@ config.h
*/ */
/* Acoustic Grand Piano seems to be the usual default instrument. */ /* 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. /* 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. 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 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 try to play music on it. This is now a runtime option, so this isn't
a critical choice anymore. */ a critical choice anymore. */
#define DEFAULT_DRUMCHANNELS (1<<9) #define DEFAULT_DRUMCHANNELS (1<<9)
/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/ /*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
/* Default sampling rate, default polyphony, and maximum polyphony. /* Default polyphony, and maximum polyphony. */
All but the last can be overridden from the command line. */ #define DEFAULT_VOICES 32
#define DEFAULT_RATE 32000 #define MAX_VOICES 256
#define DEFAULT_VOICES 32
#define MAX_VOICES 256 #define MAXCHAN 16
#define MAXCHAN 16 #define MAXNOTE 128
#define MAXNOTE 128
/* 1000 here will give a control ratio of 22:1 with 22 kHz output. /* 1000 here will give a control ratio of 22:1 with 22 kHz output.
Higher CONTROLS_PER_SECOND values allow more accurate rendering Higher CONTROLS_PER_SECOND values allow more accurate rendering
of envelopes and tremolo. The cost is CPU time. */ of envelopes and tremolo. The cost is CPU time. */
#define CONTROLS_PER_SECOND 1000 #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
/* How many bits to use for the fractional part of sample positions. /* How many bits to use for the fractional part of sample positions.
This affects tonal accuracy. The entire position counter must fit 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 a sample is 1048576 samples (2 megabytes in memory). The GUS gets
by with just 9 bits and a little help from its friends... by with just 9 bits and a little help from its friends...
"The GUS does not SUCK!!!" -- a happy user :) */ "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 /* For some reason the sample volume is always set to maximum in all
patch files. Define this for a crude adjustment that may help 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 /* The number of samples to use for ramping out a dying note. Affects
click removal. */ 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 /* 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 */ /* change FRACTION_BITS above, not these */
#define INTEGER_BITS (32 - FRACTION_BITS) #define INTEGER_BITS (32 - FRACTION_BITS)
#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS) #define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
#define FRACTION_MASK (~ INTEGER_MASK) #define FRACTION_MASK (~ INTEGER_MASK)
#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS) #define MAX_SAMPLE_SIZE (1 << INTEGER_BITS)
/* This is enforced by some computations that must fit in an int */ /* 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 */ /* The TiMiditiy configuration file */
#define CONFIG_FILE "timidity.cfg" #define CONFIG_FILE "timidity.cfg"
typedef float sample_t; typedef float sample_t;
typedef float final_volume_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 FSCALE(a,b) ((a) * (float)(1<<(b)))
#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b)))) #define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b))))
/* Vibrato and tremolo Choices of the Day */ /* Vibrato and tremolo Choices of the Day */
#define SWEEP_TUNING 38 #define SWEEP_TUNING 38
#define VIBRATO_AMPLITUDE_TUNING 1.0L #define VIBRATO_AMPLITUDE_TUNING 1.0
#define VIBRATO_RATE_TUNING 38 #define VIBRATO_RATE_TUNING 38
#define TREMOLO_AMPLITUDE_TUNING 1.0L #define TREMOLO_AMPLITUDE_TUNING 1.0
#define TREMOLO_RATE_TUNING 38 #define TREMOLO_RATE_TUNING 38
#define SWEEP_SHIFT 16 #define SWEEP_SHIFT 16
#define RATE_SHIFT 5 #define RATE_SHIFT 5
#define VIBRATO_SAMPLE_INCREMENTS 32 #define VIBRATO_SAMPLE_INCREMENTS 32
#ifndef PI #ifndef PI
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846
@ -188,21 +182,20 @@ FileReader *open_filereader(const char *name, int open, int *plumpnum);
controls.h controls.h
*/ */
#define CMSG_INFO 0 enum
#define CMSG_WARNING 1 {
#define CMSG_ERROR 2 CMSG_INFO,
#define CMSG_FATAL 3 CMSG_WARNING,
#define CMSG_TRACE 4 CMSG_ERROR
#define CMSG_TIME 5 };
#define CMSG_TOTAL 6
#define CMSG_FILE 7
#define CMSG_TEXT 8
#define VERB_NORMAL 0 enum
#define VERB_VERBOSE 1 {
#define VERB_NOISY 2 VERB_NORMAL,
#define VERB_DEBUG 3 VERB_VERBOSE,
#define VERB_DEBUG_SILLY 4 VERB_NOISY,
VERB_DEBUG
};
void cmsg(int type, int verbosity_level, const char *fmt, ...); void cmsg(int type, int verbosity_level, const char *fmt, ...);
@ -217,114 +210,174 @@ struct Sample
loop_start, loop_end, data_length, loop_start, loop_end, data_length,
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq; sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
SDWORD SDWORD
envelope_rate[7], envelope_offset[7]; envelope_rate[6], envelope_offset[6];
float float
modulation_rate[7], modulation_offset[7]; volume;
float
volume, resonance,
modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc;
sample_t *data; sample_t *data;
SDWORD SDWORD
tremolo_sweep_increment, tremolo_phase_increment, tremolo_sweep_increment, tremolo_phase_increment,
lfo_sweep_increment, lfo_phase_increment, vibrato_sweep_increment, vibrato_control_ratio;
vibrato_sweep_increment, vibrato_control_ratio,
cutoff_freq;
BYTE BYTE
reverberation, chorusdepth,
tremolo_depth, vibrato_depth, tremolo_depth, vibrato_depth,
modes, modes;
attenuation;
WORD WORD
freq_center, panning; panning, scale_factor;
SBYTE
note_to_use, exclusiveClass;
SWORD SWORD
keyToModEnvHold, keyToModEnvDecay, scale_note;
keyToVolEnvHold, keyToVolEnvDecay; bool
SDWORD self_nonexclusive;
freq_scale; BYTE
key_group;
}; };
void convert_sample_data(Sample *sample, const void *data); void convert_sample_data(Sample *sample, const void *data);
void free_instruments(); void free_instruments();
/* Bits in modes: */ /* Patch definition: */
#define MODES_16BIT (1<<0) enum
#define MODES_UNSIGNED (1<<1) {
#define MODES_LOOPING (1<<2) HEADER_SIZE = 12,
#define MODES_PINGPONG (1<<3) ID_SIZE = 10,
#define MODES_REVERSE (1<<4) DESC_SIZE = 60,
#define MODES_SUSTAIN (1<<5) RESERVED_SIZE = 40,
#define MODES_ENVELOPE (1<<6) PATCH_HEADER_RESERVED_SIZE = 36,
#define MODES_FAST_RELEASE (1<<7) 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 enum
#define INST_SF2 1 {
#define INST_DLS 2 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 struct Instrument
{ {
Instrument();
~Instrument();
int type; int type;
int samples; int samples;
Sample *sample; 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 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) note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
{} {}
FString name; FString name;
InstrumentLayer *layer;
int font_type, sf_ix, tuning;
int note, amp, pan, strip_loop, strip_envelope, strip_tail; int note, amp, pan, strip_loop, strip_envelope, strip_tail;
}; };
/* A hack to delay instrument loading until after reading the /* A hack to delay instrument loading until after reading the
entire MIDI file. */ entire MIDI file. */
#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1)) #define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
#define MAXPROG 128 enum
#define MAXBANK 130 {
#define SFXBANK (MAXBANK-1) MAXPROG = 128,
#define SFXDRUM1 (MAXBANK-2) MAXBANK = 128
#define SFXDRUM2 (MAXBANK-1) };
#define XGDRUM 1
struct ToneBank struct ToneBank
{ {
FString name; ToneBank();
ToneBankElement tone[MAXPROG]; ~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); extern void pcmap(int *b, int *v, int *p, int *drums);
@ -341,60 +394,55 @@ playmidi.h
*/ */
/* Midi events */ /* Midi events */
#define ME_NOTEOFF 0x80 enum
#define ME_NOTEON 0x90 {
#define ME_KEYPRESSURE 0xA0 ME_NOTEOFF = 0x80,
#define ME_CONTROLCHANGE 0xB0 ME_NOTEON = 0x90,
#define ME_PROGRAM 0xC0 ME_KEYPRESSURE = 0xA0,
#define ME_CHANNELPRESSURE 0xD0 ME_CONTROLCHANGE = 0xB0,
#define ME_PITCHWHEEL 0xE0 ME_PROGRAM = 0xC0,
ME_CHANNELPRESSURE = 0xD0,
ME_PITCHWHEEL = 0xE0
};
/* Controllers */ /* Controllers */
#define CTRL_BANK_SELECT 0 enum
#define CTRL_DATA_ENTRY 6 {
#define CTRL_VOLUME 7 CTRL_BANK_SELECT = 0,
#define CTRL_PAN 10 CTRL_DATA_ENTRY = 6,
#define CTRL_EXPRESSION 11 CTRL_VOLUME = 7,
#define CTRL_SUSTAIN 64 CTRL_PAN = 10,
#define CTRL_HARMONICCONTENT 71 CTRL_EXPRESSION = 11,
#define CTRL_RELEASETIME 72 CTRL_SUSTAIN = 64,
#define CTRL_ATTACKTIME 73 CTRL_HARMONICCONTENT = 71,
#define CTRL_BRIGHTNESS 74 CTRL_RELEASETIME = 72,
#define CTRL_REVERBERATION 91 CTRL_ATTACKTIME = 73,
#define CTRL_CHORUSDEPTH 93 CTRL_BRIGHTNESS = 74,
#define CTRL_NRPN_LSB 98 CTRL_REVERBERATION = 91,
#define CTRL_NRPN_MSB 99 CTRL_CHORUSDEPTH = 93,
#define CTRL_RPN_LSB 100 CTRL_NRPN_LSB = 98,
#define CTRL_RPN_MSB 101 CTRL_NRPN_MSB = 99,
#define CTRL_ALL_SOUNDS_OFF 120 CTRL_RPN_LSB = 100,
#define CTRL_RESET_CONTROLLERS 121 CTRL_RPN_MSB = 101,
#define CTRL_ALL_NOTES_OFF 123 CTRL_ALL_SOUNDS_OFF = 120,
CTRL_RESET_CONTROLLERS = 121,
/* NRPNs */ CTRL_ALL_NOTES_OFF = 123
#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) // "
/* RPNs */ /* RPNs */
#define RPN_PITCH_SENS 0x0000 enum
#define RPN_FINE_TUNING 0x0001 {
#define RPN_COARSE_TUNING 0x0002 RPN_PITCH_SENS = 0x0000,
#define RPN_RESET 0x3fff RPN_FINE_TUNING = 0x0001,
RPN_COARSE_TUNING = 0x0002,
#define SFX_BANKTYPE 64 RPN_RESET = 0x3fff
};
struct Channel struct Channel
{ {
int int
bank, program, sustain, pitchbend, bank, program, sustain, pitchbend,
mono, /* one note only on this channel -- not implemented yet */ mono, /* one note only on this channel -- not implemented yet */
/* new stuff */
variationbank, reverberation, chorusdepth, harmoniccontent,
releasetime, attacktime, brightness, kit, sfx,
/* end new */
pitchsens; pitchsens;
WORD WORD
volume, expression; volume, expression;
@ -404,84 +452,71 @@ struct Channel
rpn, nrpn; rpn, nrpn;
bool bool
nrpn_mode; nrpn_mode;
char
transpose;
float float
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */ pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
}; };
/* Causes the instrument's default panning to be used. */ /* Causes the instrument's default panning to be used. */
#define NO_PANNING -1 #define NO_PANNING -1
/* envelope points */ /* envelope points */
#define MAXPOINT 7 #define MAXPOINT 6
struct Voice struct Voice
{ {
BYTE BYTE
status, channel, note, velocity, clone_type; status, channel, note, velocity;
Sample *sample; Sample *sample;
Sample *left_sample;
Sample *right_sample;
int clone_voice;
float float
orig_frequency, frequency; orig_frequency, frequency;
int int
sample_offset, loop_start, loop_end; sample_offset, sample_increment,
int envelope_volume, envelope_target, envelope_increment,
envelope_volume, modulation_volume; tremolo_sweep, tremolo_sweep_position,
int tremolo_phase, tremolo_phase_increment,
envelope_target, modulation_target; vibrato_sweep, vibrato_sweep_position;
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;
final_volume_t left_mix, right_mix; final_volume_t left_mix, right_mix;
float float
left_amp, right_amp, left_amp, right_amp, tremolo_volume;
volume, tremolo_volume, lfo_volume;
int int
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS]; vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
int
envelope_rate[MAXPOINT], envelope_offset[MAXPOINT];
int int
vibrato_phase, vibrato_control_ratio, vibrato_control_counter, vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
envelope_stage, modulation_stage, control_counter, envelope_stage, control_counter, panning, panned;
modulation_delay, modulation_counter, panning, panned;
}; };
/* Voice status options: */ /* Voice status options: */
#define VOICE_FREE 0 enum
#define VOICE_ON 1 {
#define VOICE_SUSTAINED 2 VOICE_FREE,
#define VOICE_OFF 3 VOICE_ON,
#define VOICE_DIE 4 VOICE_SUSTAINED,
VOICE_OFF,
VOICE_DIE
};
/* Voice panned options: */ /* Voice panned options: */
#define PANNED_MYSTERY 0 enum
#define PANNED_LEFT 1 {
#define PANNED_RIGHT 2 PANNED_MYSTERY,
#define PANNED_CENTER 3 PANNED_LEFT,
PANNED_RIGHT,
PANNED_CENTER
};
/* Anything but PANNED_MYSTERY only uses the left volume */ /* Anything but PANNED_MYSTERY only uses the left volume */
/* Envelope stages: */ /* Envelope stages: */
#define ATTACK 0 enum
#define HOLD 1 {
#define DECAY 2 ATTACK,
#define RELEASE 3 HOLD,
#define RELEASEB 4 DECAY,
#define RELEASEC 5 RELEASE,
#define DELAY 6 RELEASEB,
RELEASEC
};
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c)))) #define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
@ -498,9 +533,7 @@ tables.h
#define sine(x) (sin((2*PI/1024.0) * (x))) #define sine(x) (sin((2*PI/1024.0) * (x)))
#define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0))) #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 calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
#define XMAPMAX 800
/* /*
timidity.h timidity.h
@ -517,27 +550,16 @@ struct Renderer
{ {
float rate; float rate;
DLS_Data *patches; DLS_Data *patches;
InstrumentLayer *default_instrument; Instrument *default_instrument;
int default_program; int default_program;
bool fast_decay;
int resample_buffer_size; int resample_buffer_size;
sample_t *resample_buffer; sample_t *resample_buffer;
Channel channel[16]; Channel channel[16];
Voice voice[MAX_VOICES]; 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 control_ratio, amp_with_poly;
int drumchannels; int drumchannels;
int adjust_panning_immediately; int adjust_panning_immediately;
int voices; 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; int lost_notes, cut_notes;
Renderer(float sample_rate); Renderer(float sample_rate);
@ -558,10 +580,8 @@ struct Renderer
int convert_vibrato_rate(BYTE rate); int convert_vibrato_rate(BYTE rate);
void recompute_amp(Voice *v); void recompute_amp(Voice *v);
int vc_alloc(int not_this_voice); void kill_key_group(int voice);
void kill_others(int voice); float calculate_scaled_frequency(Sample *sample, int note);
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 start_note(int chan, int note, int vel, int voice); void start_note(int chan, int note, int vel, int voice);
void note_on(int chan, int note, int vel); void note_on(int chan, int note, int vel);
@ -579,7 +599,6 @@ struct Renderer
void reset_midi(); void reset_midi();
void select_sample(int voice, Instrument *instr, int vel); 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 recompute_freq(int voice);
void kill_note(int voice); void kill_note(int voice);

View file

@ -64,6 +64,7 @@ BYTE GoldColormap[256];
// [BC] New Skulltag colormaps. // [BC] New Skulltag colormaps.
BYTE RedColormap[256]; BYTE RedColormap[256];
BYTE GreenColormap[256]; BYTE GreenColormap[256];
BYTE DesaturateColormap[31][256];
static void FreeSpecialLights();; static void FreeSpecialLights();;
@ -433,6 +434,24 @@ void InitPalette ()
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
intensity>>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" extern "C"

View file

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

View file

@ -1157,216 +1157,6 @@ void DFrameBuffer::WipeCleanup()
wipe_Cleanup(); 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 // Texture precaching

View file

@ -372,15 +372,6 @@ public:
// Create a palette texture from a remap/palette table. // Create a palette texture from a remap/palette table.
virtual FNativePalette *CreatePalette(FRemapTable *remap); 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 // Precaches or unloads a texture
virtual void PrecacheTexture(FTexture *tex, int cache); virtual void PrecacheTexture(FTexture *tex, int cache);
@ -405,9 +396,6 @@ private:
DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; 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; extern FColorMatcher ColorMatcher;
@ -478,106 +466,5 @@ int CheckRatio (int width, int height);
extern const int BaseRatioSizes[5][4]; 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__ #endif // __V_VIDEO_H__

View file

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

View file

@ -124,7 +124,7 @@ class Actor extends Thinker
action native A_FLoopActiveSound(); action native A_FLoopActiveSound();
action native A_LoopActiveSound(); action native A_LoopActiveSound();
action native A_StopSound(); 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_StopSoundEx(coerce name slot);
action native A_SeekerMissile(eval int threshold, eval int turnmax); action native A_SeekerMissile(eval int threshold, eval int turnmax);
action native A_Jump(eval int chance, state label, ...); 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_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_ClearTarget();
action native A_JumpIfTargetInLOS (state label, optional eval float fov); action native A_JumpIfTargetInLOS (state label, optional eval float fov);
action native A_DamageMaster(int amount, optional name damagetype); action native A_DamageMaster(eval int amount, optional name damagetype);
action native A_DamageChildren(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_SelectWeapon(class<Weapon> whichweapon);
action native A_Punch(); action native A_Punch();
} }