diff --git a/gzdoom.vcproj b/gzdoom.vcproj
index 5eb13d45..23f24584 100644
--- a/gzdoom.vcproj
+++ b/gzdoom.vcproj
@@ -2654,6 +2654,14 @@
RelativePath=".\src\textures\automaptexture.cpp"
>
+
+
+
+
diff --git a/src/actor.h b/src/actor.h
index baf0bc4c..7dcc0bcc 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -605,6 +605,12 @@ public:
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
}
+ bool intersects(AActor *other) const
+ {
+ fixed_t blockdist = radius + other->radius;
+ return ( abs(x - other->x) < blockdist && abs(y - other->y) < blockdist);
+ }
+
// Calculate amount of missile damage
virtual int GetMissileDamage(int mask, int add);
diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp
index 94ed7787..a0e9e380 100644
--- a/src/g_doom/doom_sbar.cpp
+++ b/src/g_doom/doom_sbar.cpp
@@ -145,9 +145,9 @@ public:
player_t *oldplayer = CPlayer;
DBaseStatusBar::AttachToPlayer (player);
- if (oldplayer != CPlayer)
+ if (oldplayer != CPlayer || savegamerestore/*added for morphing*/)
{
- SetFace (&skins[CPlayer->userinfo.skin]);
+ SetFace (&skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin]);
}
if (multiplayer)
{
@@ -211,7 +211,7 @@ private:
void Unload ();
~FDoomStatusBarTexture ();
void SetPlayerRemap(FRemapTable *remap);
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
FTextureFormat GetFormat()
{
@@ -224,7 +224,7 @@ private:
FTexture *BaseTexture;
BYTE *Pixels;
- FRemapTable *STBFremap;
+ FRemapTable *STFBRemap;
}
StatusBarTex;
@@ -1044,7 +1044,7 @@ DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture ()
// now copy all the properties from the base texture
CopySize(BaseTexture);
Pixels = NULL;
- STBFremap = NULL;
+ STFBRemap = NULL;
}
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out)
@@ -1090,36 +1090,36 @@ void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL);
DrawToBar("STTPRCNT", 90, 3, NULL);
DrawToBar("STTPRCNT", 221, 3, NULL);
- if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL);
+ if (multiplayer) DrawToBar("STFBANY", 143, 1, STFBRemap? STFBRemap->Remap : NULL);
}
-int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
FTexture *tex;
- // rotate is never used here
- BaseTexture->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x, y);
+ // rotate and inf are never used here
+ BaseTexture->CopyTrueColorPixels(bmp, x, y);
if (!deathmatch)
{
tex = TexMan["STARMS"];
if (tex != NULL)
{
- tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+104, y);
+ tex->CopyTrueColorPixels(bmp, x+104, y);
}
}
tex = TexMan["STTPRCNT"];
if (tex != NULL)
{
- tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+90, y+3);
- tex->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x+221, y+3);
+ tex->CopyTrueColorPixels(bmp, x+90, y+3);
+ tex->CopyTrueColorPixels(bmp, x+221, y+3);
}
if (multiplayer)
{
tex = TexMan["STFBANY"];
if (tex != NULL)
{
- tex->CopyTrueColorTranslated(buffer, buf_pitch, buf_height, x+143, y+1, STBFremap);
+ tex->CopyTrueColorTranslated(bmp, x+143, y+1, 0, STFBRemap);
}
}
return -1;
@@ -1141,7 +1141,7 @@ void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap)
{
Unload();
KillNative();
- STBFremap = remap;
+ STFBRemap = remap;
}
DBaseStatusBar *CreateDoomStatusBar ()
diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp
index a165af79..86dfe3b5 100644
--- a/src/g_hexen/a_spike.cpp
+++ b/src/g_hexen/a_spike.cpp
@@ -5,6 +5,7 @@
#include "p_local.h"
#include "a_sharedglobal.h"
#include "s_sound.h"
+#include "m_bbox.h"
static FRandom pr_thrustraise ("ThrustRaise");
@@ -262,9 +263,14 @@ void A_ThrustBlock (AActor *actor)
void A_ThrustImpale (AActor *actor)
{
AActor *thing;
- FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
+ FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
+ if (!thing->intersects(actor))
+ {
+ continue;
+ }
+
if (!(thing->flags & MF_SHOOTABLE) )
continue;
diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp
index 4c89b8c5..4643bad3 100644
--- a/src/g_shared/a_artifacts.cpp
+++ b/src/g_shared/a_artifacts.cpp
@@ -535,6 +535,7 @@ void APowerStrength::InitEffect ()
void APowerStrength::Tick ()
{
// Strength counts up to diminish the fade.
+ assert(EffectTics < (INT_MAX - 1)); // I can't see a game lasting nearly two years, but...
EffectTics += 2;
Super::Tick();
}
@@ -998,6 +999,7 @@ void APowerFlight::Tick ()
// The Wings of Wrath only expire in multiplayer and non-hub games
if (!multiplayer && (level.flags & LEVEL_INFINITE_FLIGHT))
{
+ assert(EffectTics < INT_MAX); // I can't see a game lasting nearly two years, but...
EffectTics++;
}
diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp
index 348aafc9..d0fd94ac 100644
--- a/src/g_shared/a_morph.cpp
+++ b/src/g_shared/a_morph.cpp
@@ -206,6 +206,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
const PClass *exit_flash = player->MorphExitFlash;
+ bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON);
player->morphTics = 0;
player->MorphedPlayerClass = 0;
@@ -267,13 +268,32 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
{
player->ReadyWeapon = player->PendingWeapon = NULL;
}
- if (beastweap != NULL)
- { // You don't get to keep your morphed weapon.
- if (beastweap->SisterWeapon != NULL)
+ if (correctweapon)
+ { // Better "lose morphed weapon" semantics
+ const PClass *morphweapon = PClass::FindClass (mo->MorphWeapon);
+ if (morphweapon != NULL && morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
{
- beastweap->SisterWeapon->Destroy ();
+ AWeapon *OriginalMorphWeapon = static_cast(mo->FindInventory (morphweapon));
+ if ((OriginalMorphWeapon != NULL) && (OriginalMorphWeapon->GivenAsMorphWeapon))
+ { // You don't get to keep your morphed weapon.
+ if (OriginalMorphWeapon->SisterWeapon != NULL)
+ {
+ OriginalMorphWeapon->SisterWeapon->Destroy ();
+ }
+ OriginalMorphWeapon->Destroy ();
+ }
+ }
+ }
+ else // old behaviour (not really useful now)
+ { // Assumptions made here are no longer valid
+ if (beastweap != NULL)
+ { // You don't get to keep your morphed weapon.
+ if (beastweap->SisterWeapon != NULL)
+ {
+ beastweap->SisterWeapon->Destroy ();
+ }
+ beastweap->Destroy ();
}
- beastweap->Destroy ();
}
pmo->tracer = NULL;
pmo->Destroy ();
diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h
index 1beb7879..18cb1984 100644
--- a/src/g_shared/a_morph.h
+++ b/src/g_shared/a_morph.h
@@ -17,7 +17,8 @@ enum
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
- MORPH_WHENINVULNERABLE = 0x00000040 // Player can morph when invulnerable but ONLY if doing it to themselves
+ MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph when invulnerable but ONLY if doing it to themselves
+ MORPH_LOSEACTUALWEAPON = 0X00000080 // Player loses specified morph weapon only (not "whichever they have when unmorphing")
};
struct PClass;
diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h
index 50ecc569..03bb0a7a 100644
--- a/src/g_shared/a_pickups.h
+++ b/src/g_shared/a_pickups.h
@@ -221,6 +221,7 @@ public:
// In-inventory instance variables
TObjPtr Ammo1, Ammo2;
TObjPtr SisterWeapon;
+ bool GivenAsMorphWeapon;
bool bAltFire; // Set when this weapon's alternate fire is used.
diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp
index 8f35819f..3f392957 100644
--- a/src/g_shared/a_weapons.cpp
+++ b/src/g_shared/a_weapons.cpp
@@ -52,7 +52,7 @@ void AWeapon::Serialize (FArchive &arc)
<< ProjectileType << AltProjectileType
<< SelectionOrder
<< MoveCombatDist
- << Ammo1 << Ammo2 << SisterWeapon
+ << Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
<< bAltFire;
}
@@ -230,6 +230,7 @@ void AWeapon::AttachToOwner (AActor *other)
StatusBar->ReceivedWeapon (this);
}
}
+ GivenAsMorphWeapon = false; // will be set explicitly by morphing code
}
//===========================================================================
diff --git a/src/gl/gl_framebuffer.h b/src/gl/gl_framebuffer.h
index f12b1eda..fc515558 100644
--- a/src/gl/gl_framebuffer.h
+++ b/src/gl/gl_framebuffer.h
@@ -63,15 +63,6 @@ public:
void Dim (PalEntry color, float damount, int x1, int y1, int w, int h);
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false);
- // texture copy functions
- virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
- const BYTE * patch, int pix_width, int pix_height, int step_x, int step_y,
- int rotate, int ct);
-
- virtual void CopyPixelData(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
- const BYTE * patch, int pix_width, int pix_height,
- int step_x, int step_y, int rotate, PalEntry * palette);
-
void PrecacheTexture(FTexture *tex, bool cache);
// Create a native texture from a game texture.
@@ -81,13 +72,6 @@ public:
void RenderView (player_t* player);
void WriteSavePic (player_t *player, FILE *file, int width, int height);
-
- void SetTranslationInfo(int _cm, int _trans=-1337)
- {
- if (_cm != -1) cm = _cm;
- if (_trans != -1337) translation = _trans;
- }
-
bool WipeStartScreen(int type);
void WipeEndScreen();
bool WipeDo(int ticks);
@@ -96,8 +80,12 @@ public:
private:
PalEntry Flash;
+
+ // Texture creation info
int cm;
int translation;
+ bool iscomplex;
+
PalEntry SourcePalette[256];
BYTE *ScreenshotBuffer;
@@ -122,10 +110,5 @@ private:
};
-inline void SetTranslationInfo(int _cm, int _trans=-1337)
-{
- static_cast(screen)->SetTranslationInfo(_cm,_trans);
-}
-
#endif //__GL_FRAMEBUFFER
diff --git a/src/gl/gl_hirestex.cpp b/src/gl/gl_hirestex.cpp
index a84d3d65..f5dad979 100644
--- a/src/gl/gl_hirestex.cpp
+++ b/src/gl/gl_hirestex.cpp
@@ -329,7 +329,7 @@ int FGLTexture::CheckExternalFile(bool & hascolorkey)
// Checks for the presence of a hires texture replacement and loads it
//
//==========================================================================
-unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height)
+unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height, int cm)
{
if (HiresLump==-1)
{
@@ -350,8 +350,11 @@ unsigned char *FGLTexture::LoadHiresTexture(int *width, int *height)
unsigned char * buffer=new unsigned char[w*(h+1)*4];
memset(buffer, 0, w * (h+1) * 4);
+ FGLBitmap bmp(buffer, w*4, w, h);
+ bmp.SetTranslationInfo(cm);
+
- int trans = hirestexture->CopyTrueColorPixels(buffer, w<<2, h, 0, 0);
+ int trans = hirestexture->CopyTrueColorPixels(&bmp, 0, 0);
CheckTrans(buffer, w*h, trans);
if (bHasColorkey)
diff --git a/src/gl/gl_skydome.cpp b/src/gl/gl_skydome.cpp
index 53ec8fd7..fde28d2d 100644
--- a/src/gl/gl_skydome.cpp
+++ b/src/gl/gl_skydome.cpp
@@ -76,9 +76,9 @@ public:
if (faces[0]) return faces[0]->GetPixels();
return NULL;
}
- virtual int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y)
+ virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
- if (faces[0]) return faces[0]->CopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
+ if (faces[0]) return faces[0]->CopyTrueColorPixels(bmp, x, y, rotate, inf);
return 0;
}
bool UseBasePalette() { return false; } // not really but here it's not important.
diff --git a/src/gl/gl_texture.cpp b/src/gl/gl_texture.cpp
index 1224d5aa..15480eb4 100644
--- a/src/gl/gl_texture.cpp
+++ b/src/gl/gl_texture.cpp
@@ -48,6 +48,7 @@
#include "stats.h"
#include "templates.h"
#include "sc_man.h"
+#include "r_translate.h"
#include "gl/gl_struct.h"
#include "gl/gl_framebuffer.h"
@@ -94,8 +95,8 @@ EXTERN_CVAR(Bool, gl_render_precise)
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
-static char GlobalBrightmap[256];
static bool HasGlobalBrightmap;
+static FRemapTable GlobalBrightmap;
//===========================================================================
//
@@ -111,7 +112,13 @@ void gl_GenerateGlobalBrightmapFromColormap()
const unsigned char *cmapdata = (const unsigned char *)cmap.GetMem();
const unsigned char *paldata = (const unsigned char *)palette.GetMem();
- memset(GlobalBrightmap, 255, 256);
+ const int black = 0;
+ const int white = ColorMatcher.Pick(255,255,255);
+
+
+ GlobalBrightmap.MakeIdentity();
+ memset(GlobalBrightmap.Remap, white, 256);
+ for(int i=0;i<256;i++) GlobalBrightmap.Palette[i]=PalEntry(255,255,255);
for(int j=0;j<32;j++)
{
for(int i=0;i<256;i++)
@@ -120,38 +127,18 @@ void gl_GenerateGlobalBrightmapFromColormap()
// and Hexen.
if (cmapdata[i+j*256]!=i || (paldata[3*i]<10 && paldata[3*i+1]<10 && paldata[3*i+2]<10))
{
- GlobalBrightmap[i]=0;
+ GlobalBrightmap.Remap[i]=black;
+ GlobalBrightmap.Palette[i]=PalEntry(0,0,0);
}
}
}
for(int i=0;i<256;i++)
{
- HasGlobalBrightmap|=!!GlobalBrightmap[i];
+ HasGlobalBrightmap |= GlobalBrightmap.Remap[i] == black;
//if (GlobalBrightmap[i]) Printf("Marked color %d as fullbright\n",i);
}
}
-static const BYTE IcePalette[16][3] =
-{
- { 10, 8, 18 },
- { 15, 15, 26 },
- { 20, 16, 36 },
- { 30, 26, 46 },
- { 40, 36, 57 },
- { 50, 46, 67 },
- { 59, 57, 78 },
- { 69, 67, 88 },
- { 79, 77, 99 },
- { 89, 87,109 },
- { 99, 97,120 },
- { 109,107,130 },
- { 118,118,141 },
- { 128,128,151 },
- { 138,138,162 },
- { 148,148,172 }
-};
-
-
//===========================================================================
//
// multi-format pixel copy with colormap application
@@ -300,16 +287,16 @@ static CopyFunc copyfuncs[]={
// base palette because they wouldn't be used anyway.
//
//===========================================================================
-void OpenGLFrameBuffer::CopyPixelDataRGB(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
- const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
- int rotate, int ct)
+void FGLBitmap::CopyPixelDataRGB(int originx, int originy,
+ const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
+ int rotate, int ct, FCopyInfo *inf)
{
- if (ClipCopyPixelRect(texpitch>>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
+ if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
- buffer+=4*originx + texpitch*originy;
+ BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
for (int y=0;y>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
+ if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{
- buffer+=4*originx + texpitch*originy;
+ BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
// CM_SHADE is an alpha map with 0==transparent and 1==opaque
if (cm == CM_SHADE)
@@ -467,28 +453,6 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
penew[i]=0xffffffff; // If the palette contains transparent colors keep them.
}
}
- else if (cm == CM_BRIGHTMAP)
- {
- if (palette == GetPalette() && translation >= 0)
- {
- for(int i=0;i<256;i++)
- {
- if (GlobalBrightmap[i] && palette[i].a==0)
- {
- penew[i] = PalEntry(0,255,255,255);
- }
- else
- {
- penew[i] = PalEntry(255,0,0,0);
- }
- }
- }
- else
- {
- for(int i=0;i<256;i++)
- penew[i] = PalEntry(palette[i].a,0,0,0);
- }
- }
else
{
// apply any translation.
@@ -535,7 +499,7 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
// This can also handle full PNG translucency.
for (y=0;yGetPitch();
+ int buf_width = bmp->GetWidth();
+ int buf_height = bmp->GetHeight();
+
+ if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
{
- return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
+ return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
}
- unsigned long * in=new unsigned long[Width*Height];
+ FGLBitmap inb;
+
+ if (!inb.Create(Width, Height))
+ return false;
+
+ unsigned long * in = (unsigned long *)inb.GetPixels();
unsigned long * out;
bool direct;
- int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{
- out = (unsigned long*)buffer;
+ out = (unsigned long*)bmp->GetPixels();
direct=true;
}
else
@@ -595,9 +567,9 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
- int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
+ int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
- static unsigned long linebuffer[4096]; // that's the maximum texture size for most graphics cards!
+ static unsigned long linebuffer[256]; // anything larger will bring down performance so it is excluded above.
int timebase = r_FrameTime*23/28;
int xsize = Width;
int ysize = Height;
@@ -638,7 +610,7 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
if (xx<0) xx=0;
if (yy<0) yy=0;
- unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
+ unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
int linelen=MIN(Width, buf_width-xx);
int linecount=MIN(Height, buf_height-yy);
@@ -649,7 +621,6 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
}
delete [] out;
}
- delete [] in;
GenTime=r_FrameTime;
return ret;
}
@@ -663,23 +634,31 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
//
//===========================================================================
-int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_height, int xx, int yy, int rotate)
+int FWarp2Texture::CopyTrueColorPixels(FBitmap *bmp, int xx, int yy, int rotate, FCopyInfo *inf)
{
- if (gl_warp_shader || gl_glsl_renderer)
+ int buf_pitch = bmp->GetPitch();
+ int buf_width = bmp->GetWidth();
+ int buf_height = bmp->GetHeight();
+
+ if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
{
- return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
+ return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
}
- unsigned long * in=new unsigned long[Width*Height];
+ FGLBitmap inb;
+
+ if (!inb.Create(Width, Height))
+ return false;
+
+ unsigned long * in = (unsigned long *)inb.GetPixels();
unsigned long * out;
bool direct;
- int buf_width = buf_pitch>>2;
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
gltex->createWarped = true;
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
{
- out = (unsigned long*)buffer;
+ out = (unsigned long*)bmp->GetPixels();
direct=true;
}
else
@@ -690,7 +669,7 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
GenTime = r_FrameTime;
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
- int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
+ int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
int xsize = Width;
int ysize = Height;
@@ -721,22 +700,22 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
if (!direct)
{
- // Negative offsets cannot occur here.
+ // This can only happen for sprites so
+ // negative offsets cannot occur here.
if (xx<0) xx=0;
if (yy<0) yy=0;
- unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
+ unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
int linelen=MIN(Width, buf_width-xx);
int linecount=MIN(Height, buf_height-yy);
for(i=0;iCopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
+ SourcePic->CopyTrueColorTranslated(bmp, x, y, rotate, &GlobalBrightmap);
return 0;
}
@@ -1198,13 +1176,12 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
unsigned char * buffer;
intptr_t cm = _cm;
- SetTranslationInfo(cm, translation);
// Textures that are already scaled in the texture lump will not get replaced
// by hires textures
if (gl_texture_usehires && allowhires && scalex==1.f && scaley==1.f)
{
- buffer = LoadHiresTexture (&w, &h);
+ buffer = LoadHiresTexture (&w, &h, _cm);
if (buffer)
{
return buffer;
@@ -1214,14 +1191,32 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
w=Width;
h=Height;
+
buffer=new unsigned char[Width*(Height+1)*4];
memset(buffer, 0, Width * (Height+1) * 4);
- if (translation<=0)
+ FGLBitmap bmp(buffer, Width*4, Width, Height);
+ bmp.SetTranslationInfo(cm, translation);
+
+ if (tex->bComplex)
+ {
+ FBitmap imgCreate;
+
+ // The texture contains special processing so it must be composited using with the
+ // base bitmap class and then be converted as a whole.
+ if (imgCreate.Create(Width, Height))
+ {
+ memset(imgCreate.GetPixels(), 0, Width * Height * 4);
+ int trans =
+ tex->CopyTrueColorPixels(&imgCreate, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
+ bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), Width, Height, 4, Width*4, 0, CF_BGRA);
+ CheckTrans(buffer, w*h, trans);
+ }
+ }
+ else if (translation<=0)
{
int trans =
- tex->CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
- GetTopOffset() - tex->TopOffset);
+ tex->CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
CheckTrans(buffer, w*h, trans);
@@ -1231,8 +1226,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
// When using translations everything must be mapped to the base palette.
// Since FTexture's method is doing exactly that by calling GetPixels let's use that here
// to do all the dirty work for us. ;)
- tex->FTexture::CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
- GetTopOffset() - tex->TopOffset);
+ tex->FTexture::CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
}
return buffer;
diff --git a/src/gl/gl_texture.h b/src/gl/gl_texture.h
index b242086a..fa78cb9a 100644
--- a/src/gl/gl_texture.h
+++ b/src/gl/gl_texture.h
@@ -5,6 +5,7 @@
#include "gl/gltexture.h"
#include "r_data.h"
#include "i_system.h"
+#include "textures/bitmap.h"
EXTERN_CVAR(Bool, gl_precache)
EXTERN_CVAR(Bool, gl_brightmap_shader)
@@ -14,6 +15,31 @@ struct GL_RECT;
void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count);
void CopyColorsRGBA(unsigned char * pout, const unsigned char * pin, int cm, int count, int step);
+class FGLBitmap : public FBitmap
+{
+ int cm;
+ int translation;
+public:
+
+ FGLBitmap() {}
+ FGLBitmap(BYTE *buffer, int pitch, int width, int height)
+ : FBitmap(buffer, pitch, width, height)
+ {}
+
+ void SetTranslationInfo(int _cm, int _trans=-1337)
+ {
+ if (_cm != -1) cm = _cm;
+ if (_trans != -1337) translation = _trans;
+
+ }
+
+ virtual void CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth,
+ int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL);
+ virtual void CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight,
+ int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf = NULL);
+};
+
+
// Two intermediate classes which wrap the low level textures.
// These ones are returned by the Bind* functions to ensure
// that the coordinate functions aren't used without the texture
@@ -125,7 +151,7 @@ private:
static bool SmoothEdges(unsigned char * buffer,int w, int h, bool clampsides);
int CheckDDPK3();
int CheckExternalFile(bool & hascolorkey);
- unsigned char * LoadHiresTexture(int *width, int *height);
+ unsigned char * LoadHiresTexture(int *width, int *height, int cm);
void SetSize(int w, int h)
@@ -247,7 +273,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
- int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf);
bool UseBasePalette() { return false; }
protected:
diff --git a/src/oplsynth/fmopl.cpp b/src/oplsynth/fmopl.cpp
index f367e81c..99e7794e 100644
--- a/src/oplsynth/fmopl.cpp
+++ b/src/oplsynth/fmopl.cpp
@@ -215,7 +215,7 @@ typedef struct fm_opl_f {
UINT32 eg_cnt; /* global envelope generator counter */
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
UINT32 eg_timer_add; /* step of eg_timer */
- UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
+ UINT32 eg_timer_overflow; /* envelope generator timer overflows every 1 sample (on real chip) */
UINT32 fn_tab[1024]; /* fnumber->increment counter */
diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index 825a2a6a..14633e79 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -5339,7 +5339,21 @@ int DLevelScript::RunScript ()
static_cast(StatusBar)->SetMugShotState(FBehavior::StaticLookupString(STACK(1)));
}
break;
-
+
+ case PCD_CHECKPLAYERCAMERA:
+ {
+ int playernum = STACK(1);
+
+ if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL)
+ {
+ STACK(1) = -1;
+ }
+ else
+ {
+ STACK(1) = players[playernum].camera->tid;
+ }
+ }
+ break;
}
}
diff --git a/src/p_acs.h b/src/p_acs.h
index c97fa179..072d2ffb 100644
--- a/src/p_acs.h
+++ b/src/p_acs.h
@@ -550,6 +550,7 @@ public:
PCD_SETMUGSHOTSTATE,
PCD_THINGCOUNTSECTOR,
PCD_THINGCOUNTNAMESECTOR,
+ PCD_CHECKPLAYERCAMERA, // [TN]
PCODE_COMMAND_COUNT
};
diff --git a/src/p_local.h b/src/p_local.h
index 5893bf9f..788a01b6 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -283,14 +283,6 @@ public:
void Reset() { StartBlock(minx, miny); }
};
-class FRadiusThingsIterator : public FBlockThingsIterator
-{
- fixed_t X, Y, Radius;
-public:
- FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius);
- AActor *Next();
-};
-
class FPathTraverse
{
static TArray intercepts;
diff --git a/src/p_map.cpp b/src/p_map.cpp
index 61283f1f..a590abbd 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -254,7 +254,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
- FRadiusThingsIterator it2(x, y, thing->radius);
+ FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
AActor *th;
while ((th = it2.Next()))
@@ -266,6 +266,10 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
if (th == thing)
continue;
+ fixed_t blockdist = th->radius + tmf.thing->radius;
+ if ( abs(th->x - tmf.x) >= blockdist || abs(th->y - tmf.y) >= blockdist)
+ continue;
+
// [RH] Z-Check
// But not if not MF2_PASSMOBJ or MF3_DONTOVERLAP are set!
// Otherwise those things would get stuck inside each other.
@@ -326,7 +330,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
void P_PlayerStartStomp (AActor *actor)
{
AActor *th;
- FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
+ FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((th = it.Next()))
{
@@ -337,6 +341,9 @@ void P_PlayerStartStomp (AActor *actor)
if (th == actor || (th->player == actor->player && th->player != NULL))
continue;
+ if (!th->intersects(actor))
+ continue;
+
// only kill monsters and other players
if (th->player == NULL && !(th->flags3 & MF3_ISMONSTER))
continue;
@@ -672,7 +679,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
fixed_t topz;
bool solid;
int damage;
-
+
// don't clip against self
if (thing == tm.thing)
return true;
@@ -680,6 +687,10 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true; // can't hit thing
+ fixed_t blockdist = thing->radius + tm.thing->radius;
+ if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
+ return true;
+
tm.thing->BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
@@ -1025,6 +1036,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
tm.x = x;
tm.y = y;
+ tm.z = thing->z;
FBoundingBox box(x, y, thing->radius);
@@ -1097,7 +1109,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
tm.stepthing = NULL;
- FRadiusThingsIterator it2(x, y, thing->radius);
+ FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
AActor *th;
while ((th = it2.Next()))
{
@@ -1228,11 +1240,15 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj)
return true;
}
- FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
+ FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
AActor *thing;
while ((thing = it.Next()))
{
+ if (!thing->intersects(actor))
+ {
+ continue;
+ }
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;
@@ -3659,7 +3675,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
float bombdamagefloat = (float)bombdamage;
FVector3 bombvec(FIXED2FLOAT(bombspot->x), FIXED2FLOAT(bombspot->y), FIXED2FLOAT(bombspot->z));
- FRadiusThingsIterator it(bombspot->x, bombspot->y, bombdistance<x, bombspot->y, bombdistance<x, actor->y, actor->radius);
+ FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
+ if (!thing->intersects(actor))
+ {
+ continue;
+ }
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;
@@ -3932,9 +3952,13 @@ void P_FindBelowIntersectors (AActor *actor)
return;
AActor *thing;
- FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
+ FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
while ((thing = it.Next()))
{
+ if (!thing->intersects(actor))
+ {
+ continue;
+ }
if (!(thing->flags & MF_SOLID))
{ // Can't hit thing
continue;
diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp
index 81c7ba02..f860a891 100644
--- a/src/p_maputl.cpp
+++ b/src/p_maputl.cpp
@@ -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
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 6f102dad..e74a25f0 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -1056,6 +1056,10 @@ void APlayerPawn::ActivateMorphWeapon ()
if (player->ReadyWeapon == NULL)
{
player->ReadyWeapon = static_cast(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)
{
diff --git a/src/r_data.h b/src/r_data.h
index a8d97f03..b2153e59 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -94,7 +94,7 @@ public:
void Unload ();
virtual void SetFrontSkyLayer ();
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
int GetSourceLump() { return DefinitionLump; }
protected:
@@ -107,10 +107,11 @@ protected:
SWORD OriginX, OriginY;
BYTE Rotate;
bool textureOwned;
+ FRemapTable *Translation;
+ PalEntry Blend;
FTexture *Texture;
TexPart();
- ~TexPart();
};
int NumParts;
@@ -261,7 +262,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
FTextureFormat GetFormat ();
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@@ -329,7 +330,7 @@ protected:
void DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
void DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
friend class FTexture;
@@ -345,7 +346,7 @@ public:
const BYTE *GetPixels ();
void Unload ();
FTextureFormat GetFormat ();
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@@ -397,7 +398,7 @@ public:
void Unload ();
FTextureFormat GetFormat ();
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@@ -454,7 +455,7 @@ public:
void Unload ();
FTextureFormat GetFormat ();
- int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette();
int GetSourceLump() { return SourceLump; }
@@ -492,7 +493,7 @@ public:
bool CheckModified ();
// [OpenGL]
- int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette() { return false; }
int GetSourceLump() { return SourcePic->GetSourceLump(); }
@@ -512,7 +513,7 @@ public:
FWarp2Texture (FTexture *source);
// [OpenGL]
- int CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y, int rotate);
+ int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
bool UseBasePalette() { return false; }
protected:
diff --git a/src/r_defs.h b/src/r_defs.h
index c11f1c33..4f28b2f3 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -87,6 +87,8 @@ struct line_t;
class player_s;
class FScanner;
+class FBitmap;
+struct FCopyInfo;
//
// The SECTORS record, at runtime.
@@ -824,8 +826,8 @@ public:
// Returns the whole texture, stored in column-major order
virtual const BYTE *GetPixels () = 0;
- virtual int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate=0);
- int CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap);
+ virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL);
+ int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap);
virtual bool UseBasePalette();
virtual int GetSourceLump() { return -1; }
diff --git a/src/r_translate.cpp b/src/r_translate.cpp
index 4c6f9771..153f0e81 100644
--- a/src/r_translate.cpp
+++ b/src/r_translate.cpp
@@ -46,6 +46,26 @@
TAutoGrowArray translationtables[NUM_TRANSLATION_TABLES];
+const BYTE IcePalette[16][3] =
+{
+ { 10, 8, 18 },
+ { 15, 15, 26 },
+ { 20, 16, 36 },
+ { 30, 26, 46 },
+ { 40, 36, 57 },
+ { 50, 46, 67 },
+ { 59, 57, 78 },
+ { 69, 67, 88 },
+ { 79, 77, 99 },
+ { 89, 87,109 },
+ { 99, 97,120 },
+ { 109,107,130 },
+ { 118,118,141 },
+ { 128,128,151 },
+ { 138,138,162 },
+ { 148,148,172 }
+};
+
/****************************************************/
/****************************************************/
@@ -428,25 +448,6 @@ void R_InitTranslationTables ()
// Doom palette has no good substitutes for these bluish-tinted grays, so
// they will just look gray unless you use a different PLAYPAL with Doom.
- static const BYTE IcePalette[16][3] =
- {
- { 10, 8, 18 },
- { 15, 15, 26 },
- { 20, 16, 36 },
- { 30, 26, 46 },
- { 40, 36, 57 },
- { 50, 46, 67 },
- { 59, 57, 78 },
- { 69, 67, 88 },
- { 79, 77, 99 },
- { 89, 87,109 },
- { 99, 97,120 },
- { 109,107,130 },
- { 118,118,141 },
- { 128,128,151 },
- { 138,138,162 },
- { 148,148,172 }
- };
BYTE IcePaletteRemap[16];
for (i = 0; i < 16; ++i)
{
diff --git a/src/r_translate.h b/src/r_translate.h
index 3b25db75..84e481b0 100644
--- a/src/r_translate.h
+++ b/src/r_translate.h
@@ -97,6 +97,8 @@ void R_DeinitTranslationTables();
// [RH] Actually create a player's translation table.
void R_BuildPlayerTranslation (int player);
+extern const BYTE IcePalette[16][3];
+
#endif // __R_TRANSLATE_H
diff --git a/src/sound/fmod_wrap.h b/src/sound/fmod_wrap.h
index 7bda4bbb..1c7592df 100644
--- a/src/sound/fmod_wrap.h
+++ b/src/sound/fmod_wrap.h
@@ -18,6 +18,7 @@ struct FMOD_CHANNELGROUP {};
struct FMOD_SOUNDGROUP {};
struct FMOD_REVERB {};
struct FMOD_DSP {};
+struct FMOD_DSPCONNECTION {};
struct FMOD_POLYGON {};
struct FMOD_GEOMETRY {};
struct FMOD_SYNCPOINT {};
@@ -39,6 +40,7 @@ namespace FMOD
class SoundGroup;
class Reverb;
class DSP;
+ class DSPConnection;
class Geometry;
/*
@@ -159,7 +161,7 @@ namespace FMOD
// System level DSP access.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_System_GetDSPHead(this, (FMOD_DSP **)dsp); }
- FMOD_RESULT addDSP (DSP *dsp) { return FMOD_System_AddDSP(this, (FMOD_DSP *)dsp); }
+ FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_System_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION**)dsp); }
FMOD_RESULT lockDSP () { return FMOD_System_LockDSP(this); }
FMOD_RESULT unlockDSP () { return FMOD_System_UnlockDSP(this); }
@@ -277,8 +279,8 @@ namespace FMOD
FMOD_RESULT getFrequency (float *frequency) { return FMOD_Channel_GetFrequency(this, frequency); }
FMOD_RESULT setPan (float pan) { return FMOD_Channel_SetPan(this, pan); }
FMOD_RESULT getPan (float *pan) { return FMOD_Channel_GetPan(this, pan); }
- FMOD_RESULT setDelay (unsigned int startdelay, unsigned int enddelay) { return FMOD_Channel_SetDelay(this, startdelay, enddelay); }
- FMOD_RESULT getDelay (unsigned int *startdelay, unsigned int *enddelay) { return FMOD_Channel_GetDelay(this, startdelay, enddelay); }
+ FMOD_RESULT setDelay (FMOD_DELAYTYPE delaytype, unsigned int delayhi, unsigned int delaylo) { return FMOD_Channel_SetDelay(this, delaytype, delaylo, delayhi); }
+ FMOD_RESULT getDelay (FMOD_DELAYTYPE delaytype, unsigned int *delayhi, unsigned int *delaylo) { return FMOD_Channel_GetDelay(this, delaytype, delaylo, delayhi); }
FMOD_RESULT setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright) { return FMOD_Channel_SetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); }
FMOD_RESULT getSpeakerMix (float *frontleft, float *frontright, float *center, float *lfe, float *backleft, float *backright, float *sideleft, float *sideright) { return FMOD_Channel_GetSpeakerMix(this, frontleft, frontright, center, lfe, backleft, backright, sideleft, sideright); }
FMOD_RESULT setSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_Channel_SetSpeakerLevels(this, speaker, levels, numlevels); }
@@ -320,7 +322,7 @@ namespace FMOD
// DSP functionality only for channels playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_Channel_GetDSPHead(this, (FMOD_DSP **)dsp); }
- FMOD_RESULT addDSP (DSP *dsp) { return FMOD_Channel_AddDSP(this, (FMOD_DSP *)dsp); }
+ FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_Channel_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); }
// Information only functions.
FMOD_RESULT isPlaying (bool *isplaying) { FMOD_BOOL b; FMOD_RESULT res = FMOD_Channel_IsPlaying(this, &b); *isplaying = b; return res; }
@@ -387,7 +389,7 @@ namespace FMOD
// DSP functionality only for channel groups playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT getDSPHead (DSP **dsp) { return FMOD_ChannelGroup_GetDSPHead(this, (FMOD_DSP **)dsp); }
- FMOD_RESULT addDSP (DSP *dsp) { return FMOD_ChannelGroup_AddDSP(this, (FMOD_DSP *)dsp); }
+ FMOD_RESULT addDSP (DSP *dsp, DSPConnection **connection) { return FMOD_ChannelGroup_AddDSP(this, (FMOD_DSP *)dsp, (FMOD_DSPCONNECTION **)connection); }
// Information only functions.
FMOD_RESULT getName (char *name, int namelen) { return FMOD_ChannelGroup_GetName(this, name, namelen); }
@@ -452,22 +454,14 @@ namespace FMOD
FMOD_RESULT getSystemObject (System **system) { return FMOD_DSP_GetSystemObject(this, (FMOD_SYSTEM **)system); }
// Connection / disconnection / input and output enumeration.
- FMOD_RESULT addInput (DSP *target) { return FMOD_DSP_AddInput(this, target); }
+ FMOD_RESULT addInput (DSP *target, DSPConnection **connection) { return FMOD_DSP_AddInput(this, target, (FMOD_DSPCONNECTION **)connection); }
FMOD_RESULT disconnectFrom (DSP *target) { return FMOD_DSP_DisconnectFrom(this, target); }
FMOD_RESULT disconnectAll (bool inputs, bool outputs) { return FMOD_DSP_DisconnectAll(this, inputs, outputs); }
FMOD_RESULT remove () { return FMOD_DSP_Remove(this); }
FMOD_RESULT getNumInputs (int *numinputs) { return FMOD_DSP_GetNumInputs(this, numinputs); }
FMOD_RESULT getNumOutputs (int *numoutputs) { return FMOD_DSP_GetNumOutputs(this, numoutputs); }
- FMOD_RESULT getInput (int index, DSP **input) { return FMOD_DSP_GetInput(this, index, (FMOD_DSP **)input); }
- FMOD_RESULT getOutput (int index, DSP **output) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output); }
- FMOD_RESULT setInputMix (int index, float volume) { return FMOD_DSP_SetInputMix(this, index, volume); }
- FMOD_RESULT getInputMix (int index, float *volume) { return FMOD_DSP_GetInputMix(this, index, volume); }
- FMOD_RESULT setInputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_SetInputLevels(this, index, speaker, levels, numlevels); }
- FMOD_RESULT getInputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_GetInputLevels(this, index, speaker, levels, numlevels); }
- FMOD_RESULT setOutputMix (int index, float volume) { return FMOD_DSP_SetOutputMix(this, index, volume); }
- FMOD_RESULT getOutputMix (int index, float *volume) { return FMOD_DSP_GetOutputMix(this, index, volume); }
- FMOD_RESULT setOutputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_SetOutputLevels(this, index, speaker, levels, numlevels); }
- FMOD_RESULT getOutputLevels (int index, FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSP_GetOutputLevels(this, index, speaker, levels, numlevels); }
+ FMOD_RESULT getInput (int index, DSP **input, DSPConnection **inputconnection) { return FMOD_DSP_GetInput(this, index, (FMOD_DSP **)input, (FMOD_DSPCONNECTION **)inputconnection); }
+ FMOD_RESULT getOutput (int index, DSP **output, DSPConnection **outputconnection) { return FMOD_DSP_GetOutput(this, index, (FMOD_DSP **)output, (FMOD_DSPCONNECTION **)outputconnection); }
// DSP unit control.
FMOD_RESULT setActive (bool active) { return FMOD_DSP_SetActive(this, active); }
@@ -488,13 +482,38 @@ namespace FMOD
FMOD_RESULT getType (FMOD_DSP_TYPE *type) { return FMOD_DSP_GetType(this, type); }
FMOD_RESULT setDefaults (float frequency, float volume, float pan, int priority) { return FMOD_DSP_SetDefaults(this, frequency, volume, pan, priority); }
FMOD_RESULT getDefaults (float *frequency, float *volume, float *pan, int *priority) { return FMOD_DSP_GetDefaults(this, frequency, volume, pan, priority) ;}
-
+
// Userdata set/get.
FMOD_RESULT setUserData (void *userdata) { return FMOD_DSP_SetUserData(this, userdata); }
FMOD_RESULT getUserData (void **userdata) { return FMOD_DSP_GetUserData(this, userdata); }
};
+ /*
+ 'DSPConnection' API
+ */
+ class DSPConnection : FMOD_DSPCONNECTION
+ {
+ private:
+
+ DSPConnection(); /* Constructor made private so user cannot statically instance a DSPConnection class.
+ Appropriate DSPConnection creation or retrieval function must be used. */
+
+ public:
+
+ FMOD_RESULT F_API getInput (DSP **input) { return FMOD_DSPConnection_GetInput(this, (FMOD_DSP **)input); }
+ FMOD_RESULT F_API getOutput (DSP **output) { return FMOD_DSPConnection_GetOutput(this, (FMOD_DSP **)output); }
+ FMOD_RESULT F_API setMix (float volume) { return FMOD_DSPConnection_SetMix(this, volume); }
+ FMOD_RESULT F_API getMix (float *volume) { return FMOD_DSPConnection_GetMix(this, volume); }
+ FMOD_RESULT F_API setLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_SetLevels(this, speaker, levels, numlevels); }
+ FMOD_RESULT F_API getLevels (FMOD_SPEAKER speaker, float *levels, int numlevels) { return FMOD_DSPConnection_GetLevels(this, speaker, levels, numlevels); }
+
+ // Userdata set/get.
+ FMOD_RESULT F_API setUserData (void *userdata) { return FMOD_DSPConnection_SetUserData(this, userdata); }
+ FMOD_RESULT F_API getUserData (void **userdata) { return FMOD_DSPConnection_GetUserData(this, userdata); }
+ };
+
+
/*
'Geometry' API
*/
diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp
index e1a1c1fe..2881bb82 100644
--- a/src/sound/fmodsound.cpp
+++ b/src/sound/fmodsound.cpp
@@ -70,8 +70,6 @@ extern HWND Window;
#define MAX_CHANNELS 256
-#define ERRCHECK(x)
-
#define SPECTRUM_SIZE 256
@@ -262,7 +260,7 @@ static const char *Enum_NameForNum(const FEnumList *list, int num)
//==========================================================================
//
-// The container for a FSOUND_STREAM.
+// The container for a streaming FMOD::Sound, for playing music.
//
//==========================================================================
@@ -270,15 +268,15 @@ class FMODStreamCapsule : public SoundStream
{
public:
FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner)
- : Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL),
- UserData(NULL), Callback(NULL)
+ : Owner(owner), Stream(NULL), Channel(NULL),
+ UserData(NULL), Callback(NULL), Ended(false)
{
SetStream(stream);
}
FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner)
- : Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL),
- UserData(udata), Callback(callback)
+ : Owner(owner), Stream(NULL), Channel(NULL),
+ UserData(udata), Callback(callback), Ended(false)
{}
~FMODStreamCapsule()
@@ -333,11 +331,6 @@ public:
Channel->stop();
Channel = NULL;
}
- if (DSP != NULL)
- {
- DSP->release();
- DSP = NULL;
- }
}
bool SetPaused(bool paused)
@@ -411,20 +404,16 @@ public:
FMODStreamCapsule *self;
result = ((FMOD::Sound *)sound)->getUserData((void **)&self);
- if (result != FMOD_OK || self == NULL || self->Callback == NULL)
- {
- return FMOD_ERR_INVALID_PARAM;
- }
- if (self->Callback(self, data, datalen, self->UserData))
+ if (result != FMOD_OK || self == NULL || self->Callback == NULL || self->Ended)
{
+ // Contrary to the docs, this return value is completely ignored.
return FMOD_OK;
}
- else
+ if (!self->Callback(self, data, datalen, self->UserData))
{
- self->Channel->stop();
- // Contrary to the docs, this return value is completely ignored.
- return FMOD_ERR_INVALID_PARAM;
+ self->Ended = true;
}
+ return FMOD_OK;
}
static FMOD_RESULT F_CALLBACK PCMSetPosCallback(FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype)
@@ -438,9 +427,9 @@ private:
FMODSoundRenderer *Owner;
FMOD::Sound *Stream;
FMOD::Channel *Channel;
- FMOD::DSP *DSP;
void *UserData;
SoundStreamCallback Callback;
+ bool Ended;
};
//==========================================================================
@@ -490,18 +479,22 @@ bool FMODSoundRenderer::Init()
PrevEnvironment = DefaultEnvironments[0];
Printf("I_InitSound: Initializing FMOD\n");
- if (!ShowedBanner)
- {
- Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2007.\n");
- ShowedBanner = true;
- }
// Create a System object and initialize.
result = FMOD::System_Create(&Sys);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Sys = NULL;
+ Printf(TEXTCOLOR_ORANGE"Failed to create FMOD system object: Error %d\n", result);
+ return false;
+ }
result = Sys->getVersion(&version);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_ORANGE"Could not validate FMOD version: Error %d\n", result);
+ return false;
+ }
if (version < FMOD_VERSION)
{
@@ -512,6 +505,11 @@ bool FMODSoundRenderer::Init()
return false;
}
+ if (!ShowedBanner)
+ {
+ Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2008.\n");
+ ShowedBanner = true;
+ }
#ifdef _WIN32
if (OSPlatform == os_WinNT4)
{
@@ -554,7 +552,11 @@ bool FMODSoundRenderer::Init()
if (eval >= 0)
{
result = Sys->setOutput(FMOD_OUTPUTTYPE(eval));
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Setting output type '%s' failed. Using default instead. (Error %d)\n", *snd_output, result);
+ Sys->setOutput(FMOD_OUTPUTTYPE_AUTODETECT);
+ }
}
result = Sys->getNumDrivers(&driver);
@@ -562,7 +564,7 @@ bool FMODSoundRenderer::Init()
{
if (snd_driver >= driver)
{
- Printf (TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver);
+ Printf(TEXTCOLOR_BLUE"Driver %d does not exist. Using 0.\n", *snd_driver);
driver = 0;
}
else
@@ -573,7 +575,16 @@ bool FMODSoundRenderer::Init()
}
result = Sys->getDriver(&driver);
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result);
+ // Fill in some default to pretend it worked. (But as long as we specify a valid driver,
+ // can this call actually fail?)
+ Driver_Caps = 0;
+ Driver_MinFrequency = 4000;
+ Driver_MaxFrequency = 48000;
+ speakermode = FMOD_SPEAKERMODE_STEREO;
+ }
// Set the user selected speaker mode.
eval = Enum_NumForName(SpeakerModeNames, snd_speakermode);
@@ -581,8 +592,11 @@ bool FMODSoundRenderer::Init()
{
speakermode = FMOD_SPEAKERMODE(eval);
}
- result = Sys->setSpeakerMode(speakermode < 9000 ? speakermode : FMOD_SPEAKERMODE_STEREO);
- ERRCHECK(result);
+ result = Sys->setSpeakerMode(speakermode);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Could not set speaker mode to '%s'. (Error %d)\n", *snd_speakermode, result);
+ }
// Set software format
eval = Enum_NumForName(SoundFormatNames, snd_output_format);
@@ -599,13 +613,20 @@ bool FMODSoundRenderer::Init()
}
if (samplerate != snd_samplerate && snd_samplerate != 0)
{
- Printf(TEXTCOLOR_BLUE"Sample rate %d is unsupported. Trying %d\n", *snd_samplerate, samplerate);
+ Printf(TEXTCOLOR_BLUE"Sample rate %d is unsupported. Trying %d.\n", *snd_samplerate, samplerate);
}
result = Sys->setSoftwareFormat(samplerate, format, 0, 0, resampler);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Could not set mixing format. Defaults will be used. (Error %d)\n", result);
+ }
// Set software channels according to snd_channels
result = Sys->setSoftwareChannels(snd_channels + NUM_EXTRA_SOFTWARE_CHANNELS);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Failed to set the preferred number of channels. (Error %d)\n", result);
+ }
if (Driver_Caps & FMOD_CAPS_HARDWARE_EMULATED)
{ // The user has the 'Acceleration' slider set to off!
@@ -613,7 +634,6 @@ bool FMODSoundRenderer::Init()
Printf (TEXTCOLOR_BLUE"Warning: The sound acceleration slider has been set to off.\n");
Printf (TEXTCOLOR_BLUE"Please turn it back on if you want decent sound.\n");
result = Sys->setDSPBufferSize(1024, 10); // At 48khz, the latency between issuing an fmod command and hearing it will now be about 213ms.
- ERRCHECK(result);
}
else if (snd_buffersize != 0 || snd_buffercount != 0)
{
@@ -621,6 +641,14 @@ bool FMODSoundRenderer::Init()
int buffercount = snd_buffercount ? snd_buffercount : 4;
result = Sys->setDSPBufferSize(buffersize, buffercount);
}
+ else
+ {
+ result = FMOD_OK;
+ }
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE"Setting DSP buffer size failed. (Error %d)\n", result);
+ }
// Try to init
initflags = FMOD_INIT_NORMAL;
@@ -663,24 +691,43 @@ bool FMODSoundRenderer::Init()
}
if (result != FMOD_OK)
{ // Initializing FMOD failed. Cry cry.
- Printf (" System::init returned error code %d\n", result);
+ Printf(TEXTCOLOR_ORANGE" System::init returned error code %d\n", result);
return false;
}
// Create channel groups
result = Sys->createChannelGroup("Music", &MusicGroup);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_ORANGE" Could not create music channel group. (Error %d)\n", result);
+ return false;
+ }
result = Sys->createChannelGroup("SFX", &SfxGroup);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_ORANGE" Could not create sfx channel group. (Error %d)\n", result);
+ return false;
+ }
result = Sys->createChannelGroup("Pausable SFX", &PausableSfx);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_ORANGE" Could not create pausable sfx channel group. (Error %d)\n", result);
+ return false;
+ }
result = SfxGroup->addGroup(PausableSfx);
- ERRCHECK(result);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE" Could not create attach pausable sfx to sfx channel group. (Error %d)\n", result);
+ }
result = SPC_CreateCodec(Sys);
+ if (result != FMOD_OK)
+ {
+ Printf(TEXTCOLOR_BLUE" Could not register SPC codec. (Error %d)\n", result);
+ }
Sys->set3DSettings(0.5f, 96.f, 1.f);
Sys->set3DRolloffCallback(RolloffCallback);
@@ -729,6 +776,7 @@ void FMODSoundRenderer::Shutdown()
}
Sys->close();
+ Sys->release();
Sys = NULL;
}
}
diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp
index 3f9d454d..98b36a5e 100644
--- a/src/sound/music_midistream.cpp
+++ b/src/sound/music_midistream.cpp
@@ -655,11 +655,11 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
{
InitialPlayback = false;
// Send the full master volume SysEx message.
- events[0] = 0; // dwDeltaTime
- events[1] = 0; // dwStreamID
- events[2] = (MEVT_LONGMSG << 24) | 8; // dwEvent
- events[3] = 0x047f7ff0; // dwParms[0]
- events[4] = 0xf77f7f01; // dwParms[1]
+ events[0] = 0; // dwDeltaTime
+ events[1] = 0; // dwStreamID
+ events[2] = (MEVT_LONGMSG << 24) | 8; // dwEvent
+ events[3] = MAKE_ID(0xf0,0x7f,0x7f,0x04); // dwParms[0]
+ events[4] = MAKE_ID(0x01,0x7f,0x7f,0xf7); // dwParms[1]
events += 5;
DoInitialSetup();
}
diff --git a/src/sound/music_timidity_mididevice.cpp b/src/sound/music_timidity_mididevice.cpp
index abaf3b44..b138abdf 100644
--- a/src/sound/music_timidity_mididevice.cpp
+++ b/src/sound/music_timidity_mididevice.cpp
@@ -484,7 +484,7 @@ bool TimidityMIDIDevice::ServiceStream (void *buff, int numbytes)
memset(buff, 0, numbytes);
CritSec.Enter();
- while (numsamples > 0)
+ while (Events != NULL && numsamples > 0)
{
double ticky = NextTickIn;
int tick_in = int(NextTickIn);
diff --git a/src/svnrevision.h b/src/svnrevision.h
index 7c370aa0..a04a3878 100644
--- a/src/svnrevision.h
+++ b/src/svnrevision.h
@@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
-#define ZD_SVN_REVISION_STRING "912"
-#define ZD_SVN_REVISION_NUMBER 912
+#define ZD_SVN_REVISION_STRING "921"
+#define ZD_SVN_REVISION_NUMBER 921
diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp
index c0053a65..76ee6759 100644
--- a/src/textures/ddstexture.cpp
+++ b/src/textures/ddstexture.cpp
@@ -53,6 +53,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
+#include "bitmap.h"
// Since we want this to compile under Linux too, we need to define this
// stuff ourselves instead of including a DirectX header.
@@ -742,7 +743,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
//
//===========================================================================
-int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
FWadLump lump = Wads.OpenLumpNum (SourceLump);
@@ -768,7 +769,7 @@ int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
}
// All formats decompress to RGBA.
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA);
+ bmp->CopyPixelDataRGB(x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
delete [] TexBuffer;
return -1;
}
diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp
index 74028f2d..9c6f9ba9 100644
--- a/src/textures/jpegtexture.cpp
+++ b/src/textures/jpegtexture.cpp
@@ -39,6 +39,7 @@
#include "r_jpeg.h"
#include "w_wad.h"
#include "v_text.h"
+#include "bitmap.h"
void FLumpSourceMgr::InitSource (j_decompress_ptr cinfo)
{
@@ -332,7 +333,7 @@ void FJPEGTexture::MakeTexture ()
//
//===========================================================================
-int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
@@ -375,19 +376,19 @@ int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_heigh
switch (cinfo.out_color_space)
{
case JCS_RGB:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
- 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB);
+ bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
+ 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf);
break;
case JCS_GRAYSCALE:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
- 1, cinfo.output_width, rotate, pe);
+ bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height,
+ 1, cinfo.output_width, rotate, pe, inf);
break;
case JCS_CMYK:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
- 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK);
+ bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height,
+ 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf);
break;
default:
diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp
index fb7a1e4c..0d4fd02a 100644
--- a/src/textures/multipatchtexture.cpp
+++ b/src/textures/multipatchtexture.cpp
@@ -44,6 +44,8 @@
#include "sc_man.h"
#include "templates.h"
#include "vectors.h"
+#include "r_translate.h"
+#include "bitmap.h"
// On the Alpha, accessing the shorts directly if they aren't aligned on a
// 4-byte boundary causes unaligned access warnings. Why it does this at
@@ -177,6 +179,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
Unload ();
if (Parts != NULL)
{
+ for(int i=0; iRemap;
+
+ default:
+ if (blend.r >= BLEND_DESATURATE1 && blend.r <= BLEND_DESATURATE31)
+ {
+ return DesaturateColormap[blend - BLEND_DESATURATE1];
+ }
+ else
+ {
+ blendwork[0]=0;
+ if (blend.a == 255)
+ {
+ for(int i=1;i<256;i++)
+ {
+ int rr = (blend.r * GPalette.BaseColors[i].r) / 255;
+ int gg = (blend.g * GPalette.BaseColors[i].g) / 255;
+ int bb = (blend.b * GPalette.BaseColors[i].b) / 255;
+
+ blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
+ }
+ return blendwork;
+ }
+ else if (blend.a != 0)
+ {
+ for(int i=1;i<256;i++)
+ {
+ int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255;
+ int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255;
+ int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255;
+
+ blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
+ }
+ return blendwork;
+ }
+ }
+ }
+ return NULL;
+}
+
//==========================================================================
//
// FMultiPatchTexture :: MakeTexture
@@ -285,14 +356,20 @@ void FMultiPatchTexture::MakeTexture ()
// Add a little extra space at the end if the texture's height is not
// a power of 2, in case somebody accidentally makes it repeat vertically.
int numpix = Width * Height + (1 << HeightBits) - Height;
+ BYTE blendwork[256];
Pixels = new BYTE[numpix];
memset (Pixels, 0, numpix);
for (int i = 0; i < NumParts; ++i)
{
+ BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL;
+ if (Parts[i].Blend != BLEND_NONE)
+ {
+ trans = GetBlendMap(Parts[i].Blend, blendwork);
+ }
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
- Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate);
+ Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
}
}
@@ -304,14 +381,69 @@ void FMultiPatchTexture::MakeTexture ()
//
//===========================================================================
-int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
int retv = -1;
+ FCopyInfo info;
for(int i=0;iCopyTrueColorPixels(buffer, buf_pitch, buf_height,
- x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
+ int ret;
+
+ if (!Parts[i].Texture->bComplex || inf == NULL)
+ {
+ memset (&info, 0, sizeof (info));
+ if (Parts[i].Translation != NULL)
+ {
+ // Using a translation forces downconversion to the base palette
+ ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation);
+ }
+ else
+ {
+ PalEntry b = Parts[i].Blend;
+ if (b.a == 0 && b.r != BLEND_NONE)
+ {
+ info.blend = EBlend(b.r);
+ inf = &info;
+ }
+ else if (b.a != 0)
+ {
+ if (b.a == 255)
+ {
+ info.blendcolor[0] = b.r * FRACUNIT / 255;
+ info.blendcolor[1] = b.g * FRACUNIT / 255;
+ info.blendcolor[2] = b.b * FRACUNIT / 255;
+ info.blend = BLEND_MODULATE;
+ inf = &info;
+ }
+ else
+ {
+ info.blendcolor[3] = b.a * FRACUNIT / 255;
+ info.blendcolor[0] = b.r * (FRACUNIT-info.blendcolor[3]);
+ info.blendcolor[1] = b.g * (FRACUNIT-info.blendcolor[3]);
+ info.blendcolor[2] = b.b * (FRACUNIT-info.blendcolor[3]);
+
+ info.blend = BLEND_OVERLAY;
+ inf = &info;
+ }
+ }
+ ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, inf);
+ }
+ }
+ else
+ {
+ // If the patch is a texture with some kind of processing involved
+ // and being drawn with additional processing
+ // the copying must be done in 2 steps: First create a complete image of the patch
+ // including all processing and then copy from that intermediate image to the destination
+ FBitmap bmp1;
+ if (bmp1.Create(Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight()))
+ {
+ Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0);
+ bmp->CopyPixelDataRGB(x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(),
+ bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf);
+ }
+ }
if (ret > retv) retv = ret;
}
@@ -328,6 +460,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf
FTextureFormat FMultiPatchTexture::GetFormat()
{
+ if (bComplex) return TEX_RGB;
if (NumParts == 1) return Parts[0].Texture->GetFormat();
return UseBasePalette() ? TEX_Pal : TEX_RGB;
}
@@ -344,6 +477,7 @@ FTextureFormat FMultiPatchTexture::GetFormat()
bool FMultiPatchTexture::UseBasePalette()
{
+ if (bComplex) return false;
for(int i=0;iUseBasePalette()) return false;
@@ -490,18 +624,8 @@ FMultiPatchTexture::TexPart::TexPart()
Rotate = 0;
textureOwned = false;
Texture = NULL;
-}
-
-//==========================================================================
-//
-// FMultiPatchTexture :: TexPart :: TexPart
-//
-//==========================================================================
-
-FMultiPatchTexture::TexPart::~TexPart()
-{
- if (textureOwned && Texture != NULL) delete Texture;
- Texture = NULL;
+ Translation = NULL;
+ Blend = 0;
}
//==========================================================================
@@ -674,6 +798,17 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
}
+static bool Check(char *& range, char c)
+{
+ while (isspace(*range)) range++;
+ if (*range==c)
+ {
+ range++;
+ return true;
+ }
+ return false;
+}
+
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
{
FString patchname;
@@ -690,10 +825,20 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
part.textureOwned = true;
}
+ else if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./"))
+ {
+ int lumpnum = Wads.CheckNumForName(sc.String, ns_patches);
+ if (lumpnum >= 0)
+ {
+ part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
+ TexMan.AddTexture(part.Texture);
+ }
+ }
}
else
{
part.Texture = TexMan[texno];
+ bComplex |= part.Texture->bComplex;
}
if (part.Texture == NULL)
{
@@ -728,6 +873,113 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
}
part.Rotate = (sc.Number / 90) & 3;
}
+ else if (sc.Compare("Translation"))
+ {
+ bComplex = true;
+ if (part.Translation != NULL) delete part.Translation;
+ part.Translation = NULL;
+ part.Blend = 0;
+ static const char *maps[] = { "inverse", "gold", "red", "green", "ice", "desaturate", NULL };
+ sc.MustGetString();
+ int match = sc.MatchString(maps);
+ if (match >= 0)
+ {
+ part.Blend.r = 1 + match;
+ if (part.Blend.r == BLEND_DESATURATE1)
+ {
+ sc.MustGetStringName(",");
+ sc.MustGetNumber();
+ part.Blend.r += clamp(sc.Number-1, 0, 30);
+ }
+ }
+ else
+ {
+ sc.UnGet();
+ part.Translation = new FRemapTable;
+ part.Translation->MakeIdentity();
+ do
+ {
+ sc.MustGetString();
+
+ char *range = sc.String;
+ int start,end;
+
+ start=strtol(range, &range, 10);
+ if (!Check(range, ':')) return;
+ end=strtol(range, &range, 10);
+ if (!Check(range, '=')) return;
+ if (!Check(range, '['))
+ {
+ int pal1,pal2;
+
+ pal1=strtol(range, &range, 10);
+ if (!Check(range, ':')) return;
+ pal2=strtol(range, &range, 10);
+
+ part.Translation->AddIndexRange(start, end, pal1, pal2);
+ }
+ else
+ {
+ // translation using RGB values
+ int r1,g1,b1,r2,g2,b2;
+
+ r1=strtol(range, &range, 10);
+ if (!Check(range, ',')) return;
+ g1=strtol(range, &range, 10);
+ if (!Check(range, ',')) return;
+ b1=strtol(range, &range, 10);
+ if (!Check(range, ']')) return;
+ if (!Check(range, ':')) return;
+ if (!Check(range, '[')) return;
+ r2=strtol(range, &range, 10);
+ if (!Check(range, ',')) return;
+ g2=strtol(range, &range, 10);
+ if (!Check(range, ',')) return;
+ b2=strtol(range, &range, 10);
+ if (!Check(range, ']')) return;
+
+ part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
+ }
+ }
+ while (sc.CheckString(","));
+ }
+
+ }
+ else if (sc.Compare("Blend"))
+ {
+ bComplex = true;
+ if (part.Translation != NULL) delete part.Translation;
+ part.Translation = NULL;
+ part.Blend = 0;
+
+ if (!sc.CheckNumber())
+ {
+ sc.MustGetString();
+ part.Blend = V_GetColor(NULL, sc.String);
+ }
+ else
+ {
+ int r,g,b;
+
+ sc.MustGetNumber();
+ sc.MustGetStringName(",");
+ r = sc.Number;
+ sc.MustGetNumber();
+ sc.MustGetStringName(",");
+ g = sc.Number;
+ sc.MustGetNumber();
+ sc.MustGetStringName(",");
+ b = sc.Number;
+ part.Blend = MAKERGB(r, g, b);
+ }
+ if (sc.CheckString(","))
+ {
+ sc.MustGetFloat();
+ part.Blend.a = clamp(int(sc.Float*255), 1, 254);
+ }
+ else part.Blend.a = 255;
+ bComplex = true;
+ }
}
}
if (Mirror & 2)
@@ -790,7 +1042,9 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
{
TexPart part;
ParsePatch(sc, part);
- parts.Push(part);
+ if (part.Texture != NULL) parts.Push(part);
+ part.Texture = NULL;
+ part.Translation = NULL;
}
}
diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp
index 3239966c..cd248deb 100644
--- a/src/textures/pcxtexture.cpp
+++ b/src/textures/pcxtexture.cpp
@@ -39,6 +39,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
+#include "bitmap.h"
bool FPCXTexture::Check(FileReader & file)
@@ -418,7 +419,7 @@ void FPCXTexture::MakeTexture()
//
//===========================================================================
-int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
PCXHeader header;
@@ -472,14 +473,13 @@ int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
lump.Seek(sizeof(header), SEEK_SET);
ReadPCX8bits (Pixels, lump, &header);
}
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
+ bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf);
}
else
{
Pixels = new BYTE[Width*Height * 3];
- BYTE * row = buffer;
ReadPCX24bits (Pixels, lump, &header, 3);
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB);
+ bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB, inf);
}
delete [] Pixels;
return 0;
diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp
index 64550b69..8e36c89d 100644
--- a/src/textures/pngtexture.cpp
+++ b/src/textures/pngtexture.cpp
@@ -39,6 +39,7 @@
#include "w_wad.h"
#include "templates.h"
#include "m_png.h"
+#include "bitmap.h"
bool FPNGTexture::Check(FileReader & file)
@@ -490,7 +491,7 @@ void FPNGTexture::MakeTexture ()
//
//===========================================================================
-int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
// Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
PalEntry pe[256];
@@ -554,20 +555,20 @@ int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 0:
case 3:
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
+ bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf);
break;
case 2:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB);
+ bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB, inf);
break;
case 4:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA);
+ bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA, inf);
transpal = -1;
break;
case 6:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA);
+ bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA, inf);
transpal = -1;
break;
diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp
index 953a2a21..8bea144c 100644
--- a/src/textures/texture.cpp
+++ b/src/textures/texture.cpp
@@ -40,6 +40,7 @@
#include "templates.h"
#include "i_system.h"
#include "r_translate.h"
+#include "bitmap.h"
typedef bool (*CheckFunc)(FileReader & file);
typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum);
@@ -120,7 +121,7 @@ FTexture::FTexture ()
: LeftOffset(0), TopOffset(0),
WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT),
UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false),
- bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bIsPatch(false),
+ bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bIsPatch(false), bComplex(false),
Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL)
{
*Name = 0;
@@ -456,8 +457,11 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt)
break;
case TEX_RGB:
- CopyTrueColorPixels(buff, pitch, height, 0, 0);
+ {
+ FBitmap bmp(buff, pitch, pitch/4, height);
+ CopyTrueColorPixels(&bmp, 0, 0);
break;
+ }
default:
I_Error("FTexture::FillBuffer: Unsupported format %d", fmt);
@@ -476,25 +480,21 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt)
//
//===========================================================================
-int FTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry *palette = screen->GetPalette();
palette[0].a=255; // temporarily modify the first color's alpha
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
- GetPixels(), Width, Height, Height, 1,
- rotate, palette);
+ bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf);
palette[0].a=0;
return 0;
}
-int FTexture::CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap)
+int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap)
{
PalEntry *palette = remap->Palette;
palette[0].a=255; // temporarily modify the first color's alpha
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
- GetPixels(), Width, Height, Height, 1,
- 0, palette);
+ bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette);
palette[0].a=0;
return 0;
diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp
index 09d0b53f..cf544629 100644
--- a/src/textures/tgatexture.cpp
+++ b/src/textures/tgatexture.cpp
@@ -38,6 +38,7 @@
#include "r_local.h"
#include "w_wad.h"
#include "templates.h"
+#include "bitmap.h"
bool FTGATexture::Check(FileReader & data)
@@ -384,7 +385,7 @@ void FTGATexture::MakeTexture ()
//
//===========================================================================
-int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
+int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
PalEntry pe[256];
FWadLump lump = Wads.OpenLumpNum (SourceLump);
@@ -469,7 +470,7 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
switch (hdr.img_type & 7)
{
case 1: // paletted
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
+ bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf);
break;
case 2: // RGB
@@ -477,21 +478,21 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 15:
case 16:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555);
+ bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555, inf);
break;
case 24:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
+ bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf);
break;
case 32:
if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel
{
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
+ bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf);
}
else
{
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA);
+ bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA, inf);
transval = -1;
}
break;
@@ -506,11 +507,11 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{
case 8:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map
- screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
+ bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf);
break;
case 16:
- screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16);
+ bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16, inf);
break;
default:
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index e7435919..32462a47 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -313,7 +313,7 @@ void A_PlaySoundEx (AActor *self)
int soundid = StateParameters[index];
ENamedName channel = ENamedName(StateParameters[index + 1]);
- INTBOOL looping = StateParameters[index + 2];
+ INTBOOL looping = EvalExpressionI(StateParameters[index + 2], self);
int attenuation_raw = EvalExpressionI(StateParameters[index + 3], self);
int attenuation;
diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp
index 0496de60..1501edfa 100644
--- a/src/thingdef/thingdef_properties.cpp
+++ b/src/thingdef/thingdef_properties.cpp
@@ -754,11 +754,11 @@ static int ParseMorphStyle (FScanner &sc)
{
static const char * morphstyles[]={
"MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
- "MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", NULL};
+ "MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON", NULL};
static const int morphstyle_values[]={
MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
- MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE};
+ MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON};
// May be given flags by number...
if (sc.CheckNumber())
diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp
index ee5fdf86..247ce646 100644
--- a/src/timidity/instrum.cpp
+++ b/src/timidity/instrum.cpp
@@ -35,74 +35,48 @@
namespace Timidity
{
-extern InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
+extern Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument);
-/* Some functions get aggravated if not even the standard banks are
-available. */
-ToneBank standard_tonebank, standard_drumset;
-
-/* This is only used for tracks that don't specify a program */
-int default_program = DEFAULT_PROGRAM;
extern int openmode;
+Instrument::Instrument()
+: type(INST_GUS), samples(0), sample(NULL)
+{
+}
-static void free_instrument(Instrument *ip)
+Instrument::~Instrument()
{
Sample *sp;
int i;
- if (ip == NULL)
- {
- return;
- }
- for (i = 0, sp = &(ip->sample[0]); i < ip->samples; i++, sp++)
+
+ for (i = samples, sp = &(sample[0]); i != 0; i--, sp++)
{
if (sp->data != NULL)
{
free(sp->data);
}
}
- for (i = 0, sp = &(ip->right_sample[0]); i < ip->right_samples; i++)
- {
- if (sp->data != NULL)
- {
- free(sp->data);
- }
- }
- free(ip->sample);
- if (ip->right_sample != NULL)
- {
- free(ip->right_sample);
- }
- free(ip);
+ free(sample);
}
-
-static void free_layer(InstrumentLayer *lp)
+ToneBank::ToneBank()
{
- InstrumentLayer *next;
-
- for (; lp; lp = next)
+ tone = new ToneBankElement[128];;
+ for (int i = 0; i < MAXPROG; ++i)
{
- next = lp->next;
- free_instrument(lp->instrument);
- free(lp);
+ instrument[i] = 0;
}
}
-static void free_bank(int dr, int b)
+ToneBank::~ToneBank()
{
- int i;
- ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
- for (i = 0; i < MAXPROG; i++)
+ delete[] tone;
+ for (int i = 0; i < MAXPROG; i++)
{
- if (bank->tone[i].layer != NULL)
+ if (instrument[i] != NULL && instrument[i] != MAGIC_LOAD_INSTRUMENT)
{
- /* Not that this could ever happen, of course */
- if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT)
- {
- free_layer(bank->tone[i].layer);
- bank->tone[i].layer = NULL;
- }
+ delete instrument[i];
+ instrument[i] = NULL;
}
}
}
@@ -110,7 +84,6 @@ static void free_bank(int dr, int b)
int convert_envelope_rate(Renderer *song, BYTE rate)
{
-#if 1
int r;
r = 3 - ((rate>>6) & 0x3);
@@ -118,12 +91,7 @@ int convert_envelope_rate(Renderer *song, BYTE rate)
r = (int)(rate & 0x3f) << r; /* 6.9 fixed point */
/* 15.15 fixed point. */
- return int(((r * 44100) / song->rate) * song->control_ratio) << ((song->fast_decay) ? 10 : 9);
-#else
- double frameadd = (double)(rate & 63) / (double)(1 << (3 * (rate >> 6)));
- double realadd = (frameadd * 19293 / song->rate) * (1 << 15) * song->control_ratio;
- return (int)realadd;
-#endif
+ return int(((r * 44100) / song->rate) * song->control_ratio) << 9;
}
int convert_envelope_offset(BYTE offset)
@@ -137,7 +105,7 @@ int convert_envelope_offset(BYTE offset)
int convert_tremolo_sweep(Renderer *song, BYTE sweep)
{
- if (!sweep)
+ if (sweep == 0)
return 0;
return
@@ -146,7 +114,7 @@ int convert_tremolo_sweep(Renderer *song, BYTE sweep)
int convert_vibrato_sweep(Renderer *song, BYTE sweep, int vib_control_ratio)
{
- if (!sweep)
+ if (sweep == 0)
return 0;
return
@@ -186,30 +154,29 @@ static void reverse_data(sample_t *sp, int ls, int le)
}
/*
-If panning or note_to_use != -1, it will be used for all samples,
-instead of the sample-specific values in the instrument file.
+ If panning or note_to_use != -1, it will be used for all samples,
+ instead of the sample-specific values in the instrument file.
-For note_to_use, any value <0 or >127 will be forced to 0.
+ For note_to_use, any value <0 or >127 will be forced to 0.
-For other parameters, 1 means yes, 0 means no, other values are
-undefined.
+ For other parameters, 1 means yes, 0 means no, other values are
+ undefined.
-TODO: do reverse loops right */
-static InstrumentLayer *load_instrument(Renderer *song, const char *name, int font_type, int percussion,
- int panning, int amp, int cfg_tuning, int note_to_use,
- int strip_loop, int strip_envelope,
- int strip_tail, int bank, int gm_num, int sf_ix)
+ TODO: do reverse loops right */
+static Instrument *load_instrument(Renderer *song, const char *name, int percussion,
+ int panning, int amp, int note_to_use,
+ int strip_loop, int strip_envelope,
+ int strip_tail)
{
- InstrumentLayer *lp, *lastlp, *headlp;
Instrument *ip;
+ Sample *sp;
FileReader *fp;
- BYTE tmp[239];
- int i,j;
+ GF1PatchHeader header;
+ GF1InstrumentData idata;
+ GF1LayerData layer_data;
+ GF1PatchData patch_data;
+ int i, j;
bool noluck = false;
- bool sf2flag = false;
- int right_samples = 0;
- int stereo_channels = 1, stereo_layer;
- int vlayer_list[19][4], vlayer, vlayer_count;
if (!name) return 0;
@@ -233,518 +200,302 @@ static InstrumentLayer *load_instrument(Renderer *song, const char *name, int fo
if (noluck)
{
- cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.", name);
+ cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.\n", name);
return 0;
}
- /*cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
+ cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s\n", name);
- /* Read some headers and do cursory sanity checks. There are loads
- of magic offsets. This could be rewritten... */
+ /* Read some headers and do cursory sanity checks. */
- if ((239 != fp->Read(tmp, 239)) ||
- (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
- memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
- differences are */
+ if (sizeof(header) != fp->Read(&header, sizeof(header)))
{
- cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
+failread:
+ cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Error reading instrument.\n", name);
+ delete fp;
+ return 0;
+ }
+ if (strncmp(header.Header, GF1_HEADER_TEXT, HEADER_SIZE - 4) != 0)
+ {
+ cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not an instrument.\n", name);
+ delete fp;
+ return 0;
+ }
+ if (strcmp(header.Header + 8, "110") < 0)
+ {
+ cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Is an old and unsupported patch version.\n", name);
+ delete fp;
+ return 0;
+ }
+ if (sizeof(idata) != fp->Read(&idata, sizeof(idata)))
+ {
+ goto failread;
+ }
+
+ header.WaveForms = LittleShort(header.WaveForms);
+ header.MasterVolume = LittleShort(header.MasterVolume);
+ header.DataSize = LittleLong(header.DataSize);
+ idata.Instrument = LittleShort(idata.Instrument);
+
+ if (header.Instruments != 1 && header.Instruments != 0) /* instruments. To some patch makers, 0 means 1 */
+ {
+ cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments.\n", header.Instruments);
delete fp;
return 0;
}
- /* patch layout:
- * bytes: info: starts at offset:
- * 12 header (see above) 0
- * 10 Gravis ID 12
- * 60 description 22
- * 1 instruments 82
- * 1 voices 83
- * 1 channels 84
- * 2 number of waveforms 85
- * 2 master volume 87
- * 4 datasize 89
- * 36 reserved, but now: 93
- * 7 "SF2EXT\0" id 93
- * 1 right samples 100
- * 28 reserved 101
- * 2 instrument number 129
- * 16 instrument name 131
- * 4 instrument size 147
- * 1 number of layers 151
- * 40 reserved 152
- * 1 layer duplicate 192
- * 1 layer number 193
- * 4 layer size 194
- * 1 number of samples 198
- * 40 reserved 199
- * 239
- * THEN, for each sample, see below
- */
-
- vlayer_count = 0; // Silence, GCC
-
- if (!memcmp(tmp + 93, "SF2EXT", 6))
+ if (idata.Layers != 1 && idata.Layers != 0) /* layers. What's a layer? */
{
- sf2flag = true;
- vlayer_count = tmp[152];
- }
-
- if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 0 means 1 */
- {
- cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]);
+ cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers.\n", idata.Layers);
delete fp;
return 0;
}
- if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
+ if (sizeof(layer_data) != fp->Read(&layer_data, sizeof(layer_data)))
{
- cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]);
+ goto failread;
+ }
+
+ if (layer_data.Samples == 0)
+ {
+ cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument has 0 samples.\n");
delete fp;
return 0;
}
-
- if (sf2flag && vlayer_count > 0)
+ ip = new Instrument;
+ ip->samples = layer_data.Samples;
+ ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples);
+ memset(ip->sample, 0, sizeof(Sample) * layer_data.Samples);
+ ip->type = INST_GUS;
+ for (i = 0; i < layer_data.Samples; ++i)
{
- for (i = 0; i < 9; i++)
- for (j = 0; j < 4; j++)
- vlayer_list[i][j] = tmp[153+i*4+j];
- for (i = 9; i < 19; i++)
- for (j = 0; j < 4; j++)
- vlayer_list[i][j] = tmp[199+(i-9)*4+j];
- }
- else
- {
- for (i = 0; i < 19; i++)
- for (j = 0; j < 4; j++)
- vlayer_list[i][j] = 0;
- vlayer_list[0][0] = 0;
- vlayer_list[0][1] = 127;
- vlayer_list[0][2] = tmp[198];
- vlayer_list[0][3] = 0;
- vlayer_count = 1;
- }
-
- lastlp = NULL;
- headlp = NULL; // Silence, GCC
-
- for (vlayer = 0; vlayer < vlayer_count; vlayer++)
- {
- lp = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
- lp->lo = vlayer_list[vlayer][0];
- lp->hi = vlayer_list[vlayer][1];
- ip = (Instrument *)safe_malloc(sizeof(Instrument));
- lp->instrument = ip;
- lp->next = 0;
-
- if (lastlp != NULL)
+ if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data)))
{
- lastlp->next = lp;
- }
- else
- {
- headlp = lp;
- }
-
- lastlp = lp;
-
- ip->type = sf2flag ? INST_SF2 : INST_GUS;
- ip->samples = vlayer_list[vlayer][2];
- ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);
- ip->left_samples = ip->samples;
- ip->left_sample = ip->sample;
- right_samples = vlayer_list[vlayer][3];
- ip->right_samples = right_samples;
- if (right_samples)
- {
- ip->right_sample = (Sample *)safe_malloc(sizeof(Sample) * right_samples);
- stereo_channels = 2;
- }
- else
- {
- ip->right_sample = NULL;
- }
-
- cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",
- (percussion)? " ":"", name,
- (percussion)? note_to_use : gm_num, bank,
- (right_samples)? "(2) " : "",
- lp->lo, lp->hi, vlayer+1, vlayer_count);
-
- for (stereo_layer = 0; stereo_layer < stereo_channels; stereo_layer++)
- {
- int sample_count;
-
- if (stereo_layer == 0)
- {
- sample_count = ip->left_samples;
- }
- else if (stereo_layer == 1)
- {
- sample_count = ip->right_samples;
- }
- else
- {
- sample_count = 0;
- }
-
- for (i = 0; i < sample_count; i++)
- {
- BYTE fractions;
- int tmplong;
- WORD tmpshort;
- WORD sample_volume;
- BYTE tmpchar;
- Sample *sp;
- BYTE sf2delay;
-
-#define READ_CHAR(thing) \
- if (1 != fp->Read(&tmpchar,1)) goto fail; \
- thing = tmpchar;
-#define READ_SHORT(thing) \
- if (2 != fp->Read(&tmpshort, 2)) goto fail; \
- thing = LittleShort(tmpshort);
-#define READ_LONG(thing) \
- if (4 != fp->Read(&tmplong, 4)) goto fail; \
- thing = LittleLong(tmplong);
-
- /*
- * 7 sample name
- * 1 fractions
- * 4 length
- * 4 loop start
- * 4 loop end
- * 2 sample rate
- * 4 low frequency
- * 4 high frequency
- * 4 root frequency
- * 2 finetune
- * 1 panning
- * 6 envelope rates |
- * 6 envelope offsets | 18 bytes
- * 3 tremolo sweep, rate, depth |
- * 3 vibrato sweep, rate, depth |
- * 1 sample mode
- * 2 scale frequency
- * 2 scale factor | from 0 to 2048 or 0 to 2
- * 2 sample volume (??)
- * 34 reserved
- * Now: 1 delay
- * 33 reserved
- */
- fp->Seek(7, SEEK_CUR);
-
- if (1 != fp->Read(&fractions, 1))
- {
fail:
- cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
- if (stereo_layer == 1)
- {
- for (j = 0; j < i; j++)
- {
- free(ip->right_sample[j].data);
- }
- free(ip->right_sample);
- i = ip->left_samples;
- }
- for (j = 0; j < i; j++)
- {
- free(ip->left_sample[j].data);
- }
- free(ip->left_sample);
- free(ip);
- free(lp);
- delete fp;
- return 0;
- }
+ cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d.\n", i);
+ delete ip;
+ delete fp;
+ return 0;
+ }
- if (stereo_layer == 0)
- {
- sp = &(ip->left_sample[i]);
- }
- else if (stereo_layer == 1)
- {
- sp = &(ip->right_sample[i]);
- }
- else
- {
- assert(0);
- sp = NULL;
- }
+ sp = &(ip->sample[i]);
- READ_LONG(sp->data_length);
- READ_LONG(sp->loop_start);
- READ_LONG(sp->loop_end);
- READ_SHORT(sp->sample_rate);
- READ_LONG(sp->low_freq);
- READ_LONG(sp->high_freq);
- READ_LONG(sp->root_freq);
- fp->Seek(2, SEEK_CUR); /* Unused by GUS: Why have a "root frequency" and then "tuning"?? */
- sp->low_vel = 0;
- sp->high_vel = 127;
+ sp->data_length = LittleLong(patch_data.WaveSize);
+ sp->loop_start = LittleLong(patch_data.StartLoop);
+ sp->loop_end = LittleLong(patch_data.EndLoop);
+ sp->sample_rate = LittleShort(patch_data.SampleRate);
+ sp->low_freq = LittleLong(patch_data.LowFrequency);
+ sp->high_freq = LittleLong(patch_data.HighFrequency);
+ sp->root_freq = LittleLong(patch_data.RootFrequency);
+ sp->high_vel = 127;
- READ_CHAR(tmp[0]);
+ if (panning == -1)
+ {
+ sp->panning = patch_data.Balance & 0x0F;
+ sp->panning = (sp->panning << 3) | (sp->panning >> 1);
+ }
+ else
+ {
+ sp->panning = panning & 0x7f;
+ }
+ sp->panning |= sp->panning << 7;
- if (panning == -1)
- sp->panning = (tmp[0] * 8 + 4) & 0x7f;
- else
- sp->panning = (BYTE)(panning & 0x7F);
- sp->panning |= sp->panning << 7;
+ /* tremolo */
+ if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 0)
+ {
+ sp->tremolo_sweep_increment = 0;
+ sp->tremolo_phase_increment = 0;
+ sp->tremolo_depth = 0;
+ cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo\n");
+ }
+ else
+ {
+ sp->tremolo_sweep_increment = convert_tremolo_sweep(song, patch_data.TremoloSweep);
+ sp->tremolo_phase_increment = convert_tremolo_rate(song, patch_data.TremoloRate);
+ sp->tremolo_depth = patch_data.TremoloDepth;
+ cmsg(CMSG_INFO, VERB_DEBUG, " * tremolo: sweep %d, phase %d, depth %d\n",
+ sp->tremolo_sweep_increment, sp->tremolo_phase_increment, sp->tremolo_depth);
+ }
- sp->resonance = 0;
- sp->cutoff_freq = 0;
- sp->reverberation = 0;
- sp->chorusdepth = 0;
- sp->exclusiveClass = 0;
- sp->keyToModEnvHold = 0;
- sp->keyToModEnvDecay = 0;
- sp->keyToVolEnvHold = 0;
- sp->keyToVolEnvDecay = 0;
+ /* vibrato */
+ if (patch_data.VibratoRate == 0 || patch_data.VibratoDepth == 0)
+ {
+ sp->tremolo_sweep_increment = 0;
+ sp->vibrato_control_ratio = 0;
+ sp->vibrato_depth = 0;
+ cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato\n");
+ }
+ else
+ {
+ sp->vibrato_control_ratio = convert_vibrato_rate(song, patch_data.VibratoRate);
+ sp->tremolo_sweep_increment = convert_vibrato_sweep(song, patch_data.VibratoSweep, sp->vibrato_control_ratio);
+ sp->vibrato_depth = patch_data.VibratoDepth;
+ cmsg(CMSG_INFO, VERB_DEBUG, " * vibrato: sweep %d, ctl %d, depth %d\n",
+ sp->vibrato_sweep_increment, sp->vibrato_control_ratio, sp->vibrato_depth);
+ }
- if (cfg_tuning)
- {
- double tune_factor = (double)(cfg_tuning) / 1200.0;
- tune_factor = pow(2.0, tune_factor);
- sp->root_freq = (uint32)( tune_factor * (double)sp->root_freq );
- }
+ sp->modes = patch_data.Modes;
- /* envelope, tremolo, and vibrato */
- if (18 != fp->Read(tmp, 18)) goto fail;
+ /* Mark this as a fixed-pitch instrument if such a deed is desired. */
+ if (note_to_use != -1)
+ {
+ sp->scale_note = note_to_use;
+ sp->scale_factor = 0;
+ }
+ else
+ {
+ sp->scale_note = LittleShort(patch_data.ScaleFrequency);
+ sp->scale_factor = LittleShort(patch_data.ScaleFactor);
+ if (sp->scale_factor != 1024)
+ {
+ cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n",
+ sp->scale_note, sp->scale_factor);
+ }
+ }
- if (!tmp[13] || !tmp[14])
- {
- sp->tremolo_sweep_increment = 0;
- sp->tremolo_phase_increment = 0;
- sp->tremolo_depth = 0;
- cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
- }
- else
- {
- sp->tremolo_sweep_increment = convert_tremolo_sweep(song, tmp[12]);
- sp->tremolo_phase_increment = convert_tremolo_rate(song, tmp[13]);
- sp->tremolo_depth = tmp[14];
- cmsg(CMSG_INFO, VERB_DEBUG,
- " * tremolo: sweep %d, phase %d, depth %d",
- sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
- sp->tremolo_depth);
- }
+ /* seashore.pat in the Midia patch set has no Sustain. I don't
+ understand why, and fixing it by adding the Sustain flag to
+ all looped patches probably breaks something else. We do it
+ anyway. */
- if (!tmp[16] || !tmp[17])
- {
- sp->vibrato_sweep_increment = 0;
- sp->vibrato_control_ratio = 0;
- sp->vibrato_depth = 0;
- cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
- }
- else
- {
- sp->vibrato_control_ratio = convert_vibrato_rate(song, tmp[16]);
- sp->vibrato_sweep_increment= convert_vibrato_sweep(song, tmp[15], sp->vibrato_control_ratio);
- sp->vibrato_depth = tmp[17];
- cmsg(CMSG_INFO, VERB_DEBUG,
- " * vibrato: sweep %d, ctl %d, depth %d",
- sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
- sp->vibrato_depth);
+ if (sp->modes & PATCH_LOOPEN)
+ {
+ sp->modes |= PATCH_SUSTAIN;
+ }
- }
+ /* Strip any loops and envelopes we're permitted to */
+ if ((strip_loop == 1) &&
+ (sp->modes & (PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
+ {
+ cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain\n");
+ sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
+ }
- READ_CHAR(sp->modes);
- READ_SHORT(sp->freq_center);
- READ_SHORT(sp->freq_scale);
+ if (strip_envelope == 1)
+ {
+ if (sp->modes & PATCH_NO_SRELEASE)
+ {
+ cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope\n");
+ }
+ sp->modes &= ~PATCH_NO_SRELEASE;
+ }
+ else if (strip_envelope != 0)
+ {
+ /* Have to make a guess. */
+ if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
+ {
+ /* No loop? Then what's there to sustain? No envelope needed either... */
+ sp->modes &= ~(PATCH_SUSTAIN | PATCH_NO_SRELEASE);
+ cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n");
+ }
+ else if (memcmp(patch_data.EnvelopeRate, "??????", 6) == 0 || patch_data.EnvelopeOffset[RELEASEC] >= 100)
+ {
+ /* Envelope rates all maxed out? Envelope end at a high "offset"?
+ That's a weird envelope. Take it out. */
+ sp->modes &= ~PATCH_NO_SRELEASE;
+ cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n");
+ }
+ else if (!(sp->modes & PATCH_SUSTAIN))
+ {
+ /* No sustain? Then no envelope. I don't know if this is
+ justified, but patches without sustain usually don't need the
+ envelope either... at least the Gravis ones. They're mostly
+ drums. I think. */
+ sp->modes &= ~PATCH_NO_SRELEASE;
+ cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n");
+ }
+ }
- if (sf2flag)
- {
- READ_SHORT(sample_volume);
- READ_CHAR(sf2delay);
- READ_CHAR(sp->exclusiveClass);
- fp->Seek(32, SEEK_CUR);
- }
- else
- {
- fp->Seek(36, SEEK_CUR);
- sample_volume = 0;
- sf2delay = 0;
+ for (j = 0; j < 6; j++)
+ {
+ sp->envelope_rate[j] = convert_envelope_rate(song, patch_data.EnvelopeRate[j]);
+ sp->envelope_offset[j] = convert_envelope_offset(patch_data.EnvelopeOffset[j]);
+ }
- }
+ /* Then read the sample data */
+ if (((sp->modes & PATCH_16) && sp->data_length/2 > MAX_SAMPLE_SIZE) ||
+ (!(sp->modes & PATCH_16) && sp->data_length > MAX_SAMPLE_SIZE))
+ {
+ goto fail;
+ }
+ sp->data = (sample_t *)safe_malloc(sp->data_length);
- /* Mark this as a fixed-pitch instrument if such a deed is desired. */
- if (note_to_use != -1)
- sp->note_to_use = (BYTE)(note_to_use);
- else
- sp->note_to_use = 0;
+ if (sp->data_length != fp->Read(sp->data, sp->data_length))
+ goto fail;
- /* seashore.pat in the Midia patch set has no Sustain. I don't
- understand why, and fixing it by adding the Sustain flag to
- all looped patches probably breaks something else. We do it
- anyway. */
+ convert_sample_data(sp, sp->data);
- if (sp->modes & MODES_LOOPING)
- sp->modes |= MODES_SUSTAIN;
+ /* Reverse reverse loops and pass them off as normal loops */
+ if (sp->modes & PATCH_BACKWARD)
+ {
+ int t;
+ /* The GUS apparently plays reverse loops by reversing the
+ whole sample. We do the same because the GUS does not SUCK. */
- /* Strip any loops and envelopes we're permitted to */
- if ((strip_loop == 1) &&
- (sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
- {
- cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
- sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
- }
+ cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s\n", name);
+ reverse_data((sample_t *)sp->data, 0, sp->data_length);
+ sp->data[sp->data_length] = sp->data[sp->data_length - 1];
- if (strip_envelope == 1)
- {
- if (sp->modes & MODES_ENVELOPE)
- cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
- sp->modes &= ~MODES_ENVELOPE;
- }
- else if (strip_envelope != 0)
- {
- /* Have to make a guess. */
- if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
- {
- /* No loop? Then what's there to sustain? No envelope needed either... */
- sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
- cmsg(CMSG_INFO, VERB_DEBUG,
- " - No loop, removing sustain and envelope");
- }
- else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
- {
- /* Envelope rates all maxed out? Envelope end at a high "offset"?
- That's a weird envelope. Take it out. */
- sp->modes &= ~MODES_ENVELOPE;
- cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
- }
- else if (!(sp->modes & MODES_SUSTAIN))
- {
- /* No sustain? Then no envelope. I don't know if this is
- justified, but patches without sustain usually don't need the
- envelope either... at least the Gravis ones. They're mostly
- drums. I think. */
- sp->modes &= ~MODES_ENVELOPE;
- cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
- }
- }
+ t = sp->loop_start;
+ sp->loop_start = sp->data_length - sp->loop_end;
+ sp->loop_end = sp->data_length - t;
- sp->attenuation = 0;
+ sp->modes &= ~PATCH_BACKWARD;
+ sp->modes |= PATCH_LOOPEN; /* just in case */
+ }
- for (j = ATTACK; j < DELAY; j++)
- {
- sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]);
- sp->envelope_offset[j] = convert_envelope_offset(tmp[6+j]);
- }
- if (sf2flag)
- {
- if (sf2delay > 5)
- {
- sf2delay = 5;
- }
- sp->envelope_rate[DELAY] = (int)( (sf2delay * song->rate) / 1000 );
- }
- else
- {
- sp->envelope_rate[DELAY] = 0;
- }
- sp->envelope_offset[DELAY] = 0;
-
- for (j = ATTACK; j < DELAY; j++)
- {
- sp->modulation_rate[j] = float(sp->envelope_rate[j]);
- sp->modulation_offset[j] = float(sp->envelope_offset[j]);
- }
- sp->modulation_rate[DELAY] = sp->modulation_offset[DELAY] = 0;
- sp->modEnvToFilterFc = 0;
- sp->modEnvToPitch = 0;
- sp->lfo_sweep_increment = 0;
- sp->lfo_phase_increment = 0;
- sp->modLfoToFilterFc = 0;
-
- /* Then read the sample data */
- if (((sp->modes & MODES_16BIT) && sp->data_length/2 > MAX_SAMPLE_SIZE) ||
- (!(sp->modes & MODES_16BIT) && sp->data_length > MAX_SAMPLE_SIZE))
- {
- goto fail;
- }
- sp->data = (sample_t *)safe_malloc(sp->data_length + 1);
-
- if (sp->data_length != fp->Read(sp->data, sp->data_length))
- goto fail;
-
- convert_sample_data(sp, sp->data);
-
- /* Reverse reverse loops and pass them off as normal loops */
- if (sp->modes & MODES_REVERSE)
- {
- int t;
- /* The GUS apparently plays reverse loops by reversing the
- whole sample. We do the same because the GUS does not SUCK. */
-
- cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
- reverse_data((sample_t *)sp->data, 0, sp->data_length);
- sp->data[sp->data_length] = sp->data[sp->data_length - 1];
-
- t = sp->loop_start;
- sp->loop_start = sp->data_length - sp->loop_end;
- sp->loop_end = sp->data_length - t;
-
- sp->modes &= ~MODES_REVERSE;
- sp->modes |= MODES_LOOPING; /* just in case */
- }
-
- if (amp != -1)
- {
- sp->volume = (amp) / 100.f;
- }
- else if (sf2flag)
- {
- sp->volume = (sample_volume) / 255.f;
- }
- else
- {
+ if (amp != -1)
+ {
+ sp->volume = (amp) / 100.f;
+ }
+ else
+ {
#if defined(ADJUST_SAMPLE_VOLUMES)
- /* Try to determine a volume scaling factor for the sample.
- This is a very crude adjustment, but things sound more
- balanced with it. Still, this should be a runtime option. */
- int i, numsamps = sp->data_length;
- sample_t maxamp = 0, a;
- sample_t *tmp;
- for (i = numsamps, tmp = sp->data; i; --i)
- {
- a = abs(*tmp++);
- if (a > maxamp)
- maxamp = a;
- }
- sp->volume = 1 / maxamp;
- cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
+ /* Try to determine a volume scaling factor for the sample.
+ This is a very crude adjustment, but things sound more
+ balanced with it. Still, this should be a runtime option. */
+ int i;
+ sample_t maxamp = 0, a;
+ sample_t *tmp;
+ for (i = sp->data_length, tmp = sp->data; i; --i)
+ {
+ a = abs(*tmp++);
+ if (a > maxamp)
+ maxamp = a;
+ }
+ sp->volume = 1 / maxamp;
+ cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume);
#else
- sp->volume = 1;
+ sp->volume = 1;
#endif
- }
+ }
- /* Then fractional samples */
- sp->data_length <<= FRACTION_BITS;
- sp->loop_start <<= FRACTION_BITS;
- sp->loop_end <<= FRACTION_BITS;
+ /* Then fractional samples */
+ sp->data_length <<= FRACTION_BITS;
+ sp->loop_start <<= FRACTION_BITS;
+ sp->loop_end <<= FRACTION_BITS;
- /* Adjust for fractional loop points. */
- sp->loop_start |= (fractions & 0x0F) << (FRACTION_BITS-4);
- sp->loop_end |= ((fractions>>4) & 0x0F) << (FRACTION_BITS-4);
-
- /* If this instrument will always be played on the same note,
- and it's not looped, we can resample it now. */
- if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
- pre_resample(song, sp);
-
- if (strip_tail == 1)
- {
- /* Let's not really, just say we did. */
- cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
- sp->data_length = sp->loop_end;
- }
- } /* end of sample loop */
- } /* end of stereo layer loop */
- } /* end of vlayer loop */
+ /* Adjust for fractional loop points. */
+ sp->loop_start |= (patch_data.Fractions & 0x0F) << (FRACTION_BITS-4);
+ sp->loop_end |= (patch_data.Fractions & 0xF0) << (FRACTION_BITS-4-4);
+ /* If this instrument will always be played on the same note,
+ and it's not looped, we can resample it now. */
+ if (sp->scale_factor == 0 && !(sp->modes & PATCH_LOOPEN))
+ {
+ pre_resample(song, sp);
+ }
+ if (strip_tail == 1)
+ {
+ /* Let's not really, just say we did. */
+ cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail\n");
+ sp->data_length = sp->loop_end;
+ }
+ }
delete fp;
- return headlp;
+ return ip;
}
void convert_sample_data(Sample *sp, const void *data)
@@ -752,7 +503,7 @@ void convert_sample_data(Sample *sp, const void *data)
/* convert everything to 32-bit floating point data */
sample_t *newdata = NULL;
- switch (sp->modes & (MODES_16BIT | MODES_UNSIGNED))
+ switch (sp->modes & (PATCH_16 | PATCH_UNSIGNED))
{
case 0:
{ /* 8-bit, signed */
@@ -772,7 +523,7 @@ void convert_sample_data(Sample *sp, const void *data)
break;
}
- case MODES_UNSIGNED:
+ case PATCH_UNSIGNED:
{ /* 8-bit, unsigned */
BYTE *cp = (BYTE *)data;
newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t));
@@ -791,7 +542,7 @@ void convert_sample_data(Sample *sp, const void *data)
break;
}
- case MODES_16BIT:
+ case PATCH_16:
{ /* 16-bit, signed */
SWORD *cp = (SWORD *)data;
/* Convert these to samples */
@@ -814,7 +565,7 @@ void convert_sample_data(Sample *sp, const void *data)
break;
}
- case MODES_16BIT | MODES_UNSIGNED:
+ case PATCH_16 | PATCH_UNSIGNED:
{ /* 16-bit, unsigned */
WORD *cp = (WORD *)data;
/* Convert these to samples */
@@ -853,71 +604,61 @@ static int fill_bank(Renderer *song, int dr, int b)
if (bank == NULL)
{
cmsg(CMSG_ERROR, VERB_NORMAL,
- "Huh. Tried to load instruments in non-existent %s %d",
+ "Huh. Tried to load instruments in non-existent %s %d\n",
(dr) ? "drumset" : "tone bank", b);
return 0;
}
for (i = 0; i < MAXPROG; i++)
{
- if (bank->tone[i].layer == MAGIC_LOAD_INSTRUMENT)
+ if (bank->instrument[i] == MAGIC_LOAD_INSTRUMENT)
{
- bank->tone[i].layer = load_instrument_dls(song, dr, b, i);
- if (bank->tone[i].layer != NULL)
+ bank->instrument[i] = load_instrument_dls(song, dr, b, i);
+ if (bank->instrument[i] != NULL)
{
continue;
}
if (bank->tone[i].name.IsEmpty())
{
- cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL,
- "No instrument mapped to %s %d, program %d%s",
- (dr)? "drum set" : "tone bank", b, i,
- (b!=0) ? "" : " - this instrument will not be heard");
- if (b!=0)
+ cmsg(CMSG_WARNING, (b != 0) ? VERB_VERBOSE : VERB_NORMAL,
+ "No instrument mapped to %s %d, program %d%s\n",
+ (dr) ? "drum set" : "tone bank", b, i,
+ (b != 0) ? "" : " - this instrument will not be heard");
+ if (b != 0)
{
/* Mark the corresponding instrument in the default
- bank / drumset for loading (if it isn't already) */
+ bank / drumset for loading (if it isn't already) */
if (!dr)
{
- if (!(standard_tonebank.tone[i].layer))
- standard_tonebank.tone[i].layer=
- MAGIC_LOAD_INSTRUMENT;
+ if (tonebank[0]->instrument[i] != NULL)
+ {
+ tonebank[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
+ }
}
else
{
- if (!(standard_drumset.tone[i].layer))
- standard_drumset.tone[i].layer=
- MAGIC_LOAD_INSTRUMENT;
+ if (drumset[0]->instrument[i] != NULL)
+ {
+ drumset[0]->instrument[i] = MAGIC_LOAD_INSTRUMENT;
+ }
}
}
- bank->tone[i].layer=0;
+ bank->instrument[i] = NULL;
errors++;
}
- else if (!(bank->tone[i].layer=
+ else if (!(bank->instrument[i] =
load_instrument(song, bank->tone[i].name,
- bank->tone[i].font_type,
- (dr) ? 1 : 0,
- bank->tone[i].pan,
- bank->tone[i].amp,
- bank->tone[i].tuning,
- (bank->tone[i].note!=-1) ?
- bank->tone[i].note :
- ((dr) ? i : -1),
- (bank->tone[i].strip_loop!=-1) ?
- bank->tone[i].strip_loop :
- ((dr) ? 1 : -1),
- (bank->tone[i].strip_envelope != -1) ?
- bank->tone[i].strip_envelope :
- ((dr) ? 1 : -1),
- bank->tone[i].strip_tail,
- b,
- ((dr) ? i + 128 : i),
- bank->tone[i].sf_ix
- )))
+ (dr) ? 1 : 0,
+ bank->tone[i].pan,
+ bank->tone[i].amp,
+ (bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
+ (bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
+ (bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
+ bank->tone[i].strip_tail)))
{
cmsg(CMSG_ERROR, VERB_NORMAL,
- "Couldn't load instrument %s (%s %d, program %d)",
+ "Couldn't load instrument %s (%s %d, program %d)\n",
bank->tone[i].name.GetChars(),
- (dr)? "drum set" : "tone bank", b, i);
+ (dr) ? "drum set" : "tone bank", b, i);
errors++;
}
}
@@ -940,24 +681,34 @@ int Renderer::load_missing_instruments()
void free_instruments()
{
- int i = 128;
+ int i = MAXBANK;
while (i--)
{
if (tonebank[i] != NULL)
- free_bank(0,i);
+ {
+ delete tonebank[i];
+ tonebank[i] = NULL;
+ }
if (drumset[i] != NULL)
- free_bank(1,i);
+ {
+ delete drumset[i];
+ drumset[i] = NULL;
+ }
}
}
int Renderer::set_default_instrument(const char *name)
{
- InstrumentLayer *lp;
- if (!(lp = load_instrument(this, name, FONT_NORMAL, 0, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1)))
+ Instrument *ip;
+ if ((ip = load_instrument(this, name, 0, -1, -1, -1, 0, 0, 0)) == NULL)
+ {
return -1;
- if (default_instrument)
- free_layer(default_instrument);
- default_instrument = lp;
+ }
+ if (default_instrument != NULL)
+ {
+ delete default_instrument;
+ }
+ default_instrument = ip;
default_program = SPECIAL_PROGRAM;
return 0;
}
diff --git a/src/timidity/instrum_dls.cpp b/src/timidity/instrum_dls.cpp
index 5828b806..7900a55d 100644
--- a/src/timidity/instrum_dls.cpp
+++ b/src/timidity/instrum_dls.cpp
@@ -1121,29 +1121,29 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
DLS_Region *rgn = &ins->regions[index];
DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex];
- if (!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE))
- {
- sample->exclusiveClass = (SBYTE)rgn->header->usKeyGroup;
- }
+ sample->self_nonexclusive = !!(rgn->header->fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE);
+ sample->key_group = (SBYTE)rgn->header->usKeyGroup;
sample->low_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usLow));
sample->high_freq = SDWORD(note_to_freq(rgn->header->RangeKey.usHigh));
sample->root_freq = SDWORD(note_to_freq(rgn->wsmp->usUnityNote));
sample->low_vel = rgn->header->RangeVelocity.usLow;
sample->high_vel = rgn->header->RangeVelocity.usHigh;
- sample->modes = wave->format->wBitsPerSample == 8 ? MODES_UNSIGNED : MODES_16BIT;
+ sample->modes = wave->format->wBitsPerSample == 8 ? PATCH_UNSIGNED : PATCH_16;
sample->sample_rate = wave->format->dwSamplesPerSec;
sample->data = NULL;
sample->data_length = wave->length;
convert_sample_data(sample, wave->data);
- if (rgn->wsmp->cSampleLoops) {
- sample->modes |= (MODES_LOOPING|MODES_SUSTAIN);
+ if (rgn->wsmp->cSampleLoops)
+ {
+ sample->modes |= (PATCH_LOOPEN | PATCH_SUSTAIN);
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
}
sample->volume = 1.0f;
- if (sample->modes & MODES_SUSTAIN) {
+ if (sample->modes & PATCH_SUSTAIN)
+ {
int value;
double attack, hold, decay, release; int sustain;
CONNECTIONLIST *art = NULL;
@@ -1192,12 +1192,7 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
sample->envelope_offset[RELEASEC] = to_offset(0);
sample->envelope_rate[RELEASEC] = to_offset(1);
- sample->modes |= MODES_ENVELOPE;
- }
- for (int j = ATTACK; j < DELAY; j++)
- {
- sample->modulation_rate[j] = float(sample->envelope_rate[j]);
- sample->modulation_offset[j] = float(sample->envelope_offset[j]);
+ sample->modes |= PATCH_NO_SRELEASE;
}
sample->data_length <<= FRACTION_BITS;
@@ -1205,55 +1200,54 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
sample->loop_end <<= FRACTION_BITS;
}
-InstrumentLayer *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
+Instrument *load_instrument_dls(Renderer *song, int drum, int bank, int instrument)
{
- InstrumentLayer *layer;
+ Instrument *inst;
DWORD i;
DLS_Instrument *dls_ins = NULL;
if (song->patches == NULL)
+ {
return NULL;
-
+ }
drum = drum ? 0x80000000 : 0;
- for (i = 0; i < song->patches->cInstruments; ++i) {
+ for (i = 0; i < song->patches->cInstruments; ++i)
+ {
dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == (ULONG)bank &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break;
}
- if (i == song->patches->cInstruments && !bank) {
- for (i = 0; i < song->patches->cInstruments; ++i) {
+ if (i == song->patches->cInstruments && bank == 0)
+ {
+ for (i = 0; i < song->patches->cInstruments; ++i)
+ {
dls_ins = &song->patches->instruments[i];
if ((dls_ins->header->Locale.ulBank & 0x80000000) == (ULONG)drum &&
dls_ins->header->Locale.ulInstrument == (ULONG)instrument)
break;
}
}
- if (i == song->patches->cInstruments) {
+ if (i == song->patches->cInstruments)
+ {
// SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank));
return NULL;
}
- layer = (InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
- layer->lo = 0;
- layer->hi = 127;
- layer->instrument = (Instrument *)safe_malloc(sizeof(Instrument));
- layer->instrument->type = INST_DLS;
- layer->instrument->samples = dls_ins->header->cRegions;
- layer->instrument->sample = (Sample *)safe_malloc(layer->instrument->samples * sizeof(Sample));
- layer->instrument->left_samples = layer->instrument->samples;
- layer->instrument->left_sample = layer->instrument->sample;
- layer->instrument->right_samples = 0;
- layer->instrument->right_sample = NULL;
- memset(layer->instrument->sample, 0, layer->instrument->samples * sizeof(Sample));
+ inst = (Instrument *)safe_malloc(sizeof(Instrument));
+ inst->type = INST_DLS;
+ inst->samples = dls_ins->header->cRegions;
+ inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(Sample));
+ memset(inst->sample, 0, inst->samples * sizeof(Sample));
/*
printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples);
*/
- for (i = 0; i < dls_ins->header->cRegions; ++i) {
- load_region_dls(song, &layer->instrument->sample[i], dls_ins, i);
+ for (i = 0; i < dls_ins->header->cRegions; ++i)
+ {
+ load_region_dls(song, &inst->sample[i], dls_ins, i);
}
- return layer;
+ return inst;
}
#endif /* !TEST_MAIN_DLS */
diff --git a/src/timidity/mix.cpp b/src/timidity/mix.cpp
index 92a23138..34db6b40 100644
--- a/src/timidity/mix.cpp
+++ b/src/timidity/mix.cpp
@@ -37,15 +37,14 @@ int recompute_envelope(Voice *v)
stage = v->envelope_stage;
- if (stage >= DELAY)
+ if (stage > RELEASEC)
{
/* Envelope ran out. */
- int tmp = (v->status == VOICE_DIE); /* Already displayed as dead */
v->status = VOICE_FREE;
return 1;
}
- if (v->sample->modes & MODES_ENVELOPE)
+ if (v->sample->modes & PATCH_NO_SRELEASE)
{
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
{
@@ -60,7 +59,9 @@ int recompute_envelope(Voice *v)
v->envelope_stage = stage + 1;
if (v->envelope_volume == v->sample->envelope_offset[stage])
+ {
return recompute_envelope(v);
+ }
v->envelope_target = v->sample->envelope_offset[stage];
v->envelope_increment = v->sample->envelope_rate[stage];
if (v->envelope_target < v->envelope_volume)
@@ -75,28 +76,30 @@ void apply_envelope_to_amp(Voice *v)
{
ramp = v->right_amp;
- if (v->tremolo_phase_increment)
+ if (v->tremolo_phase_increment != 0)
{
lamp *= v->tremolo_volume;
ramp *= v->tremolo_volume;
}
- if (v->sample->modes & MODES_ENVELOPE)
+ if (v->sample->modes & PATCH_NO_SRELEASE)
{
double vol = calc_vol(v->envelope_volume / float(1 << 30));
lamp *= vol;
ramp *= vol;
}
-
v->left_mix = float(lamp);
v->right_mix = float(ramp);
}
else
{
- if (v->tremolo_phase_increment)
+ if (v->tremolo_phase_increment != 0)
+ {
lamp *= v->tremolo_volume;
- if (v->sample->modes & MODES_ENVELOPE)
+ }
+ if (v->sample->modes & PATCH_NO_SRELEASE)
+ {
lamp *= calc_vol(v->envelope_volume / float(1 << 30));
-
+ }
v->left_mix = float(lamp);
}
}
@@ -104,13 +107,14 @@ void apply_envelope_to_amp(Voice *v)
static int update_envelope(Voice *v)
{
v->envelope_volume += v->envelope_increment;
- /* Why is there no ^^ operator?? */
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
{
v->envelope_volume = v->envelope_target;
if (recompute_envelope(v))
+ {
return 1;
+ }
}
return 0;
}
@@ -119,7 +123,7 @@ static void update_tremolo(Voice *v)
{
int depth = v->sample->tremolo_depth << 7;
- if (v->tremolo_sweep)
+ if (v->tremolo_sweep != 0)
{
/* Update sweep position */
@@ -151,12 +155,14 @@ static void update_tremolo(Voice *v)
/* Returns 1 if the note died */
static int update_signal(Voice *v)
{
- if (v->envelope_increment && update_envelope(v))
+ if (v->envelope_increment != 0 && update_envelope(v))
+ {
return 1;
-
- if (v->tremolo_phase_increment)
+ }
+ if (v->tremolo_phase_increment != 0)
+ {
update_tremolo(v);
-
+ }
apply_envelope_to_amp(v);
return 0;
}
diff --git a/src/timidity/playmidi.cpp b/src/timidity/playmidi.cpp
index ca35be26..9f261a9e 100644
--- a/src/timidity/playmidi.cpp
+++ b/src/timidity/playmidi.cpp
@@ -31,210 +31,12 @@
namespace Timidity
{
-static bool opt_stereo_surround = false;
-bool adjust_panning_immediately = false;
-
-/* $Id: tables.c 1404 2004-08-21 12:27:02Z slouken $ Greg Lee */
-const BYTE xmap[XMAPMAX][5] =
-{
- { SFXBANK, 0, 0, 120, 0 },
- { SFXBANK, 0, 1, 120, 1 },
- { SFXBANK, 0, 2, 120, 2 },
- { SFXBANK, 0, 3, 120, 3 },
- { SFXBANK, 0, 4, 120, 4 },
- { SFXBANK, 0, 5, 120, 5 },
- { SFXBANK, 0, 16, 120, 16 },
- { SFXBANK, 0, 32, 120, 32 },
- { SFXBANK, 0, 33, 120, 33 },
- { SFXBANK, 0, 34, 120, 34 },
- { SFXBANK, 0, 35, 120, 35 },
- { SFXBANK, 0, 36, 120, 36 },
- { SFXBANK, 0, 48, 120, 48 },
- { SFXBANK, 0, 49, 120, 49 },
- { SFXBANK, 0, 50, 120, 50 },
- { SFXBANK, 0, 51, 120, 51 },
- { SFXBANK, 0, 52, 120, 52 },
- { SFXBANK, 0, 54, 120, 54 },
- { SFXBANK, 0, 55, 120, 55 },
- { SFXBANK, 0, 64, 120, 64 },
- { SFXBANK, 0, 65, 120, 65 },
- { SFXBANK, 0, 66, 120, 66 },
- { SFXBANK, 0, 67, 120, 67 },
- { SFXBANK, 0, 68, 120, 68 },
- { SFXBANK, 0, 69, 120, 69 },
- { SFXBANK, 0, 70, 120, 70 },
- { SFXBANK, 0, 80, 120, 80 },
- { SFXBANK, 0, 81, 120, 81 },
- { SFXBANK, 0, 82, 120, 82 },
- { SFXBANK, 0, 83, 120, 83 },
- { SFXBANK, 0, 84, 120, 84 },
- { SFXBANK, 0, 85, 120, 85 },
- { SFXBANK, 0, 86, 120, 86 },
- { SFXBANK, 0, 87, 120, 87 },
- { SFXBANK, 0, 88, 120, 88 },
- { SFXBANK, 0, 89, 120, 89 },
- { SFXBANK, 0, 90, 120, 90 },
- { SFXBANK, 0, 96, 120, 96 },
- { SFXBANK, 0, 97, 120, 97 },
- { SFXBANK, 0, 98, 120, 98 },
- { SFXBANK, 0, 99, 120, 99 },
- { SFXBANK, 0, 100, 120, 100 },
- { SFXBANK, 0, 101, 120, 101 },
- { SFXBANK, 0, 112, 120, 112 },
- { SFXBANK, 0, 113, 120, 113 },
- { SFXBANK, 0, 114, 120, 114 },
- { SFXBANK, 0, 115, 120, 115 },
- { SFXDRUM1, 0, 36, 121, 36 },
- { SFXDRUM1, 0, 37, 121, 37 },
- { SFXDRUM1, 0, 38, 121, 38 },
- { SFXDRUM1, 0, 39, 121, 39 },
- { SFXDRUM1, 0, 40, 121, 40 },
- { SFXDRUM1, 0, 41, 121, 41 },
- { SFXDRUM1, 0, 52, 121, 52 },
- { SFXDRUM1, 0, 68, 121, 68 },
- { SFXDRUM1, 0, 69, 121, 69 },
- { SFXDRUM1, 0, 70, 121, 70 },
- { SFXDRUM1, 0, 71, 121, 71 },
- { SFXDRUM1, 0, 72, 121, 72 },
- { SFXDRUM1, 0, 84, 121, 84 },
- { SFXDRUM1, 0, 85, 121, 85 },
- { SFXDRUM1, 0, 86, 121, 86 },
- { SFXDRUM1, 0, 87, 121, 87 },
- { SFXDRUM1, 0, 88, 121, 88 },
- { SFXDRUM1, 0, 90, 121, 90 },
- { SFXDRUM1, 0, 91, 121, 91 },
- { SFXDRUM1, 1, 36, 122, 36 },
- { SFXDRUM1, 1, 37, 122, 37 },
- { SFXDRUM1, 1, 38, 122, 38 },
- { SFXDRUM1, 1, 39, 122, 39 },
- { SFXDRUM1, 1, 40, 122, 40 },
- { SFXDRUM1, 1, 41, 122, 41 },
- { SFXDRUM1, 1, 42, 122, 42 },
- { SFXDRUM1, 1, 52, 122, 52 },
- { SFXDRUM1, 1, 53, 122, 53 },
- { SFXDRUM1, 1, 54, 122, 54 },
- { SFXDRUM1, 1, 55, 122, 55 },
- { SFXDRUM1, 1, 56, 122, 56 },
- { SFXDRUM1, 1, 57, 122, 57 },
- { SFXDRUM1, 1, 58, 122, 58 },
- { SFXDRUM1, 1, 59, 122, 59 },
- { SFXDRUM1, 1, 60, 122, 60 },
- { SFXDRUM1, 1, 61, 122, 61 },
- { SFXDRUM1, 1, 62, 122, 62 },
- { SFXDRUM1, 1, 68, 122, 68 },
- { SFXDRUM1, 1, 69, 122, 69 },
- { SFXDRUM1, 1, 70, 122, 70 },
- { SFXDRUM1, 1, 71, 122, 71 },
- { SFXDRUM1, 1, 72, 122, 72 },
- { SFXDRUM1, 1, 73, 122, 73 },
- { SFXDRUM1, 1, 84, 122, 84 },
- { SFXDRUM1, 1, 85, 122, 85 },
- { SFXDRUM1, 1, 86, 122, 86 },
- { SFXDRUM1, 1, 87, 122, 87 },
- { XGDRUM, 0, 25, 40, 38 },
- { XGDRUM, 0, 26, 40, 40 },
- { XGDRUM, 0, 27, 40, 39 },
- { XGDRUM, 0, 28, 40, 30 },
- { XGDRUM, 0, 29, 0, 25 },
- { XGDRUM, 0, 30, 0, 85 },
- { XGDRUM, 0, 31, 0, 38 },
- { XGDRUM, 0, 32, 0, 37 },
- { XGDRUM, 0, 33, 0, 36 },
- { XGDRUM, 0, 34, 0, 38 },
- { XGDRUM, 0, 62, 0, 101 },
- { XGDRUM, 0, 63, 0, 102 },
- { XGDRUM, 0, 64, 0, 103 },
- { XGDRUM, 8, 25, 40, 38 },
- { XGDRUM, 8, 26, 40, 40 },
- { XGDRUM, 8, 27, 40, 39 },
- { XGDRUM, 8, 28, 40, 40 },
- { XGDRUM, 8, 29, 8, 25 },
- { XGDRUM, 8, 30, 8, 85 },
- { XGDRUM, 8, 31, 8, 38 },
- { XGDRUM, 8, 32, 8, 37 },
- { XGDRUM, 8, 33, 8, 36 },
- { XGDRUM, 8, 34, 8, 38 },
- { XGDRUM, 8, 62, 8, 101 },
- { XGDRUM, 8, 63, 8, 102 },
- { XGDRUM, 8, 64, 8, 103 },
- { XGDRUM, 16, 25, 40, 38 },
- { XGDRUM, 16, 26, 40, 40 },
- { XGDRUM, 16, 27, 40, 39 },
- { XGDRUM, 16, 28, 40, 40 },
- { XGDRUM, 16, 29, 16, 25 },
- { XGDRUM, 16, 30, 16, 85 },
- { XGDRUM, 16, 31, 16, 38 },
- { XGDRUM, 16, 32, 16, 37 },
- { XGDRUM, 16, 33, 16, 36 },
- { XGDRUM, 16, 34, 16, 38 },
- { XGDRUM, 16, 62, 16, 101 },
- { XGDRUM, 16, 63, 16, 102 },
- { XGDRUM, 16, 64, 16, 103 },
- { XGDRUM, 24, 25, 40, 38 },
- { XGDRUM, 24, 26, 40, 40 },
- { XGDRUM, 24, 27, 40, 39 },
- { XGDRUM, 24, 28, 24, 100 },
- { XGDRUM, 24, 29, 24, 25 },
- { XGDRUM, 24, 30, 24, 15 },
- { XGDRUM, 24, 31, 24, 38 },
- { XGDRUM, 24, 32, 24, 37 },
- { XGDRUM, 24, 33, 24, 36 },
- { XGDRUM, 24, 34, 24, 38 },
- { XGDRUM, 24, 62, 24, 101 },
- { XGDRUM, 24, 63, 24, 102 },
- { XGDRUM, 24, 64, 24, 103 },
- { XGDRUM, 24, 78, 0, 17 },
- { XGDRUM, 24, 79, 0, 18 },
- { XGDRUM, 25, 25, 40, 38 },
- { XGDRUM, 25, 26, 40, 40 },
- { XGDRUM, 25, 27, 40, 39 },
- { XGDRUM, 25, 28, 25, 100 },
- { XGDRUM, 25, 29, 25, 25 },
- { XGDRUM, 25, 30, 25, 15 },
- { XGDRUM, 25, 31, 25, 38 },
- { XGDRUM, 25, 32, 25, 37 },
- { XGDRUM, 25, 33, 25, 36 },
- { XGDRUM, 25, 34, 25, 38 },
- { XGDRUM, 25, 78, 0, 17 },
- { XGDRUM, 25, 79, 0, 18 },
- { XGDRUM, 32, 25, 40, 38 },
- { XGDRUM, 32, 26, 40, 40 },
- { XGDRUM, 32, 27, 40, 39 },
- { XGDRUM, 32, 28, 40, 40 },
- { XGDRUM, 32, 29, 32, 25 },
- { XGDRUM, 32, 30, 32, 85 },
- { XGDRUM, 32, 31, 32, 38 },
- { XGDRUM, 32, 32, 32, 37 },
- { XGDRUM, 32, 33, 32, 36 },
- { XGDRUM, 32, 34, 32, 38 },
- { XGDRUM, 32, 62, 32, 101 },
- { XGDRUM, 32, 63, 32, 102 },
- { XGDRUM, 32, 64, 32, 103 },
- { XGDRUM, 40, 25, 40, 38 },
- { XGDRUM, 40, 26, 40, 40 },
- { XGDRUM, 40, 27, 40, 39 },
- { XGDRUM, 40, 28, 40, 40 },
- { XGDRUM, 40, 29, 40, 25 },
- { XGDRUM, 40, 30, 40, 85 },
- { XGDRUM, 40, 31, 40, 39 },
- { XGDRUM, 40, 32, 40, 37 },
- { XGDRUM, 40, 33, 40, 36 },
- { XGDRUM, 40, 34, 40, 38 },
- { XGDRUM, 40, 38, 40, 39 },
- { XGDRUM, 40, 39, 0, 39 },
- { XGDRUM, 40, 40, 40, 38 },
- { XGDRUM, 40, 42, 0, 42 },
- { XGDRUM, 40, 46, 0, 46 },
- { XGDRUM, 40, 62, 40, 101 },
- { XGDRUM, 40, 63, 40, 102 },
- { XGDRUM, 40, 64, 40, 103 },
- { XGDRUM, 40, 87, 40, 87 }
-};
-
void Renderer::reset_voices()
{
for (int i = 0; i < MAX_VOICES; i++)
+ {
voice[i].status = VOICE_FREE;
+ }
}
/* Process the Reset All Controllers event */
@@ -248,9 +50,6 @@ void Renderer::reset_controllers(int c)
channel[c].mono = 0;
channel[c].rpn = RPN_RESET;
channel[c].nrpn = RPN_RESET;
-
- channel[c].reverberation = 0;
- channel[c].chorusdepth = 0;
}
void Renderer::reset_midi()
@@ -263,18 +62,13 @@ void Renderer::reset_midi()
channel[i].panning = NO_PANNING;
channel[i].pitchsens = 200;
channel[i].bank = 0; /* tone bank or drum set */
- channel[i].harmoniccontent = 64;
- channel[i].releasetime = 64;
- channel[i].attacktime = 64;
- channel[i].brightness = 64;
- channel[i].sfx = 0;
}
reset_voices();
}
void Renderer::select_sample(int v, Instrument *ip, int vel)
{
- float f, cdiff, diff, midfreq;
+ double f, cdiff, diff;
int s, i;
Sample *sp, *closest;
@@ -300,22 +94,16 @@ void Renderer::select_sample(int v, Instrument *ip, int vel)
}
/*
- No suitable sample found! We'll select the sample whose root
- frequency is closest to the one we want. (Actually we should
- probably convert the low, high, and root frequencies to MIDI note
- values and compare those.) */
+ No suitable sample found! We'll select the sample whose root
+ frequency is closest to the one we want. (Actually we should
+ probably convert the low, high, and root frequencies to MIDI note
+ values and compare those.) */
cdiff = 1e10;
closest = sp = ip->sample;
- midfreq = float(sp->low_freq + sp->high_freq) / 2;
for (i = 0; i < s; i++)
{
- diff = sp->root_freq - f;
- /* But the root freq. can perfectly well lie outside the keyrange
- * frequencies, so let's try:
- */
- /* diff = midfreq - f; */
- if (diff < 0) diff = -diff;
+ diff = fabs(sp->root_freq - f);
if (diff < cdiff)
{
cdiff = diff;
@@ -327,61 +115,6 @@ void Renderer::select_sample(int v, Instrument *ip, int vel)
return;
}
-
-
-void Renderer::select_stereo_samples(int v, InstrumentLayer *lp, int vel)
-{
- Instrument *ip;
- InstrumentLayer *nlp, *bestvel;
- int diffvel, midvel, mindiff;
-
- /* select closest velocity */
- bestvel = lp;
- mindiff = 500;
- for (nlp = lp; nlp; nlp = nlp->next)
- {
- midvel = (nlp->hi + nlp->lo)/2;
- if (!midvel)
- {
- diffvel = 127;
- }
- else if (voice[v].velocity < nlp->lo || voice[v].velocity > nlp->hi)
- {
- diffvel = 200;
- }
- else
- {
- diffvel = voice[v].velocity - midvel;
- }
- if (diffvel < 0)
- {
- diffvel = -diffvel;
- }
- if (diffvel < mindiff)
- {
- mindiff = diffvel;
- bestvel = nlp;
- }
- }
- ip = bestvel->instrument;
-
- if (ip->right_sample)
- {
- ip->sample = ip->right_sample;
- ip->samples = ip->right_samples;
- select_sample(v, ip, vel);
- voice[v].right_sample = voice[v].sample;
- }
- else
- {
- voice[v].right_sample = NULL;
- }
- ip->sample = ip->left_sample;
- ip->samples = ip->left_samples;
- select_sample(v, ip, vel);
-}
-
-
void Renderer::recompute_freq(int v)
{
Channel *ch = &channel[voice[v].channel];
@@ -390,17 +123,16 @@ void Renderer::recompute_freq(int v)
pb = ch->pitchbend;
double a;
- if (!voice[v].sample->sample_rate)
+ if (voice[v].sample->sample_rate == 0)
+ {
return;
+ }
- if (voice[v].vibrato_control_ratio)
+ if (voice[v].vibrato_control_ratio != 0)
{
/* This instrument has vibrato. Invalidate any precomputed
- sample_increments. */
-
- int i = VIBRATO_SAMPLE_INCREMENTS;
- while (i--)
- voice[v].vibrato_sample_increment[i]=0;
+ sample_increments. */
+ memset(voice[v].vibrato_sample_increment, 0, sizeof(voice[v].vibrato_sample_increment));
}
if (pb == 0x2000 || pb < 0 || pb > 0x3FFF)
@@ -437,34 +169,24 @@ void Renderer::recompute_freq(int v)
void Renderer::recompute_amp(Voice *v)
{
- double tempamp;
int chan = v->channel;
int panning = v->panning;
double vol = channel[chan].volume / 16383.f;
- double expr = calc_vol(channel[chan].expression / 16383.f);
- double vel = calc_vol(v->velocity / 127.f);
+ double expr = channel[chan].expression / 16383.f;
+ double vel = v->velocity / 127.f;
+ double tempamp = calc_vol(vol * expr * vel) * v->sample->volume;
- if (channel[chan].kit)
- {
- int note = v->sample->note_to_use;
- if (note > 0 && drumvolume[chan][note] >= 0) { vol = drumvolume[chan][note] / 127.f; }
- if (note > 0 && drumpanpot[chan][note] >= 0) { panning = drumvolume[chan][note]; panning |= panning << 7; }
- }
-
- vol = calc_vol(vol);
- tempamp = vel * vol * expr * v->sample->volume;
-
- if (panning > (60 << 7) && panning < (68 << 7))
+ if (panning >= 0x1DBB && panning < 0x2244)
{
v->panned = PANNED_CENTER;
v->left_amp = (float)(tempamp * 0.70710678118654752440084436210485); // * sqrt(0.5)
}
- else if (panning < (5 << 7))
+ else if (panning == 0)
{
v->panned = PANNED_LEFT;
v->left_amp = (float)tempamp;
}
- else if (panning > (123 << 7))
+ else if (panning == 0x3FFF)
{
v->panned = PANNED_RIGHT;
v->left_amp = (float)tempamp; /* left_amp will be used */
@@ -478,471 +200,75 @@ void Renderer::recompute_amp(Voice *v)
}
}
-
-#define NOT_CLONE 0
-#define STEREO_CLONE 1
-#define REVERB_CLONE 2
-#define CHORUS_CLONE 3
-
-
-/* just a variant of note_on() */
-int Renderer::vc_alloc(int j)
-{
- int i = voices;
-
- while (i--)
- {
- if (i != j && (voice[i].status == VOICE_FREE))
- {
- return i;
- }
- }
- return -1;
-}
-
-void Renderer::kill_others(int i)
+void Renderer::kill_key_group(int i)
{
int j = voices;
- if (!voice[i].sample->exclusiveClass) return;
-
+ if (voice[i].sample->key_group == 0)
+ {
+ return;
+ }
while (j--)
{
- if (voice[j].status == VOICE_FREE ||
- voice[j].status == VOICE_OFF ||
- voice[j].status == VOICE_DIE) continue;
+ if (voice[j].status != VOICE_ON && voice[j].status != VOICE_SUSTAINED) continue;
if (i == j) continue;
if (voice[i].channel != voice[j].channel) continue;
- if (voice[j].sample->note_to_use)
- {
- if (voice[j].sample->exclusiveClass != voice[i].sample->exclusiveClass) continue;
- kill_note(j);
- }
+ if (voice[j].sample->key_group != voice[i].sample->key_group) continue;
+ kill_note(j);
}
}
-
-void Renderer::clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank)
+float Renderer::calculate_scaled_frequency(Sample *sp, int note)
{
- int w, played_note, chorus = 0, reverb = 0, milli;
- int chan = voice[v].channel;
-
- // [RH] Don't do the other clones.
- if (clone_type != STEREO_CLONE)
- {
- return;
- }
-
- if (clone_type == STEREO_CLONE)
- {
- if (!voice[v].right_sample && variationbank != 3) return;
- if (variationbank == 6) return;
- }
-
- if (channel[chan].kit)
- {
- reverb = drumreverberation[chan][voice[v].note];
- chorus = drumchorusdepth[chan][voice[v].note];
- }
- else
- {
- reverb = channel[chan].reverberation;
- chorus = channel[chan].chorusdepth;
- }
-
- if (clone_type == REVERB_CLONE) chorus = 0;
- else if (clone_type == CHORUS_CLONE) reverb = 0;
- else if (clone_type == STEREO_CLONE) reverb = chorus = 0;
-
- if (reverb > 127) reverb = 127;
- if (chorus > 127) chorus = 127;
-
- if (clone_type == CHORUS_CLONE)
- {
- if (variationbank == 32) chorus = 30;
- else if (variationbank == 33) chorus = 60;
- else if (variationbank == 34) chorus = 90;
- }
-
- chorus /= 2; /* This is an ad hoc adjustment. */
-
- if (!reverb && !chorus && clone_type != STEREO_CLONE) return;
-
- if ( (w = vc_alloc(v)) < 0 ) return;
-
- voice[w] = voice[v];
- if (clone_type == STEREO_CLONE) voice[v].clone_voice = w;
- voice[w].clone_voice = v;
- voice[w].clone_type = clone_type;
- voice[w].velocity = vel;
-
- milli = int(rate / 1000);
-
- if (clone_type == STEREO_CLONE)
- {
- int left, right, leftpan, rightpan;
- int panrequest = voice[v].panning;
- voice[w].sample = voice[v].right_sample;
- if (variationbank == 3)
- {
- voice[v].panning = 0;
- voice[w].panning = 127;
- }
- else
- {
- if (voice[v].sample->panning > voice[w].sample->panning)
- {
- left = w;
- right = v;
- }
- else
- {
- left = v;
- right = w;
- }
-#define INSTRUMENT_SEPARATION 12
- leftpan = panrequest - INSTRUMENT_SEPARATION / 2;
- rightpan = leftpan + INSTRUMENT_SEPARATION;
- if (leftpan < 0)
- {
- leftpan = 0;
- rightpan = leftpan + INSTRUMENT_SEPARATION;
- }
- if (rightpan > 127)
- {
- rightpan = 127;
- leftpan = rightpan - INSTRUMENT_SEPARATION;
- }
- voice[left].panning = leftpan;
- voice[right].panning = rightpan;
- voice[right].echo_delay = 20 * milli;
- }
- }
-
- voice[w].volume = voice[w].sample->volume;
-
- if (reverb)
- {
- if (opt_stereo_surround)
- {
- if (voice[w].panning > 64)
- voice[w].panning = 127;
- else
- voice[w].panning = 0;
- }
- else
- {
- if (voice[v].panning < 64)
- voice[w].panning = 64 + reverb/2;
- else
- voice[w].panning = 64 - reverb/2;
- }
-
- /* try 98->99 for melodic instruments ? (bit much for percussion) */
- /* voice[w].volume *= calc_vol(((127 - reverb) / 8 + 98) / 127.f); */
- voice[w].volume = float(voice[w].volume * calc_vol((911 - reverb) / (8 * 127.f)));
-
- voice[w].echo_delay += reverb * milli;
- voice[w].envelope_rate[DECAY] *= 2;
- voice[w].envelope_rate[RELEASE] /= 2;
-
- if (XG_System_reverb_type >= 0)
- {
- int subtype = XG_System_reverb_type & 0x07;
- int rtype = XG_System_reverb_type >> 3;
- switch (rtype)
- {
- case 0: /* no effect */
- break;
- case 1: /* hall */
- if (subtype) voice[w].echo_delay += 100 * milli;
- break;
- case 2: /* room */
- voice[w].echo_delay /= 2;
- break;
- case 3: /* stage */
- voice[w].velocity = voice[v].velocity;
- break;
- case 4: /* plate */
- voice[w].panning = voice[v].panning;
- break;
- case 16: /* white room */
- voice[w].echo_delay = 0;
- break;
- case 17: /* tunnel */
- voice[w].echo_delay *= 2;
- voice[w].velocity /= 2;
- break;
- case 18: /* canyon */
- voice[w].echo_delay *= 2;
- break;
- case 19: /* basement */
- voice[w].velocity /= 2;
- break;
- default:
- break;
- }
- }
- }
- played_note = voice[w].sample->note_to_use;
- if (!played_note)
- {
- played_note = note & 0x7f;
- if (variationbank == 35) played_note += 12;
- else if (variationbank == 36) played_note -= 12;
- else if (variationbank == 37) played_note += 7;
- else if (variationbank == 36) played_note -= 7;
- }
-#if 0
- played_note = ( (played_note - voice[w].sample->freq_center) * voice[w].sample->freq_scale ) / 1024 +
- voice[w].sample->freq_center;
-#endif
- voice[w].note = played_note;
- voice[w].orig_frequency = note_to_freq(played_note);
-
- if (chorus)
- {
- if (opt_stereo_surround)
- {
- if (voice[v].panning < 64)
- voice[w].panning = voice[v].panning + 32;
- else
- voice[w].panning = voice[v].panning - 32;
- }
-
- if (!voice[w].vibrato_control_ratio)
- {
- voice[w].vibrato_control_ratio = 100;
- voice[w].vibrato_depth = 6;
- voice[w].vibrato_sweep = 74;
- }
- voice[w].volume *= 0.40f;
- voice[v].volume = voice[w].volume;
- recompute_amp(&voice[v]);
- apply_envelope_to_amp(&voice[v]);
-
- voice[w].vibrato_sweep = chorus/2;
- voice[w].vibrato_depth /= 2;
- if (!voice[w].vibrato_depth) voice[w].vibrato_depth = 2;
- voice[w].vibrato_control_ratio /= 2;
- voice[w].echo_delay += 30 * milli;
-
- if (XG_System_chorus_type >= 0)
- {
- int subtype = XG_System_chorus_type & 0x07;
- int chtype = 0x0f & (XG_System_chorus_type >> 3);
- float chorus_factor;
-
- switch (chtype)
- {
- case 0: /* no effect */
- break;
- case 1: /* chorus */
- chorus /= 3;
- chorus_factor = pow(2.f, chorus / (256.f * 12.f));
- if(channel[ voice[w].channel ].pitchbend + chorus < 0x2000)
- {
- voice[w].orig_frequency = voice[w].orig_frequency * chorus_factor;
- }
- else
- {
- voice[w].orig_frequency = voice[w].orig_frequency / chorus_factor;
- }
- if (subtype)
- {
- voice[w].vibrato_depth *= 2;
- }
- break;
- case 2: /* celeste */
- voice[w].orig_frequency += (voice[w].orig_frequency/128) * chorus;
- break;
- case 3: /* flanger */
- voice[w].vibrato_control_ratio = 10;
- voice[w].vibrato_depth = 100;
- voice[w].vibrato_sweep = 8;
- voice[w].echo_delay += 200 * milli;
- break;
- case 4: /* symphonic : cf Children of the Night /128 bad, /1024 ok */
- voice[w].orig_frequency += (voice[w].orig_frequency/512) * chorus;
- voice[v].orig_frequency -= (voice[v].orig_frequency/512) * chorus;
- recompute_freq(v);
- break;
- case 8: /* phaser */
- break;
- default:
- break;
- }
- }
- else
- {
- float chorus_factor;
- chorus /= 3;
- chorus_factor = pow(2.f, chorus / (256.f * 12.f));
- if (channel[ voice[w].channel ].pitchbend + chorus < 0x2000)
- {
- voice[w].orig_frequency = voice[w].orig_frequency * chorus_factor;
- }
- else
- {
- voice[w].orig_frequency = voice[w].orig_frequency / chorus_factor;
- }
- }
- }
-#if 0
- voice[w].loop_start = voice[w].sample->loop_start;
- voice[w].loop_end = voice[w].sample->loop_end;
-#endif
- voice[w].echo_delay_count = voice[w].echo_delay;
- if (reverb) voice[w].echo_delay *= 2;
-
- recompute_freq(w);
- recompute_amp(&voice[w]);
- if (voice[w].sample->modes & MODES_ENVELOPE)
- {
- /* Ramp up from 0 */
- voice[w].envelope_stage = ATTACK;
- voice[w].modulation_stage = ATTACK;
- voice[w].envelope_volume = 0;
- voice[w].modulation_volume = 0;
- voice[w].control_counter = 0;
- voice[w].modulation_counter = 0;
- recompute_envelope(&voice[w]);
- /*recompute_modulation(w);*/
- }
- else
- {
- voice[w].envelope_increment = 0;
- voice[w].modulation_increment = 0;
- }
- apply_envelope_to_amp(&voice[w]);
+ double scalednote = (note - sp->scale_note) * sp->scale_factor / 1024.0 + sp->scale_note;
+ return (float)note_to_freq(scalednote);
}
-
-void Renderer::xremap(int *banknumpt, int *this_notept, int this_kit)
+void Renderer::start_note(int chan, int note, int vel, int i)
{
- int i, newmap;
- int banknum = *banknumpt;
- int this_note = *this_notept;
- int newbank, newnote;
-
- if (!this_kit)
- {
- if (banknum == SFXBANK && tonebank[SFXBANK])
- {
- return;
- }
- if (banknum == SFXBANK && tonebank[120])
- {
- *banknumpt = 120;
- }
- return;
- }
- if (this_kit != 127 && this_kit != 126)
- {
- return;
- }
- for (i = 0; i < XMAPMAX; i++)
- {
- newmap = xmap[i][0];
- if (!newmap) return;
- if (this_kit == 127 && newmap != XGDRUM) continue;
- if (this_kit == 126 && newmap != SFXDRUM1) continue;
- if (xmap[i][1] != banknum) continue;
- if (xmap[i][3] != this_note) continue;
- newbank = xmap[i][2];
- newnote = xmap[i][4];
- if (newbank == banknum && newnote == this_note) return;
- if (!drumset[newbank]) return;
- if (!drumset[newbank]->tone[newnote].layer) return;
- if (drumset[newbank]->tone[newnote].layer == MAGIC_LOAD_INSTRUMENT) return;
- *banknumpt = newbank;
- *this_notept = newnote;
- return;
- }
-}
-
-
-void Renderer::start_note(int ch, int this_note, int this_velocity, int i)
-{
- InstrumentLayer *lp;
Instrument *ip;
- int j, banknum;
- int played_note, drumpan = NO_PANNING;
- int rt;
- int attacktime, releasetime, decaytime, variationbank;
- int brightness = channel[ch].brightness;
- int harmoniccontent = channel[ch].harmoniccontent;
- int drumsflag = channel[ch].kit;
- int this_prog = channel[ch].program;
+ int bank = channel[chan].bank;
+ int prog = channel[chan].program;
- if (channel[ch].sfx)
+ if (ISDRUMCHANNEL(chan))
{
- banknum = channel[ch].sfx;
- }
- else
- {
- banknum = channel[ch].bank;
- }
-
- voice[i].velocity = this_velocity;
-
- if (XG_System_On) xremap(&banknum, &this_note, drumsflag);
- /* if (current_config_pc42b) pcmap(&banknum, &this_note, &this_prog, &drumsflag); */
-
- if (drumsflag)
- {
- if (NULL == drumset[banknum] || NULL == (lp = drumset[banknum]->tone[this_note].layer))
+ if (NULL == drumset[bank] || NULL == (ip = drumset[bank]->instrument[note]))
{
- if (!(lp = drumset[0]->tone[this_note].layer))
+ if (!(ip = drumset[0]->instrument[note]))
return; /* No instrument? Then we can't play. */
}
- ip = lp->instrument;
if (ip->type == INST_GUS && ip->samples != 1)
{
cmsg(CMSG_WARNING, VERB_VERBOSE,
"Strange: percussion instrument with %d samples!", ip->samples);
}
-
- if (ip->sample->note_to_use) /* Do we have a fixed pitch? */
- {
- voice[i].orig_frequency = note_to_freq(ip->sample->note_to_use);
- drumpan = drumpanpot[ch][(int)ip->sample->note_to_use];
- drumpan |= drumpan << 7;
- }
- else
- voice[i].orig_frequency = note_to_freq(this_note & 0x7F);
}
else
{
- if (channel[ch].program == SPECIAL_PROGRAM)
+ if (channel[chan].program == SPECIAL_PROGRAM)
{
- lp = default_instrument;
+ ip = default_instrument;
}
- else if (NULL == tonebank[channel[ch].bank] || NULL == (lp = tonebank[channel[ch].bank]->tone[channel[ch].program].layer))
+ else if (NULL == tonebank[bank] || NULL == (ip = tonebank[bank]->instrument[prog]))
{
- if (NULL == (lp = tonebank[0]->tone[this_prog].layer))
+ if (NULL == (ip = tonebank[0]->instrument[prog]))
return; /* No instrument? Then we can't play. */
}
- ip = lp->instrument;
- if (ip->sample->note_to_use) /* Fixed-pitch instrument? */
- voice[i].orig_frequency = note_to_freq(ip->sample->note_to_use);
- else
- voice[i].orig_frequency = note_to_freq(this_note & 0x7F);
}
+ if (ip->sample->scale_factor != 1024)
+ {
+ voice[i].orig_frequency = calculate_scaled_frequency(ip->sample, note & 0x7F);
+ }
+ else
+ {
+ voice[i].orig_frequency = note_to_freq(note & 0x7F);
+ }
+ select_sample(i, ip, vel);
- select_stereo_samples(i, lp, this_velocity);
-
- played_note = voice[i].sample->note_to_use;
-
- if (!played_note || !drumsflag) played_note = this_note & 0x7f;
-#if 0
- played_note = ( (played_note - voice[i].sample->freq_center) * voice[i].sample->freq_scale ) / 1024 +
- voice[i].sample->freq_center;
-#endif
voice[i].status = VOICE_ON;
- voice[i].channel = ch;
- voice[i].note = played_note;
- voice[i].velocity = this_velocity;
+ voice[i].channel = chan;
+ voice[i].note = note;
+ voice[i].velocity = vel;
voice[i].sample_offset = 0;
voice[i].sample_increment = 0; /* make sure it isn't negative */
@@ -953,160 +279,25 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i)
voice[i].vibrato_sweep = voice[i].sample->vibrato_sweep_increment;
voice[i].vibrato_sweep_position = 0;
- voice[i].vibrato_depth = voice[i].sample->vibrato_depth;
voice[i].vibrato_control_ratio = voice[i].sample->vibrato_control_ratio;
- voice[i].vibrato_control_counter = voice[i].vibrato_phase=0;
-// voice[i].vibrato_delay = voice[i].sample->vibrato_delay;
+ voice[i].vibrato_control_counter = voice[i].vibrato_phase = 0;
- kill_others(i);
+ kill_key_group(i);
- for (j = 0; j < VIBRATO_SAMPLE_INCREMENTS; j++)
- voice[i].vibrato_sample_increment[j] = 0;
+ memset(voice[i].vibrato_sample_increment, 0, sizeof(voice[i].vibrato_sample_increment));
- attacktime = channel[ch].attacktime;
- releasetime = channel[ch].releasetime;
- decaytime = 64;
- variationbank = channel[ch].variationbank;
-
- switch (variationbank)
+ if (channel[chan].panning != NO_PANNING)
{
- case 8:
- attacktime = 64+32;
- break;
- case 12:
- decaytime = 64-32;
- break;
- case 16:
- brightness = 64+16;
- break;
- case 17:
- brightness = 64+32;
- break;
- case 18:
- brightness = 64-16;
- break;
- case 19:
- brightness = 64-32;
- break;
- case 20:
- harmoniccontent = 64+16;
- break;
-#if 0
- case 24:
- voice[i].modEnvToFilterFc=2.0;
- voice[i].sample->cutoff_freq = 800;
- break;
- case 25:
- voice[i].modEnvToFilterFc=-2.0;
- voice[i].sample->cutoff_freq = 800;
- break;
- case 27:
- voice[i].modLfoToFilterFc=2.0;
- voice[i].lfo_phase_increment=109;
- voice[i].lfo_sweep=122;
- voice[i].sample->cutoff_freq = 800;
- break;
- case 28:
- voice[i].modLfoToFilterFc=-2.0;
- voice[i].lfo_phase_increment=109;
- voice[i].lfo_sweep=122;
- voice[i].sample->cutoff_freq = 800;
- break;
-#endif
- default:
- break;
- }
-
- for (j = ATTACK; j < MAXPOINT; j++)
- {
- voice[i].envelope_rate[j] = voice[i].sample->envelope_rate[j];
- voice[i].envelope_offset[j] = voice[i].sample->envelope_offset[j];
- }
-
- voice[i].echo_delay = voice[i].envelope_rate[DELAY];
- voice[i].echo_delay_count = voice[i].echo_delay;
-
- if (attacktime != 64)
- {
- rt = voice[i].envelope_rate[ATTACK];
- rt = rt + ( (64-attacktime)*rt ) / 100;
- if (rt > 1000)
- {
- voice[i].envelope_rate[ATTACK] = rt;
- }
- }
- if (releasetime != 64)
- {
- rt = voice[i].envelope_rate[RELEASE];
- rt = rt + ( (64-releasetime)*rt ) / 100;
- if (rt > 1000)
- {
- voice[i].envelope_rate[RELEASE] = rt;
- }
- }
- if (decaytime != 64)
- {
- rt = voice[i].envelope_rate[DECAY];
- rt = rt + ( (64-decaytime)*rt ) / 100;
- if (rt > 1000)
- {
- voice[i].envelope_rate[DECAY] = rt;
- }
- }
-
- if (channel[ch].panning != NO_PANNING)
- {
- voice[i].panning = channel[ch].panning;
+ voice[i].panning = channel[chan].panning;
}
else
{
voice[i].panning = voice[i].sample->panning;
}
- if (drumpan != NO_PANNING)
- {
- voice[i].panning = drumpan;
- }
-
- if (variationbank == 1)
- {
- int pan = voice[i].panning;
- int disturb = 0;
- /* If they're close up (no reverb) and you are behind the pianist,
- * high notes come from the right, so we'll spread piano etc. notes
- * out horizontally according to their pitches.
- */
- if (this_prog < 21)
- {
- int n = voice[i].velocity - 32;
- if (n < 0) n = 0;
- if (n > 64) n = 64;
- pan = pan/2 + n;
- }
- /* For other types of instruments, the music sounds more alive if
- * notes come from slightly different directions. However, instruments
- * do drift around in a sometimes disconcerting way, so the following
- * might not be such a good idea.
- */
- else
- {
- disturb = (voice[i].velocity/32 % 8) + (voice[i].note % 8); /* /16? */
- }
-
- if (pan < 64)
- {
- pan += disturb;
- }
- else
- {
- pan -= disturb;
- }
- pan = pan < 0 ? 0 : pan > 127 ? 127 : pan;
- voice[i].panning = pan | (pan << 7);
- }
recompute_freq(i);
recompute_amp(&voice[i]);
- if (voice[i].sample->modes & MODES_ENVELOPE)
+ if (voice[i].sample->modes & PATCH_NO_SRELEASE)
{
/* Ramp up from 0 */
voice[i].envelope_stage = ATTACK;
@@ -1119,25 +310,13 @@ void Renderer::start_note(int ch, int this_note, int this_velocity, int i)
voice[i].envelope_increment = 0;
}
apply_envelope_to_amp(&voice[i]);
-
- voice[i].clone_voice = -1;
- voice[i].clone_type = NOT_CLONE;
-
- clone_voice(ip, i, this_note, this_velocity, STEREO_CLONE, variationbank);
- clone_voice(ip, i, this_note, this_velocity, CHORUS_CLONE, variationbank);
- clone_voice(ip, i, this_note, this_velocity, REVERB_CLONE, variationbank);
}
void Renderer::kill_note(int i)
{
voice[i].status = VOICE_DIE;
- if (voice[i].clone_voice >= 0)
- {
- voice[ voice[i].clone_voice ].status = VOICE_DIE;
- }
}
-
/* Only one instance of a note can be playing on a single channel. */
void Renderer::note_on(int chan, int note, int vel)
{
@@ -1150,7 +329,7 @@ void Renderer::note_on(int chan, int note, int vel)
{
lowest = i; /* Can't get a lower volume than silence */
}
- else if (voice[i].channel == chan && (voice[i].note == note || channel[chan].mono))
+ else if (voice[i].channel == chan && ((voice[i].note == note && !voice[i].sample->self_nonexclusive) || channel[chan].mono))
{
kill_note(i);
}
@@ -1169,10 +348,7 @@ void Renderer::note_on(int chan, int note, int vel)
i = voices;
while (i--)
{
- if ( (voice[i].status != VOICE_ON &&
- voice[i].status != VOICE_DIE &&
- voice[i].status != VOICE_FREE) &&
- (!voice[i].clone_type))
+ if (voice[i].status != VOICE_ON && voice[i].status != VOICE_DIE)
{
v = voice[i].left_mix;
if ((voice[i].panned == PANNED_MYSTERY) && (voice[i].right_mix > v))
@@ -1190,25 +366,10 @@ void Renderer::note_on(int chan, int note, int vel)
if (lowest != -1)
{
- int cl = voice[lowest].clone_voice;
-
/* This can still cause a click, but if we had a free voice to
- spare for ramping down this note, we wouldn't need to kill it
- in the first place... Still, this needs to be fixed. Perhaps
- we could use a reserve of voices to play dying notes only. */
-
- if (cl >= 0)
- {
- if (voice[cl].clone_type == STEREO_CLONE ||
- (!voice[cl].clone_type && voice[lowest].clone_type == STEREO_CLONE))
- {
- voice[cl].status = VOICE_FREE;
- }
- else if (voice[cl].clone_voice == lowest)
- {
- voice[cl].clone_voice = -1;
- }
- }
+ spare for ramping down this note, we wouldn't need to kill it
+ in the first place... Still, this needs to be fixed. Perhaps
+ we could use a reserve of voices to play dying notes only. */
cut_notes++;
voice[lowest].status = VOICE_FREE;
@@ -1222,7 +383,7 @@ void Renderer::note_on(int chan, int note, int vel)
void Renderer::finish_note(int i)
{
- if (voice[i].sample->modes & MODES_ENVELOPE)
+ if (voice[i].sample->modes & PATCH_NO_SRELEASE)
{
/* We need to get the envelope out of Sustain stage */
voice[i].envelope_stage = RELEASE;
@@ -1233,22 +394,15 @@ void Renderer::finish_note(int i)
else
{
/* Set status to OFF so resample_voice() will let this voice out
- of its loop, if any. In any case, this voice dies when it
- hits the end of its data (ofs>=data_length). */
+ of its loop, if any. In any case, this voice dies when it
+ hits the end of its data (ofs >= data_length). */
voice[i].status = VOICE_OFF;
}
-
- int v;
- if ( (v = voice[i].clone_voice) >= 0)
- {
- voice[i].clone_voice = -1;
- finish_note(v);
- }
}
void Renderer::note_off(int chan, int note, int vel)
{
- int i = voices, v;
+ int i = voices;
while (i--)
{
if (voice[i].status == VOICE_ON &&
@@ -1258,32 +412,28 @@ void Renderer::note_off(int chan, int note, int vel)
if (channel[chan].sustain)
{
voice[i].status = VOICE_SUSTAINED;
-
- if ( (v = voice[i].clone_voice) >= 0)
- {
- if (voice[v].status == VOICE_ON)
- voice[v].status = VOICE_SUSTAINED;
- }
}
else
{
finish_note(i);
}
- return;
+ if (!voice[i].sample->self_nonexclusive)
+ {
+ return;
+ }
}
}
}
/* Process the All Notes Off event */
-void Renderer::all_notes_off(int c)
+void Renderer::all_notes_off(int chan)
{
int i = voices;
- cmsg(CMSG_INFO, VERB_DEBUG, "All notes off on channel %d", c);
while (i--)
{
- if (voice[i].status == VOICE_ON && voice[i].channel == c)
+ if (voice[i].status == VOICE_ON && voice[i].channel == chan)
{
- if (channel[c].sustain)
+ if (channel[chan].sustain)
{
voice[i].status = VOICE_SUSTAINED;
}
@@ -1296,12 +446,12 @@ void Renderer::all_notes_off(int c)
}
/* Process the All Sounds Off event */
-void Renderer::all_sounds_off(int c)
+void Renderer::all_sounds_off(int chan)
{
int i = voices;
while (i--)
{
- if (voice[i].channel == c &&
+ if (voice[i].channel == chan &&
voice[i].status != VOICE_FREE &&
voice[i].status != VOICE_DIE)
{
@@ -1322,55 +472,59 @@ void Renderer::adjust_pressure(int chan, int note, int amount)
voice[i].velocity = amount;
recompute_amp(&voice[i]);
apply_envelope_to_amp(&voice[i]);
- return;
+ if (!(voice[i].sample->self_nonexclusive))
+ {
+ return;
+ }
}
}
}
-void Renderer::adjust_panning(int c)
+void Renderer::adjust_panning(int chan)
{
int i = voices;
while (i--)
{
- if ((voice[i].channel == c) &&
+ if ((voice[i].channel == chan) &&
(voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED))
{
- if (voice[i].clone_type != NOT_CLONE) continue;
- voice[i].panning = channel[c].panning;
+ voice[i].panning = channel[chan].panning;
recompute_amp(&voice[i]);
apply_envelope_to_amp(&voice[i]);
}
}
}
-void Renderer::drop_sustain(int c)
+void Renderer::drop_sustain(int chan)
{
int i = voices;
while (i--)
{
- if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == c)
+ if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == chan)
+ {
finish_note(i);
+ }
}
}
-void Renderer::adjust_pitchbend(int c)
+void Renderer::adjust_pitchbend(int chan)
{
int i = voices;
while (i--)
{
- if (voice[i].status != VOICE_FREE && voice[i].channel == c)
+ if (voice[i].status != VOICE_FREE && voice[i].channel == chan)
{
recompute_freq(i);
}
}
}
-void Renderer::adjust_volume(int c)
+void Renderer::adjust_volume(int chan)
{
int i = voices;
while (i--)
{
- if (voice[i].channel == c &&
+ if (voice[i].channel == chan &&
(voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED))
{
recompute_amp(&voice[i]);
@@ -1387,7 +541,6 @@ void Renderer::HandleEvent(int status, int parm1, int parm2)
switch (command)
{
case ME_NOTEON:
- parm1 += channel[chan].transpose;
if (parm2 == 0)
{
note_off(chan, parm1, 0);
@@ -1399,7 +552,6 @@ void Renderer::HandleEvent(int status, int parm1, int parm2)
break;
case ME_NOTEOFF:
- parm1 += channel[chan].transpose;
note_off(chan, parm1, parm2);
break;
@@ -1412,8 +564,8 @@ void Renderer::HandleEvent(int status, int parm1, int parm2)
break;
case ME_PROGRAM:
- /* if (ISDRUMCHANNEL(chan)) { */
- if (channel[chan].kit) {
+ if (ISDRUMCHANNEL(chan))
+ {
/* Change drum set */
channel[chan].bank = parm1;
}
@@ -1447,29 +599,13 @@ void Renderer::HandleController(int chan, int ctrl, int val)
continuous controller. This will cause lots of
warnings about undefined tone banks. */
case CTRL_BANK_SELECT:
- if (XG_System_On)
- {
- if (val == SFX_BANKTYPE)
- {
- channel[chan].sfx = SFXBANK;
- channel[chan].kit = 0;
- }
- else
- {
- channel[chan].sfx = 0;
- channel[chan].kit = val;
- }
- }
- else
- {
- channel[chan].bank = val;
- }
+ channel[chan].bank = val;
break;
case CTRL_BANK_SELECT+32:
- if (XG_System_On)
+ if (val == 0)
{
- channel[chan].bank = val;
+ channel[chan].bank = 0;
}
break;
@@ -1495,18 +631,12 @@ void Renderer::HandleController(int chan, int ctrl, int val)
case CTRL_PAN:
channel[chan].panning = (channel[chan].panning & 0x007F) | (val << 7);
- if (adjust_panning_immediately)
- {
- adjust_panning(chan);
- }
+ adjust_panning(chan);
break;
case CTRL_PAN+32:
channel[chan].panning = (channel[chan].panning & 0x3F80) | (val);
- if (adjust_panning_immediately)
- {
- adjust_panning(chan);
- }
+ adjust_panning(chan);
break;
case CTRL_SUSTAIN:
@@ -1517,30 +647,6 @@ void Renderer::HandleController(int chan, int ctrl, int val)
}
break;
- case CTRL_HARMONICCONTENT:
- channel[chan].harmoniccontent = val;
- break;
-
- case CTRL_RELEASETIME:
- channel[chan].releasetime = val;
- break;
-
- case CTRL_ATTACKTIME:
- channel[chan].attacktime = val;
- break;
-
- case CTRL_BRIGHTNESS:
- channel[chan].brightness = val;
- break;
-
- case CTRL_REVERBERATION:
- channel[chan].reverberation = val;
- break;
-
- case CTRL_CHORUSDEPTH:
- channel[chan].chorusdepth = val;
- break;
-
case CTRL_NRPN_LSB:
channel[chan].nrpn = (channel[chan].nrpn & 0x3F80) | (val);
channel[chan].nrpn_mode = true;
@@ -1623,47 +729,12 @@ void Renderer::DataEntryFineRPN(int chan, int rpn, int val)
}
}
-// [RH] Q. What device are we pretending to be by responding to these NRPNs?
void Renderer::DataEntryCoarseNRPN(int chan, int nrpn, int val)
{
- switch (nrpn & 0x3F80)
- {
- case 0x0080:
- if (nrpn == NRPN_BRIGHTNESS)
- {
- channel[chan].brightness = val;
- }
- else if (nrpn == NRPN_HARMONICCONTENT)
- {
- channel[chan].harmoniccontent = val;
- }
- break;
-
- case NRPN_DRUMVOLUME:
- drumvolume[chan][nrpn & 0x007F] = val;
- break;
-
- case NRPN_DRUMPANPOT:
- if (val == 0)
- {
- val = 127 * rand() / RAND_MAX;
- }
- drumpanpot[chan][nrpn & 0x007F] = val;
- break;
-
- case NRPN_DRUMREVERBERATION:
- drumreverberation[chan][nrpn & 0x007F] = val;
- break;
-
- case NRPN_DRUMCHORUSDEPTH:
- drumchorusdepth[chan][nrpn & 0x007F] = val;
- break;
- }
}
void Renderer::DataEntryFineNRPN(int chan, int nrpn, int val)
{
- // We don't care about fine data entry for any NRPN at this time.
}
void Renderer::HandleLongMessage(const BYTE *data, int len)
@@ -1673,25 +744,7 @@ void Renderer::HandleLongMessage(const BYTE *data, int len)
void Renderer::Reset()
{
- int i;
-
lost_notes = cut_notes = 0;
- GM_System_On = GS_System_On = XG_System_On = 0;
- XG_System_reverb_type = XG_System_chorus_type = XG_System_variation_type = 0;
- memset(&drumvolume, -1, sizeof(drumvolume));
- memset(&drumchorusdepth, -1, sizeof(drumchorusdepth));
- memset(&drumreverberation, -1, sizeof(drumreverberation));
- memset(&drumpanpot, NO_PANNING, sizeof(drumpanpot));
- for (i = 0; i < MAXCHAN; ++i)
- {
- channel[i].kit = ISDRUMCHANNEL(i) ? 127 : 0;
- channel[i].brightness = 64;
- channel[i].harmoniccontent = 64;
- channel[i].variationbank = 0;
- channel[i].chorusdepth = 0;
- channel[i].reverberation = 0;
- channel[i].transpose = 0;
- }
reset_midi();
}
diff --git a/src/timidity/resample.cpp b/src/timidity/resample.cpp
index 13180da9..5569eea5 100644
--- a/src/timidity/resample.cpp
+++ b/src/timidity/resample.cpp
@@ -215,12 +215,12 @@ static sample_t *rs_bidir(sample_t *resample_buffer, Voice *vp, int count)
/* We only need to compute one half of the vibrato sine cycle */
static int vib_phase_to_inc_ptr(int phase)
{
- if (phase < VIBRATO_SAMPLE_INCREMENTS/2)
- return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
- else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
- return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
+ if (phase < VIBRATO_SAMPLE_INCREMENTS / 2)
+ return VIBRATO_SAMPLE_INCREMENTS / 2 - 1 - phase;
+ else if (phase >= VIBRATO_SAMPLE_INCREMENTS * 3 / 2)
+ return VIBRATO_SAMPLE_INCREMENTS * 5 / 2 - 1 - phase;
else
- return phase-VIBRATO_SAMPLE_INCREMENTS/2;
+ return phase - VIBRATO_SAMPLE_INCREMENTS / 2;
}
static int update_vibrato(float output_rate, Voice *vp, int sign)
@@ -229,8 +229,8 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
int phase;
double a, pb;
- if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1)
- vp->vibrato_phase=0;
+ if (vp->vibrato_phase++ >= 2 * VIBRATO_SAMPLE_INCREMENTS - 1)
+ vp->vibrato_phase = 0;
phase = vib_phase_to_inc_ptr(vp->vibrato_phase);
if (vp->vibrato_sample_increment[phase])
@@ -244,7 +244,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
/* Need to compute this sample increment. */
depth = vp->sample->vibrato_depth << 7;
- if (vp->vibrato_sweep)
+ if (vp->vibrato_sweep != 0)
{
/* Need to update sweep */
vp->vibrato_sweep_position += vp->vibrato_sweep;
@@ -265,7 +265,7 @@ static int update_vibrato(float output_rate, Voice *vp, int sign)
pb = (sine(vp->vibrato_phase * (1.0/(2*VIBRATO_SAMPLE_INCREMENTS)))
* (double)(depth) * VIBRATO_AMPLITUDE_TUNING);
- a *= pow(2.0, pb / (8191 * 12.f));
+ a *= pow(2.0, pb / (8192 * 12.f));
/* If the sweep's over, we can store the newly computed sample_increment */
if (!vp->vibrato_sweep)
@@ -511,11 +511,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
if (vp->vibrato_control_ratio)
{
- if ((modes & MODES_LOOPING) &&
- ((modes & MODES_ENVELOPE) ||
+ if ((modes & PATCH_LOOPEN) &&
+ ((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
{
- if (modes & MODES_PINGPONG)
+ if (modes & PATCH_BIDIR)
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
else
return rs_vib_loop(song->resample_buffer, song->rate, vp, *countptr);
@@ -527,11 +527,11 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
}
else
{
- if ((modes & MODES_LOOPING) &&
- ((modes & MODES_ENVELOPE) ||
+ if ((modes & PATCH_LOOPEN) &&
+ ((modes & PATCH_NO_SRELEASE) ||
(vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED)))
{
- if (modes & MODES_PINGPONG)
+ if (modes & PATCH_BIDIR)
return rs_bidir(song->resample_buffer, vp, *countptr);
else
return rs_loop(song->resample_buffer, vp, *countptr);
@@ -554,11 +554,14 @@ void pre_resample(Renderer *song, Sample *sp)
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
};
- cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
- sp->note_to_use,
- note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
+ if (sp->scale_factor != 0)
+ return;
- a = (sp->sample_rate * note_to_freq(sp->note_to_use)) / (sp->root_freq * song->rate);
+ cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)\n",
+ sp->scale_note,
+ note_name[sp->scale_note % 12], (sp->scale_note & 0x7F) / 12);
+
+ a = (sp->sample_rate * note_to_freq(sp->scale_note)) / (sp->root_freq * song->rate);
if (a <= 0)
return;
newlen = (int)(sp->data_length / a);
diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp
index 19fd0cdd..24c4725d 100644
--- a/src/timidity/timidity.cpp
+++ b/src/timidity/timidity.cpp
@@ -413,6 +413,13 @@ void FreeAll()
int LoadConfig(const char *filename)
{
+ /* !!! FIXME: This may be ugly, but slightly less so than requiring the
+ * default search path to have only one element. I think.
+ *
+ * We only need to include the likely locations for the config
+ * file itself since that file should contain any other directory
+ * that needs to be added to the search path.
+ */
clear_pathlist();
#ifdef _WIN32
add_to_pathlist("C:\\TIMIDITY");
@@ -443,25 +450,21 @@ Renderer::Renderer(float sample_rate)
{
rate = sample_rate;
patches = NULL;
- default_instrument = NULL;
-#ifdef FAST_DECAY
- fast_decay = true;
-#else
- fast_decay = false;
-#endif
resample_buffer_size = 0;
resample_buffer = NULL;
+ adjust_panning_immediately = false;
control_ratio = clamp(int(rate / CONTROLS_PER_SECOND), 1, MAX_CONTROL_RATIO);
+
+ lost_notes = 0;
+ cut_notes = 0;
+
+ default_instrument = NULL;
+ default_program = DEFAULT_PROGRAM;
if (def_instr_name.IsNotEmpty())
set_default_instrument(def_instr_name);
voices = DEFAULT_VOICES;
- memset(voice, 0, sizeof(voice));
- memset(drumvolume, 0, sizeof(drumvolume));
- memset(drumpanpot, 0, sizeof(drumpanpot));
- memset(drumreverberation, 0, sizeof(drumreverberation));
- memset(drumchorusdepth, 0, sizeof(drumchorusdepth));
drumchannels = DEFAULT_DRUMCHANNELS;
}
@@ -492,22 +495,7 @@ void Renderer::ComputeOutput(float *buffer, int count)
{
if (v->status != VOICE_FREE)
{
- if (v->sample_offset == 0 && v->echo_delay_count)
- {
- if (v->echo_delay_count >= count)
- {
- v->echo_delay_count -= count;
- }
- else
- {
- mix_voice(this, buffer + v->echo_delay_count, v, count - v->echo_delay_count);
- v->echo_delay_count = 0;
- }
- }
- else
- {
- mix_voice(this, buffer, v, count);
- }
+ mix_voice(this, buffer, v, count);
}
}
}
@@ -520,6 +508,11 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{
return;
}
+ if (banknum != 0)
+ {
+ /* Mark the standard bank in case it's not defined by this one. */
+ MarkInstrument(0, percussion, instr);
+ }
if (percussion)
{
bank = drumset[banknum];
@@ -532,9 +525,9 @@ void Renderer::MarkInstrument(int banknum, int percussion, int instr)
{
return;
}
- if (bank->tone[instr].layer == NULL)
+ if (bank->instrument[instr] == NULL)
{
- bank->tone[instr].layer = MAGIC_LOAD_INSTRUMENT;
+ bank->instrument[instr] = MAGIC_LOAD_INSTRUMENT;
}
}
@@ -557,9 +550,6 @@ void cmsg(int type, int verbosity_level, const char *fmt, ...)
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
- size_t l = strlen(buf);
- buf[l] = '\n';
- buf[l+1] = '\0';
OutputDebugString(buf);
#endif
}
diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h
index 4ba2233b..2fbfb684 100644
--- a/src/timidity/timidity.h
+++ b/src/timidity/timidity.h
@@ -33,33 +33,27 @@ config.h
*/
/* Acoustic Grand Piano seems to be the usual default instrument. */
-#define DEFAULT_PROGRAM 0
+#define DEFAULT_PROGRAM 0
/* 9 here is MIDI channel 10, which is the standard percussion channel.
Some files (notably C:\WINDOWS\CANYON.MID) think that 16 is one too.
On the other hand, some files know that 16 is not a drum channel and
try to play music on it. This is now a runtime option, so this isn't
a critical choice anymore. */
-#define DEFAULT_DRUMCHANNELS (1<<9)
-/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
+#define DEFAULT_DRUMCHANNELS (1<<9)
+/*#define DEFAULT_DRUMCHANNELS ((1<<9) | (1<<15))*/
-/* Default sampling rate, default polyphony, and maximum polyphony.
- All but the last can be overridden from the command line. */
-#define DEFAULT_RATE 32000
-#define DEFAULT_VOICES 32
-#define MAX_VOICES 256
-#define MAXCHAN 16
-#define MAXNOTE 128
+/* Default polyphony, and maximum polyphony. */
+#define DEFAULT_VOICES 32
+#define MAX_VOICES 256
+
+#define MAXCHAN 16
+#define MAXNOTE 128
/* 1000 here will give a control ratio of 22:1 with 22 kHz output.
Higher CONTROLS_PER_SECOND values allow more accurate rendering
of envelopes and tremolo. The cost is CPU time. */
-#define CONTROLS_PER_SECOND 1000
-
-/* Make envelopes twice as fast. Saves ~20% CPU time (notes decay
- faster) and sounds more like a GUS. There is now a command line
- option to toggle this as well. */
-//#define FAST_DECAY
+#define CONTROLS_PER_SECOND 1000
/* How many bits to use for the fractional part of sample positions.
This affects tonal accuracy. The entire position counter must fit
@@ -67,7 +61,7 @@ config.h
a sample is 1048576 samples (2 megabytes in memory). The GUS gets
by with just 9 bits and a little help from its friends...
"The GUS does not SUCK!!!" -- a happy user :) */
-#define FRACTION_BITS 12
+#define FRACTION_BITS 12
/* For some reason the sample volume is always set to maximum in all
patch files. Define this for a crude adjustment that may help
@@ -76,7 +70,7 @@ config.h
/* The number of samples to use for ramping out a dying note. Affects
click removal. */
-#define MAX_DIE_TIME 20
+#define MAX_DIE_TIME 20
/**************************************************************************/
/* Anything below this shouldn't need to be changed unless you're porting
@@ -84,37 +78,37 @@ config.h
/**************************************************************************/
/* change FRACTION_BITS above, not these */
-#define INTEGER_BITS (32 - FRACTION_BITS)
-#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
-#define FRACTION_MASK (~ INTEGER_MASK)
-#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS)
+#define INTEGER_BITS (32 - FRACTION_BITS)
+#define INTEGER_MASK (0xFFFFFFFF << FRACTION_BITS)
+#define FRACTION_MASK (~ INTEGER_MASK)
+#define MAX_SAMPLE_SIZE (1 << INTEGER_BITS)
/* This is enforced by some computations that must fit in an int */
-#define MAX_CONTROL_RATIO 255
+#define MAX_CONTROL_RATIO 255
-#define MAX_AMPLIFICATION 800
+#define MAX_AMPLIFICATION 800
/* The TiMiditiy configuration file */
#define CONFIG_FILE "timidity.cfg"
typedef float sample_t;
typedef float final_volume_t;
-#define FINAL_VOLUME(v) (v)
+#define FINAL_VOLUME(v) (v)
-#define FSCALE(a,b) ((a) * (float)(1<<(b)))
-#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b))))
+#define FSCALE(a,b) ((a) * (float)(1<<(b)))
+#define FSCALENEG(a,b) ((a) * (1.0L / (float)(1<<(b))))
/* Vibrato and tremolo Choices of the Day */
-#define SWEEP_TUNING 38
-#define VIBRATO_AMPLITUDE_TUNING 1.0L
-#define VIBRATO_RATE_TUNING 38
-#define TREMOLO_AMPLITUDE_TUNING 1.0L
-#define TREMOLO_RATE_TUNING 38
+#define SWEEP_TUNING 38
+#define VIBRATO_AMPLITUDE_TUNING 1.0
+#define VIBRATO_RATE_TUNING 38
+#define TREMOLO_AMPLITUDE_TUNING 1.0
+#define TREMOLO_RATE_TUNING 38
-#define SWEEP_SHIFT 16
-#define RATE_SHIFT 5
+#define SWEEP_SHIFT 16
+#define RATE_SHIFT 5
-#define VIBRATO_SAMPLE_INCREMENTS 32
+#define VIBRATO_SAMPLE_INCREMENTS 32
#ifndef PI
#define PI 3.14159265358979323846
@@ -188,21 +182,20 @@ FileReader *open_filereader(const char *name, int open, int *plumpnum);
controls.h
*/
-#define CMSG_INFO 0
-#define CMSG_WARNING 1
-#define CMSG_ERROR 2
-#define CMSG_FATAL 3
-#define CMSG_TRACE 4
-#define CMSG_TIME 5
-#define CMSG_TOTAL 6
-#define CMSG_FILE 7
-#define CMSG_TEXT 8
+enum
+{
+ CMSG_INFO,
+ CMSG_WARNING,
+ CMSG_ERROR
+};
-#define VERB_NORMAL 0
-#define VERB_VERBOSE 1
-#define VERB_NOISY 2
-#define VERB_DEBUG 3
-#define VERB_DEBUG_SILLY 4
+enum
+{
+ VERB_NORMAL,
+ VERB_VERBOSE,
+ VERB_NOISY,
+ VERB_DEBUG
+};
void cmsg(int type, int verbosity_level, const char *fmt, ...);
@@ -217,114 +210,174 @@ struct Sample
loop_start, loop_end, data_length,
sample_rate, low_vel, high_vel, low_freq, high_freq, root_freq;
SDWORD
- envelope_rate[7], envelope_offset[7];
+ envelope_rate[6], envelope_offset[6];
float
- modulation_rate[7], modulation_offset[7];
- float
- volume, resonance,
- modEnvToFilterFc, modEnvToPitch, modLfoToFilterFc;
+ volume;
sample_t *data;
SDWORD
tremolo_sweep_increment, tremolo_phase_increment,
- lfo_sweep_increment, lfo_phase_increment,
- vibrato_sweep_increment, vibrato_control_ratio,
- cutoff_freq;
+ vibrato_sweep_increment, vibrato_control_ratio;
BYTE
- reverberation, chorusdepth,
tremolo_depth, vibrato_depth,
- modes,
- attenuation;
+ modes;
WORD
- freq_center, panning;
- SBYTE
- note_to_use, exclusiveClass;
+ panning, scale_factor;
SWORD
- keyToModEnvHold, keyToModEnvDecay,
- keyToVolEnvHold, keyToVolEnvDecay;
- SDWORD
- freq_scale;
+ scale_note;
+ bool
+ self_nonexclusive;
+ BYTE
+ key_group;
};
void convert_sample_data(Sample *sample, const void *data);
void free_instruments();
-/* Bits in modes: */
-#define MODES_16BIT (1<<0)
-#define MODES_UNSIGNED (1<<1)
-#define MODES_LOOPING (1<<2)
-#define MODES_PINGPONG (1<<3)
-#define MODES_REVERSE (1<<4)
-#define MODES_SUSTAIN (1<<5)
-#define MODES_ENVELOPE (1<<6)
-#define MODES_FAST_RELEASE (1<<7)
+/* Patch definition: */
+enum
+{
+ HEADER_SIZE = 12,
+ ID_SIZE = 10,
+ DESC_SIZE = 60,
+ RESERVED_SIZE = 40,
+ PATCH_HEADER_RESERVED_SIZE = 36,
+ LAYER_RESERVED_SIZE = 40,
+ PATCH_DATA_RESERVED_SIZE = 36,
+ INST_NAME_SIZE = 16,
+ ENVELOPES = 6,
+ MAX_LAYERS = 4
+};
+#define GF1_HEADER_TEXT "GF1PATCH110"
-#define INST_GUS 0
-#define INST_SF2 1
-#define INST_DLS 2
+enum
+{
+ PATCH_16 = (1<<0),
+ PATCH_UNSIGNED = (1<<1),
+ PATCH_LOOPEN = (1<<2),
+ PATCH_BIDIR = (1<<3),
+ PATCH_BACKWARD = (1<<4),
+ PATCH_SUSTAIN = (1<<5),
+ PATCH_NO_SRELEASE = (1<<6),
+ PATCH_FAST_REL = (1<<7)
+};
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#define GCC_PACKED
+#else
+#define GCC_PACKED __attribute__((__packed__))
+#endif
+
+struct GF1PatchHeader
+{
+ char Header[HEADER_SIZE];
+ char GravisID[ID_SIZE]; /* Id = "ID#000002" */
+ char Description[DESC_SIZE];
+ BYTE Instruments;
+ BYTE Voices;
+ BYTE Channels;
+ WORD WaveForms;
+ WORD MasterVolume;
+ DWORD DataSize;
+ BYTE Reserved[PATCH_HEADER_RESERVED_SIZE];
+} GCC_PACKED;
+
+struct GF1InstrumentData
+{
+ WORD Instrument;
+ char InstrumentName[INST_NAME_SIZE];
+ int InstrumentSize;
+ BYTE Layers;
+ BYTE Reserved[RESERVED_SIZE];
+} GCC_PACKED;
+
+struct GF1LayerData
+{
+ BYTE LayerDuplicate;
+ BYTE Layer;
+ int LayerSize;
+ BYTE Samples;
+ BYTE Reserved[LAYER_RESERVED_SIZE];
+} GCC_PACKED;
+
+struct GF1PatchData
+{
+ char WaveName[7];
+ BYTE Fractions;
+ int WaveSize;
+ int StartLoop;
+ int EndLoop;
+ WORD SampleRate;
+ int LowFrequency;
+ int HighFrequency;
+ int RootFrequency;
+ SWORD Tune;
+ BYTE Balance;
+ BYTE EnvelopeRate[6];
+ BYTE EnvelopeOffset[6];
+ BYTE TremoloSweep;
+ BYTE TremoloRate;
+ BYTE TremoloDepth;
+ BYTE VibratoSweep;
+ BYTE VibratoRate;
+ BYTE VibratoDepth;
+ BYTE Modes;
+ SWORD ScaleFrequency;
+ WORD ScaleFactor; /* From 0 to 2048 or 0 to 2 */
+ BYTE Reserved[PATCH_DATA_RESERVED_SIZE];
+} GCC_PACKED;
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+#undef GCC_PACKED
+
+enum
+{
+ INST_GUS,
+ INST_DLS
+};
struct Instrument
{
+ Instrument();
+ ~Instrument();
+
int type;
int samples;
Sample *sample;
- int left_samples;
- Sample *left_sample;
- int right_samples;
- Sample *right_sample;
};
-struct InstrumentLayer
-{
- BYTE lo, hi;
- Instrument *instrument;
- InstrumentLayer *next;
-};
-
-struct cfg_type
-{
- int font_code;
- int num;
- const char *name;
-};
-
-#define FONT_NORMAL 0
-#define FONT_FFF 1
-#define FONT_SBK 2
-#define FONT_TONESET 3
-#define FONT_DRUMSET 4
-#define FONT_PRESET 5
-
struct ToneBankElement
{
- ToneBankElement() : layer(NULL), font_type(0), sf_ix(0), tuning(0),
+ ToneBankElement() :
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
{}
FString name;
- InstrumentLayer *layer;
- int font_type, sf_ix, tuning;
int note, amp, pan, strip_loop, strip_envelope, strip_tail;
};
/* A hack to delay instrument loading until after reading the
entire MIDI file. */
-#define MAGIC_LOAD_INSTRUMENT ((InstrumentLayer *)(-1))
+#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
-#define MAXPROG 128
-#define MAXBANK 130
-#define SFXBANK (MAXBANK-1)
-#define SFXDRUM1 (MAXBANK-2)
-#define SFXDRUM2 (MAXBANK-1)
-#define XGDRUM 1
+enum
+{
+ MAXPROG = 128,
+ MAXBANK = 128
+};
struct ToneBank
{
- FString name;
- ToneBankElement tone[MAXPROG];
+ ToneBank();
+ ~ToneBank();
+
+ ToneBankElement *tone;
+ Instrument *instrument[MAXPROG];
};
-#define SPECIAL_PROGRAM -1
+#define SPECIAL_PROGRAM -1
extern void pcmap(int *b, int *v, int *p, int *drums);
@@ -341,60 +394,55 @@ playmidi.h
*/
/* Midi events */
-#define ME_NOTEOFF 0x80
-#define ME_NOTEON 0x90
-#define ME_KEYPRESSURE 0xA0
-#define ME_CONTROLCHANGE 0xB0
-#define ME_PROGRAM 0xC0
-#define ME_CHANNELPRESSURE 0xD0
-#define ME_PITCHWHEEL 0xE0
+enum
+{
+ ME_NOTEOFF = 0x80,
+ ME_NOTEON = 0x90,
+ ME_KEYPRESSURE = 0xA0,
+ ME_CONTROLCHANGE = 0xB0,
+ ME_PROGRAM = 0xC0,
+ ME_CHANNELPRESSURE = 0xD0,
+ ME_PITCHWHEEL = 0xE0
+};
/* Controllers */
-#define CTRL_BANK_SELECT 0
-#define CTRL_DATA_ENTRY 6
-#define CTRL_VOLUME 7
-#define CTRL_PAN 10
-#define CTRL_EXPRESSION 11
-#define CTRL_SUSTAIN 64
-#define CTRL_HARMONICCONTENT 71
-#define CTRL_RELEASETIME 72
-#define CTRL_ATTACKTIME 73
-#define CTRL_BRIGHTNESS 74
-#define CTRL_REVERBERATION 91
-#define CTRL_CHORUSDEPTH 93
-#define CTRL_NRPN_LSB 98
-#define CTRL_NRPN_MSB 99
-#define CTRL_RPN_LSB 100
-#define CTRL_RPN_MSB 101
-#define CTRL_ALL_SOUNDS_OFF 120
-#define CTRL_RESET_CONTROLLERS 121
-#define CTRL_ALL_NOTES_OFF 123
-
-/* NRPNs */
-#define NRPN_BRIGHTNESS 0x00A0
-#define NRPN_HARMONICCONTENT 0x00A1
-#define NRPN_DRUMVOLUME (26<<7) // drum number in low 7 bits
-#define NRPN_DRUMPANPOT (28<<7) // "
-#define NRPN_DRUMREVERBERATION (29<<7) // "
-#define NRPN_DRUMCHORUSDEPTH (30<<7) // "
+enum
+{
+ CTRL_BANK_SELECT = 0,
+ CTRL_DATA_ENTRY = 6,
+ CTRL_VOLUME = 7,
+ CTRL_PAN = 10,
+ CTRL_EXPRESSION = 11,
+ CTRL_SUSTAIN = 64,
+ CTRL_HARMONICCONTENT = 71,
+ CTRL_RELEASETIME = 72,
+ CTRL_ATTACKTIME = 73,
+ CTRL_BRIGHTNESS = 74,
+ CTRL_REVERBERATION = 91,
+ CTRL_CHORUSDEPTH = 93,
+ CTRL_NRPN_LSB = 98,
+ CTRL_NRPN_MSB = 99,
+ CTRL_RPN_LSB = 100,
+ CTRL_RPN_MSB = 101,
+ CTRL_ALL_SOUNDS_OFF = 120,
+ CTRL_RESET_CONTROLLERS = 121,
+ CTRL_ALL_NOTES_OFF = 123
+};
/* RPNs */
-#define RPN_PITCH_SENS 0x0000
-#define RPN_FINE_TUNING 0x0001
-#define RPN_COARSE_TUNING 0x0002
-#define RPN_RESET 0x3fff
-
-#define SFX_BANKTYPE 64
+enum
+{
+ RPN_PITCH_SENS = 0x0000,
+ RPN_FINE_TUNING = 0x0001,
+ RPN_COARSE_TUNING = 0x0002,
+ RPN_RESET = 0x3fff
+};
struct Channel
{
int
bank, program, sustain, pitchbend,
mono, /* one note only on this channel -- not implemented yet */
- /* new stuff */
- variationbank, reverberation, chorusdepth, harmoniccontent,
- releasetime, attacktime, brightness, kit, sfx,
- /* end new */
pitchsens;
WORD
volume, expression;
@@ -404,84 +452,71 @@ struct Channel
rpn, nrpn;
bool
nrpn_mode;
- char
- transpose;
float
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
};
/* Causes the instrument's default panning to be used. */
-#define NO_PANNING -1
+#define NO_PANNING -1
/* envelope points */
-#define MAXPOINT 7
+#define MAXPOINT 6
struct Voice
{
BYTE
- status, channel, note, velocity, clone_type;
+ status, channel, note, velocity;
Sample *sample;
- Sample *left_sample;
- Sample *right_sample;
- int clone_voice;
float
orig_frequency, frequency;
int
- sample_offset, loop_start, loop_end;
- int
- envelope_volume, modulation_volume;
- int
- envelope_target, modulation_target;
- int
- tremolo_sweep, tremolo_sweep_position, tremolo_phase,
- lfo_sweep, lfo_sweep_position, lfo_phase,
- vibrato_sweep, vibrato_sweep_position, vibrato_depth,
- echo_delay_count;
- int
- echo_delay,
- sample_increment,
- envelope_increment,
- modulation_increment,
- tremolo_phase_increment,
- lfo_phase_increment;
+ sample_offset, sample_increment,
+ envelope_volume, envelope_target, envelope_increment,
+ tremolo_sweep, tremolo_sweep_position,
+ tremolo_phase, tremolo_phase_increment,
+ vibrato_sweep, vibrato_sweep_position;
final_volume_t left_mix, right_mix;
float
- left_amp, right_amp,
- volume, tremolo_volume, lfo_volume;
+ left_amp, right_amp, tremolo_volume;
int
vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS];
- int
- envelope_rate[MAXPOINT], envelope_offset[MAXPOINT];
int
vibrato_phase, vibrato_control_ratio, vibrato_control_counter,
- envelope_stage, modulation_stage, control_counter,
- modulation_delay, modulation_counter, panning, panned;
+ envelope_stage, control_counter, panning, panned;
};
/* Voice status options: */
-#define VOICE_FREE 0
-#define VOICE_ON 1
-#define VOICE_SUSTAINED 2
-#define VOICE_OFF 3
-#define VOICE_DIE 4
+enum
+{
+ VOICE_FREE,
+ VOICE_ON,
+ VOICE_SUSTAINED,
+ VOICE_OFF,
+ VOICE_DIE
+};
/* Voice panned options: */
-#define PANNED_MYSTERY 0
-#define PANNED_LEFT 1
-#define PANNED_RIGHT 2
-#define PANNED_CENTER 3
+enum
+{
+ PANNED_MYSTERY,
+ PANNED_LEFT,
+ PANNED_RIGHT,
+ PANNED_CENTER
+};
/* Anything but PANNED_MYSTERY only uses the left volume */
/* Envelope stages: */
-#define ATTACK 0
-#define HOLD 1
-#define DECAY 2
-#define RELEASE 3
-#define RELEASEB 4
-#define RELEASEC 5
-#define DELAY 6
+enum
+{
+ ATTACK,
+ HOLD,
+ DECAY,
+ RELEASE,
+ RELEASEB,
+ RELEASEC
+};
#define ISDRUMCHANNEL(c) ((drumchannels & (1<<(c))))
@@ -498,9 +533,7 @@ tables.h
#define sine(x) (sin((2*PI/1024.0) * (x)))
#define note_to_freq(x) (float(8175.7989473096690661233836992789 * pow(2.0, (x) / 12.0)))
-#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
-
-#define XMAPMAX 800
+#define calc_vol(x) (pow(2.0,((x)*6.0 - 6.0)))
/*
timidity.h
@@ -517,27 +550,16 @@ struct Renderer
{
float rate;
DLS_Data *patches;
- InstrumentLayer *default_instrument;
+ Instrument *default_instrument;
int default_program;
- bool fast_decay;
int resample_buffer_size;
sample_t *resample_buffer;
Channel channel[16];
Voice voice[MAX_VOICES];
- signed char drumvolume[MAXCHAN][MAXNOTE];
- signed char drumpanpot[MAXCHAN][MAXNOTE];
- signed char drumreverberation[MAXCHAN][MAXNOTE];
- signed char drumchorusdepth[MAXCHAN][MAXNOTE];
int control_ratio, amp_with_poly;
int drumchannels;
int adjust_panning_immediately;
int voices;
- int GM_System_On;
- int XG_System_On;
- int GS_System_On;
- int XG_System_reverb_type;
- int XG_System_chorus_type;
- int XG_System_variation_type;
int lost_notes, cut_notes;
Renderer(float sample_rate);
@@ -558,10 +580,8 @@ struct Renderer
int convert_vibrato_rate(BYTE rate);
void recompute_amp(Voice *v);
- int vc_alloc(int not_this_voice);
- void kill_others(int voice);
- void clone_voice(Instrument *ip, int v, int note, int vel, int clone_type, int variationbank);
- void xremap(int *banknumpt, int *this_notept, int this_kit);
+ void kill_key_group(int voice);
+ float calculate_scaled_frequency(Sample *sample, int note);
void start_note(int chan, int note, int vel, int voice);
void note_on(int chan, int note, int vel);
@@ -579,7 +599,6 @@ struct Renderer
void reset_midi();
void select_sample(int voice, Instrument *instr, int vel);
- void select_stereo_samples(int voice, InstrumentLayer *layer, int vel);
void recompute_freq(int voice);
void kill_note(int voice);
diff --git a/src/v_palette.cpp b/src/v_palette.cpp
index 00e3ddc5..e6f13f06 100644
--- a/src/v_palette.cpp
+++ b/src/v_palette.cpp
@@ -64,6 +64,7 @@ BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
BYTE RedColormap[256];
BYTE GreenColormap[256];
+BYTE DesaturateColormap[31][256];
static void FreeSpecialLights();;
@@ -433,6 +434,24 @@ void InitPalette ()
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
intensity>>8 );
}
+
+ // desaturated colormaps
+ for(int m = 0; m < 31; m++)
+ {
+ shade = DesaturateColormap[m];
+ for (c = 0; c < 256; c++)
+ {
+ intensity = GPalette.BaseColors[c].r * 77 +
+ GPalette.BaseColors[c].g * 143 +
+ GPalette.BaseColors[c].b * 37;
+
+ int r = (GPalette.BaseColors[c].r * (31-m) + intensity *m) / 31;
+ int g = (GPalette.BaseColors[c].g * (31-m) + intensity *m) / 31;
+ int b = (GPalette.BaseColors[c].b * (31-m) + intensity *m) / 31;
+ shade[c] = ColorMatcher.Pick (r, g, b);
+ }
+ }
+
}
extern "C"
diff --git a/src/v_palette.h b/src/v_palette.h
index 2fbe992c..c8236a38 100644
--- a/src/v_palette.h
+++ b/src/v_palette.h
@@ -85,6 +85,7 @@ extern BYTE GoldColormap[256];
// [BC] New Skulltag colormaps.
extern BYTE RedColormap[256];
extern BYTE GreenColormap[256];
+extern BYTE DesaturateColormap[31][256];
extern FPalette GPalette;
extern "C" {
extern FDynamicColormap NormalLight;
diff --git a/src/v_video.cpp b/src/v_video.cpp
index 4aa7043e..fdb351f8 100644
--- a/src/v_video.cpp
+++ b/src/v_video.cpp
@@ -1157,216 +1157,6 @@ void DFrameBuffer::WipeCleanup()
wipe_Cleanup();
}
-//===========================================================================
-//
-// multi-format pixel copy with colormap application
-// requires one of the previously defined conversion classes to work
-//
-//===========================================================================
-template
-void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step)
-{
- for(int i=0;i,
- iCopyColors,
- iCopyColors,
- iCopyColors,
- iCopyColors,
- iCopyColors,
- iCopyColors,
- iCopyColors,
- iCopyColors
-};
-
-//===========================================================================
-//
-// 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(buffer[pos+3] + (( 255-buffer[pos+3]) * (255-palette[v].a))/255, 0, 255);
- }
- }
- }
- }
-}
-
//===========================================================================
//
// Texture precaching
diff --git a/src/v_video.h b/src/v_video.h
index 68758a5e..8357a0a7 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -372,15 +372,6 @@ public:
// Create a palette texture from a remap/palette table.
virtual FNativePalette *CreatePalette(FRemapTable *remap);
- // texture copy functions
- virtual void CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
- const BYTE *patch, int pix_width, int pix_height, int step_x, int step_y,
- int rotate, int ct);
-
- virtual void CopyPixelData(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
- const BYTE *patch, int pix_width, int pix_height,
- int step_x, int step_y, int rotate, PalEntry * palette);
-
// Precaches or unloads a texture
virtual void PrecacheTexture(FTexture *tex, int cache);
@@ -405,9 +396,6 @@ private:
DWORD LastMS, LastSec, FrameCount, LastCount, LastTic;
};
-bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
- const BYTE *&patch, int &srcwidth, int &srcheight,
- int &step_x, int &step_y, int rotate);
extern FColorMatcher ColorMatcher;
@@ -478,106 +466,5 @@ int CheckRatio (int width, int height);
extern const int BaseRatioSizes[5][4];
-//===========================================================================
-//
-// True color conversion classes for the different pixel formats
-// used by the supported texture formats
-//
-//===========================================================================
-struct cRGB
-{
- static unsigned char R(const unsigned char * p) { return p[0]; }
- static unsigned char G(const unsigned char * p) { return p[1]; }
- static unsigned char B(const unsigned char * p) { return p[2]; }
- static unsigned char A(const unsigned char * p) { return 255; }
- static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
-};
-
-struct cRGBA
-{
- static unsigned char R(const unsigned char * p) { return p[0]; }
- static unsigned char G(const unsigned char * p) { return p[1]; }
- static unsigned char B(const unsigned char * p) { return p[2]; }
- static unsigned char A(const unsigned char * p) { return p[3]; }
- static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
-};
-
-struct cIA
-{
- static unsigned char R(const unsigned char * p) { return p[0]; }
- static unsigned char G(const unsigned char * p) { return p[0]; }
- static unsigned char B(const unsigned char * p) { return p[0]; }
- static unsigned char A(const unsigned char * p) { return p[1]; }
- static int Gray(const unsigned char * p) { return p[0]; }
-};
-
-struct cCMYK
-{
- static unsigned char R(const unsigned char * p) { return p[3] - (((256-p[0])*p[3]) >> 8); }
- static unsigned char G(const unsigned char * p) { return p[3] - (((256-p[1])*p[3]) >> 8); }
- static unsigned char B(const unsigned char * p) { return p[3] - (((256-p[2])*p[3]) >> 8); }
- static unsigned char A(const unsigned char * p) { return 255; }
- static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
-};
-
-struct cBGR
-{
- static unsigned char R(const unsigned char * p) { return p[2]; }
- static unsigned char G(const unsigned char * p) { return p[1]; }
- static unsigned char B(const unsigned char * p) { return p[0]; }
- static unsigned char A(const unsigned char * p) { return 255; }
- static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
-};
-
-struct cBGRA
-{
- static unsigned char R(const unsigned char * p) { return p[2]; }
- static unsigned char G(const unsigned char * p) { return p[1]; }
- static unsigned char B(const unsigned char * p) { return p[0]; }
- static unsigned char A(const unsigned char * p) { return p[3]; }
- static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
-};
-
-struct cI16
-{
- static unsigned char R(const unsigned char * p) { return p[1]; }
- static unsigned char G(const unsigned char * p) { return p[1]; }
- static unsigned char B(const unsigned char * p) { return p[1]; }
- static unsigned char A(const unsigned char * p) { return 255; }
- static int Gray(const unsigned char * p) { return p[1]; }
-};
-
-struct cRGB555
-{
- static unsigned char R(const unsigned char * p) { return (((*(WORD*)p)&0x1f)<<3); }
- static unsigned char G(const unsigned char * p) { return (((*(WORD*)p)&0x3e0)>>2); }
- static unsigned char B(const unsigned char * p) { return (((*(WORD*)p)&0x7c00)>>7); }
- static unsigned char A(const unsigned char * p) { return p[1]; }
- static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
-};
-
-struct cPalEntry
-{
- static unsigned char R(const unsigned char * p) { return ((PalEntry*)p)->r; }
- static unsigned char G(const unsigned char * p) { return ((PalEntry*)p)->g; }
- static unsigned char B(const unsigned char * p) { return ((PalEntry*)p)->b; }
- static unsigned char A(const unsigned char * p) { return ((PalEntry*)p)->a; }
- static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
-};
-
-enum ColorType
-{
- CF_RGB,
- CF_RGBA,
- CF_IA,
- CF_CMYK,
- CF_BGR,
- CF_BGRA,
- CF_I16,
- CF_RGB555,
- CF_PalEntry
-};
-
-
#endif // __V_VIDEO_H__
diff --git a/wadsrc/decorate/doom/possessed.txt b/wadsrc/decorate/doom/possessed.txt
index b255cede..62a41a80 100644
--- a/wadsrc/decorate/doom/possessed.txt
+++ b/wadsrc/decorate/doom/possessed.txt
@@ -205,6 +205,7 @@ ACTOR WolfensteinSS 84
DeathSound "wolfss/death"
ActiveSound "wolfss/active"
AttackSound "wolfss/attack"
+ Obituary "$OB_WOLFSS"
Dropitem "Clip"
States
{
diff --git a/wadsrc/decorate/nativeclasses.txt b/wadsrc/decorate/nativeclasses.txt
index 2a46114c..7b0aed67 100644
--- a/wadsrc/decorate/nativeclasses.txt
+++ b/wadsrc/decorate/nativeclasses.txt
@@ -124,7 +124,7 @@ class Actor extends Thinker
action native A_FLoopActiveSound();
action native A_LoopActiveSound();
action native A_StopSound();
- action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional bool looping, optional eval int attenuation);
+ action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional eval bool looping, optional eval int attenuation);
action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(eval int threshold, eval int turnmax);
action native A_Jump(eval int chance, state label, ...);
@@ -174,8 +174,8 @@ class Actor extends Thinker
action native A_LookEx(optional eval int flags, optional eval float minseedist, optional eval float maxseedist, optional eval float maxheardist, optional eval float fov, optional state label);
action native A_ClearTarget();
action native A_JumpIfTargetInLOS (state label, optional eval float fov);
- action native A_DamageMaster(int amount, optional name damagetype);
- action native A_DamageChildren(int amount, optional name damagetype);
+ action native A_DamageMaster(eval int amount, optional name damagetype);
+ action native A_DamageChildren(eval int amount, optional name damagetype);
action native A_SelectWeapon(class whichweapon);
action native A_Punch();
}