mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-06-04 19:20:53 +00:00
Update to ZDoom r922:
- Added Martin Howe's fixes for morphing and DECORATE function prototypes. - Minor fixes in texture code. - Fixed: The FMOD::System object was never released, only closed, so snd_reset would eventually run into the hard limit on the total number of FMOD::System objects that can be created concurrently (currently 15). - Added proper error checks to the FMOD initialization process. - Updated fmod_wrap.h for FMOD 4.14. - Set note velocity back to using a linear sounding volume curve, although it's now used to scale channel volume and expression, so recompute_amp() is still only doing one volume curve lookup. - Fixed: TimidityMIDIDevice caused a crash at the end of a non-looping song. - Made translation support for multipatch textures operational. - Added support for the GUS patch format's scale_frequency and scale_factor parameters. These seem to be used primarily to restrict percussion instruments to specific notes. - Changed note velocity to not use the volume curve in recompute_amp(), since this sounds closer to TiMidity++, although I don't believe it's correct MIDI behavior. Also changed expression so that it scales the channel volume before going through the curve. - Reworked load_instrument() to be less opaque. - Went through the TiMidity code and removed pretty much all of the SDL_mixer extensions. The only exception would be kill_others(), which I reworked into a kill_key_group() function, which should be useful for DLS instruments in the future. - Added translation support to multipatch textures. Not tested yet! - Added Martin Howe's morph weapon update. - Changed true color texture creation to use a newly defined Bitmap class instead of having the copy functions in the frame buffer class. - Fixed: The WolfSS didn't have its obituary defined. - Added submission for ACS CheckPlayerCamera ACS function. - Removed FRadiusThingsIterator after discovering that VC++ misoptimized it in P_CheckPosition. Now FBlockThingsIterator is used with the distance check being done manually. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@94 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
parent
7fef77f47b
commit
93df2a62bf
52 changed files with 1526 additions and 2628 deletions
|
@ -2654,6 +2654,14 @@
|
|||
RelativePath=".\src\textures\automaptexture.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\textures\bitmap.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\textures\bitmap.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\textures\buildtexture.cpp"
|
||||
>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,6 +268,24 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
{
|
||||
player->ReadyWeapon = player->PendingWeapon = NULL;
|
||||
}
|
||||
if (correctweapon)
|
||||
{ // Better "lose morphed weapon" semantics
|
||||
const PClass *morphweapon = PClass::FindClass (mo->MorphWeapon);
|
||||
if (morphweapon != NULL && morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
|
||||
{
|
||||
AWeapon *OriginalMorphWeapon = static_cast<AWeapon *>(mo->FindInventory (morphweapon));
|
||||
if ((OriginalMorphWeapon != NULL) && (OriginalMorphWeapon->GivenAsMorphWeapon))
|
||||
{ // You don't get to keep your morphed weapon.
|
||||
if (OriginalMorphWeapon->SisterWeapon != NULL)
|
||||
{
|
||||
OriginalMorphWeapon->SisterWeapon->Destroy ();
|
||||
}
|
||||
OriginalMorphWeapon->Destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else // old behaviour (not really useful now)
|
||||
{ // Assumptions made here are no longer valid
|
||||
if (beastweap != NULL)
|
||||
{ // You don't get to keep your morphed weapon.
|
||||
if (beastweap->SisterWeapon != NULL)
|
||||
|
@ -275,6 +294,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
}
|
||||
beastweap->Destroy ();
|
||||
}
|
||||
}
|
||||
pmo->tracer = NULL;
|
||||
pmo->Destroy ();
|
||||
// Restore playerclass armor to its normal amount.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -221,6 +221,7 @@ public:
|
|||
// In-inventory instance variables
|
||||
TObjPtr<AAmmo> Ammo1, Ammo2;
|
||||
TObjPtr<AWeapon> SisterWeapon;
|
||||
bool GivenAsMorphWeapon;
|
||||
|
||||
bool bAltFire; // Set when this weapon's alternate fire is used.
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -63,15 +63,6 @@ public:
|
|||
void Dim (PalEntry color, float damount, int x1, int y1, int w, int h);
|
||||
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false);
|
||||
|
||||
// texture copy functions
|
||||
virtual void CopyPixelDataRGB(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
|
||||
const BYTE * patch, int pix_width, int pix_height, int step_x, int step_y,
|
||||
int rotate, int ct);
|
||||
|
||||
virtual void CopyPixelData(BYTE * buffer, int texwidth, int texheight, int originx, int originy,
|
||||
const BYTE * patch, int pix_width, int pix_height,
|
||||
int step_x, int step_y, int rotate, PalEntry * palette);
|
||||
|
||||
void PrecacheTexture(FTexture *tex, bool cache);
|
||||
|
||||
// Create a native texture from a game texture.
|
||||
|
@ -81,13 +72,6 @@ public:
|
|||
void RenderView (player_t* player);
|
||||
void WriteSavePic (player_t *player, FILE *file, int width, int height);
|
||||
|
||||
|
||||
void SetTranslationInfo(int _cm, int _trans=-1337)
|
||||
{
|
||||
if (_cm != -1) cm = _cm;
|
||||
if (_trans != -1337) translation = _trans;
|
||||
}
|
||||
|
||||
bool WipeStartScreen(int type);
|
||||
void WipeEndScreen();
|
||||
bool WipeDo(int ticks);
|
||||
|
@ -96,8 +80,12 @@ public:
|
|||
|
||||
private:
|
||||
PalEntry Flash;
|
||||
|
||||
// Texture creation info
|
||||
int cm;
|
||||
int translation;
|
||||
bool iscomplex;
|
||||
|
||||
PalEntry SourcePalette[256];
|
||||
BYTE *ScreenshotBuffer;
|
||||
|
||||
|
@ -122,10 +110,5 @@ private:
|
|||
|
||||
};
|
||||
|
||||
inline void SetTranslationInfo(int _cm, int _trans=-1337)
|
||||
{
|
||||
static_cast<OpenGLFrameBuffer*>(screen)->SetTranslationInfo(_cm,_trans);
|
||||
}
|
||||
|
||||
|
||||
#endif //__GL_FRAMEBUFFER
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
void FGLBitmap::CopyPixelDataRGB(int originx, int originy,
|
||||
const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y,
|
||||
int rotate, int ct)
|
||||
int rotate, int ct, FCopyInfo *inf)
|
||||
{
|
||||
if (ClipCopyPixelRect(texpitch>>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
{
|
||||
buffer+=4*originx + texpitch*originy;
|
||||
BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
|
||||
for (int y=0;y<srcheight;y++)
|
||||
{
|
||||
copyfuncs[ct](&buffer[y*texpitch], &patch[y*step_y], cm, srcwidth, step_x);
|
||||
copyfuncs[ct](&buffer[y*Pitch], &patch[y*step_y], cm, srcwidth, step_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -444,17 +431,16 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count)
|
|||
// Paletted to True Color texture copy function
|
||||
//
|
||||
//===========================================================================
|
||||
void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
|
||||
const BYTE * patch, int srcwidth, int srcheight,
|
||||
int step_x, int step_y, int rotate, PalEntry * palette)
|
||||
void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight,
|
||||
int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf)
|
||||
{
|
||||
PalEntry penew[256];
|
||||
|
||||
int x,y,pos,i;
|
||||
|
||||
if (ClipCopyPixelRect(texpitch>>2, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
{
|
||||
buffer+=4*originx + texpitch*originy;
|
||||
BYTE *buffer = GetPixels() + 4*originx + Pitch*originy;
|
||||
|
||||
// CM_SHADE is an alpha map with 0==transparent and 1==opaque
|
||||
if (cm == CM_SHADE)
|
||||
|
@ -467,28 +453,6 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
|
|||
penew[i]=0xffffffff; // If the palette contains transparent colors keep them.
|
||||
}
|
||||
}
|
||||
else if (cm == CM_BRIGHTMAP)
|
||||
{
|
||||
if (palette == GetPalette() && translation >= 0)
|
||||
{
|
||||
for(int i=0;i<256;i++)
|
||||
{
|
||||
if (GlobalBrightmap[i] && palette[i].a==0)
|
||||
{
|
||||
penew[i] = PalEntry(0,255,255,255);
|
||||
}
|
||||
else
|
||||
{
|
||||
penew[i] = PalEntry(255,0,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0;i<256;i++)
|
||||
penew[i] = PalEntry(palette[i].a,0,0,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// apply any translation.
|
||||
|
@ -535,7 +499,7 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
|
|||
// This can also handle full PNG translucency.
|
||||
for (y=0;y<srcheight;y++)
|
||||
{
|
||||
pos=(y*texpitch);
|
||||
pos=(y*Pitch);
|
||||
for (x=0;x<srcwidth;x++,pos+=4)
|
||||
{
|
||||
int v=(unsigned char)patch[y*step_y+x*step_x];
|
||||
|
@ -568,23 +532,31 @@ void OpenGLFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_height, int xx, int yy, int rotate)
|
||||
int FWarpTexture::CopyTrueColorPixels(FBitmap *bmp, int xx, int yy, int rotate, FCopyInfo *inf)
|
||||
{
|
||||
if (gl_warp_shader || gl_glsl_renderer)
|
||||
int buf_pitch = bmp->GetPitch();
|
||||
int buf_width = bmp->GetWidth();
|
||||
int buf_height = bmp->GetHeight();
|
||||
|
||||
if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
|
||||
{
|
||||
return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
|
||||
return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
|
||||
}
|
||||
|
||||
unsigned long * in=new unsigned long[Width*Height];
|
||||
FGLBitmap inb;
|
||||
|
||||
if (!inb.Create(Width, Height))
|
||||
return false;
|
||||
|
||||
unsigned long * in = (unsigned long *)inb.GetPixels();
|
||||
unsigned long * out;
|
||||
bool direct;
|
||||
int buf_width = buf_pitch>>2;
|
||||
|
||||
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
|
||||
gltex->createWarped = true;
|
||||
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
|
||||
{
|
||||
out = (unsigned long*)buffer;
|
||||
out = (unsigned long*)bmp->GetPixels();
|
||||
direct=true;
|
||||
}
|
||||
else
|
||||
|
@ -595,9 +567,9 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
|
|||
|
||||
GenTime = r_FrameTime;
|
||||
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
|
||||
int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
|
||||
int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
|
||||
|
||||
static unsigned long linebuffer[4096]; // that's the maximum texture size for most graphics cards!
|
||||
static unsigned long linebuffer[256]; // anything larger will bring down performance so it is excluded above.
|
||||
int timebase = r_FrameTime*23/28;
|
||||
int xsize = Width;
|
||||
int ysize = Height;
|
||||
|
@ -638,7 +610,7 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
|
|||
if (xx<0) xx=0;
|
||||
if (yy<0) yy=0;
|
||||
|
||||
unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
|
||||
unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
|
||||
int linelen=MIN<int>(Width, buf_width-xx);
|
||||
int linecount=MIN<int>(Height, buf_height-yy);
|
||||
|
||||
|
@ -649,7 +621,6 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
|
|||
}
|
||||
delete [] out;
|
||||
}
|
||||
delete [] in;
|
||||
GenTime=r_FrameTime;
|
||||
return ret;
|
||||
}
|
||||
|
@ -663,23 +634,31 @@ int FWarpTexture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_heig
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_height, int xx, int yy, int rotate)
|
||||
int FWarp2Texture::CopyTrueColorPixels(FBitmap *bmp, int xx, int yy, int rotate, FCopyInfo *inf)
|
||||
{
|
||||
if (gl_warp_shader || gl_glsl_renderer)
|
||||
int buf_pitch = bmp->GetPitch();
|
||||
int buf_width = bmp->GetWidth();
|
||||
int buf_height = bmp->GetHeight();
|
||||
|
||||
if (gl_warp_shader || gl_glsl_renderer || rotate != 0 || inf != NULL || Width > 256 || Height > 256)
|
||||
{
|
||||
return SourcePic->CopyTrueColorPixels(buffer, buf_pitch, buf_height, xx, yy, rotate);
|
||||
return SourcePic->CopyTrueColorPixels(bmp, xx, yy, rotate, inf);
|
||||
}
|
||||
|
||||
unsigned long * in=new unsigned long[Width*Height];
|
||||
FGLBitmap inb;
|
||||
|
||||
if (!inb.Create(Width, Height))
|
||||
return false;
|
||||
|
||||
unsigned long * in = (unsigned long *)inb.GetPixels();
|
||||
unsigned long * out;
|
||||
bool direct;
|
||||
int buf_width = buf_pitch>>2;
|
||||
|
||||
FGLTexture *gltex = FGLTexture::ValidateTexture(this);
|
||||
gltex->createWarped = true;
|
||||
if (Width == buf_width && Height == buf_height && xx==0 && yy==0)
|
||||
{
|
||||
out = (unsigned long*)buffer;
|
||||
out = (unsigned long*)bmp->GetPixels();
|
||||
direct=true;
|
||||
}
|
||||
else
|
||||
|
@ -690,7 +669,7 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
|
|||
|
||||
GenTime = r_FrameTime;
|
||||
if (SourcePic->bMasked) memset(in, 0, Width*Height*sizeof(long));
|
||||
int ret = SourcePic->CopyTrueColorPixels((BYTE*)in, Width<<2, Height, 0, 0);
|
||||
int ret = SourcePic->CopyTrueColorPixels(&inb, 0, 0);
|
||||
|
||||
int xsize = Width;
|
||||
int ysize = Height;
|
||||
|
@ -721,22 +700,22 @@ int FWarp2Texture::CopyTrueColorPixels(BYTE * buffer, int buf_pitch, int buf_hei
|
|||
|
||||
if (!direct)
|
||||
{
|
||||
// Negative offsets cannot occur here.
|
||||
// This can only happen for sprites so
|
||||
// negative offsets cannot occur here.
|
||||
if (xx<0) xx=0;
|
||||
if (yy<0) yy=0;
|
||||
|
||||
unsigned long * targ = ((unsigned long*)buffer) + xx + yy*buf_width;
|
||||
unsigned long * targ = ((unsigned long*)bmp->GetPixels()) + xx + yy*buf_width;
|
||||
int linelen=MIN<int>(Width, buf_width-xx);
|
||||
int linecount=MIN<int>(Height, buf_height-yy);
|
||||
|
||||
for(i=0;i<linecount;i++)
|
||||
{
|
||||
memcpy(targ, &out[Width*i], linelen*sizeof(unsigned long));
|
||||
targ+=buf_width;
|
||||
targ+=buf_pitch/4;
|
||||
}
|
||||
delete [] out;
|
||||
}
|
||||
delete [] in;
|
||||
GenTime=r_FrameTime;
|
||||
return ret;
|
||||
}
|
||||
|
@ -837,10 +816,9 @@ void FBrightmapTexture::Unload ()
|
|||
{
|
||||
}
|
||||
|
||||
int FBrightmapTexture::CopyTrueColorPixels(BYTE * buffer, int buf_width, int buf_height, int x, int y)
|
||||
int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
|
||||
{
|
||||
SetTranslationInfo(CM_BRIGHTMAP, 0);
|
||||
SourcePic->CopyTrueColorPixels(buffer, buf_width, buf_height, x, y);
|
||||
SourcePic->CopyTrueColorTranslated(bmp, x, y, rotate, &GlobalBrightmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1198,13 +1176,12 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
|
|||
unsigned char * buffer;
|
||||
intptr_t cm = _cm;
|
||||
|
||||
SetTranslationInfo(cm, translation);
|
||||
|
||||
// Textures that are already scaled in the texture lump will not get replaced
|
||||
// by hires textures
|
||||
if (gl_texture_usehires && allowhires && scalex==1.f && scaley==1.f)
|
||||
{
|
||||
buffer = LoadHiresTexture (&w, &h);
|
||||
buffer = LoadHiresTexture (&w, &h, _cm);
|
||||
if (buffer)
|
||||
{
|
||||
return buffer;
|
||||
|
@ -1214,14 +1191,32 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
|
|||
w=Width;
|
||||
h=Height;
|
||||
|
||||
|
||||
buffer=new unsigned char[Width*(Height+1)*4];
|
||||
memset(buffer, 0, Width * (Height+1) * 4);
|
||||
|
||||
if (translation<=0)
|
||||
FGLBitmap bmp(buffer, Width*4, Width, Height);
|
||||
bmp.SetTranslationInfo(cm, translation);
|
||||
|
||||
if (tex->bComplex)
|
||||
{
|
||||
FBitmap imgCreate;
|
||||
|
||||
// The texture contains special processing so it must be composited using with the
|
||||
// base bitmap class and then be converted as a whole.
|
||||
if (imgCreate.Create(Width, Height))
|
||||
{
|
||||
memset(imgCreate.GetPixels(), 0, Width * Height * 4);
|
||||
int trans =
|
||||
tex->CopyTrueColorPixels(&imgCreate, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
|
||||
bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), Width, Height, 4, Width*4, 0, CF_BGRA);
|
||||
CheckTrans(buffer, w*h, trans);
|
||||
}
|
||||
}
|
||||
else if (translation<=0)
|
||||
{
|
||||
int trans =
|
||||
tex->CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
|
||||
GetTopOffset() - tex->TopOffset);
|
||||
tex->CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
|
||||
|
||||
CheckTrans(buffer, w*h, trans);
|
||||
|
||||
|
@ -1231,8 +1226,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int _cm, int translation, int & w, i
|
|||
// When using translations everything must be mapped to the base palette.
|
||||
// Since FTexture's method is doing exactly that by calling GetPixels let's use that here
|
||||
// to do all the dirty work for us. ;)
|
||||
tex->FTexture::CopyTrueColorPixels(buffer, GetWidth()<<2, GetHeight(), GetLeftOffset() - tex->LeftOffset,
|
||||
GetTopOffset() - tex->TopOffset);
|
||||
tex->FTexture::CopyTrueColorPixels(&bmp, GetLeftOffset() - tex->LeftOffset, GetTopOffset() - tex->TopOffset);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -5340,6 +5340,20 @@ int DLevelScript::RunScript ()
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -550,6 +550,7 @@ public:
|
|||
PCD_SETMUGSHOTSTATE,
|
||||
PCD_THINGCOUNTSECTOR,
|
||||
PCD_THINGCOUNTNAMESECTOR,
|
||||
PCD_CHECKPLAYERCAMERA, // [TN]
|
||||
|
||||
PCODE_COMMAND_COUNT
|
||||
};
|
||||
|
|
|
@ -283,14 +283,6 @@ public:
|
|||
void Reset() { StartBlock(minx, miny); }
|
||||
};
|
||||
|
||||
class FRadiusThingsIterator : public FBlockThingsIterator
|
||||
{
|
||||
fixed_t X, Y, Radius;
|
||||
public:
|
||||
FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius);
|
||||
AActor *Next();
|
||||
};
|
||||
|
||||
class FPathTraverse
|
||||
{
|
||||
static TArray<intercept_t> intercepts;
|
||||
|
|
|
@ -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;
|
||||
|
@ -680,6 +687,10 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
|
||||
return true; // can't hit thing
|
||||
|
||||
fixed_t blockdist = thing->radius + tm.thing->radius;
|
||||
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
|
||||
return true;
|
||||
|
||||
tm.thing->BlockingMobj = thing;
|
||||
topz = thing->z + thing->height;
|
||||
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
|
||||
|
@ -1025,6 +1036,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
|
|||
|
||||
tm.x = x;
|
||||
tm.y = y;
|
||||
tm.z = thing->z;
|
||||
|
||||
FBoundingBox box(x, y, thing->radius);
|
||||
|
||||
|
@ -1097,7 +1109,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
|
|||
|
||||
tm.stepthing = NULL;
|
||||
|
||||
FRadiusThingsIterator it2(x, y, thing->radius);
|
||||
FBlockThingsIterator it2(FBoundingBox(x, y, thing->radius));
|
||||
AActor *th;
|
||||
while ((th = it2.Next()))
|
||||
{
|
||||
|
@ -1228,11 +1240,15 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj)
|
|||
return true;
|
||||
}
|
||||
|
||||
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
|
||||
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
|
||||
AActor *thing;
|
||||
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if (!thing->intersects(actor))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(thing->flags & MF_SOLID))
|
||||
{ // Can't hit thing
|
||||
continue;
|
||||
|
@ -3659,7 +3675,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
|
|||
float bombdamagefloat = (float)bombdamage;
|
||||
FVector3 bombvec(FIXED2FLOAT(bombspot->x), FIXED2FLOAT(bombspot->y), FIXED2FLOAT(bombspot->z));
|
||||
|
||||
FRadiusThingsIterator it(bombspot->x, bombspot->y, bombdistance<<FRACBITS);
|
||||
FBlockThingsIterator it(FBoundingBox(bombspot->x, bombspot->y, bombdistance<<FRACBITS));
|
||||
AActor *thing;
|
||||
|
||||
while ((thing = it.Next()))
|
||||
|
@ -3894,9 +3910,13 @@ void P_FindAboveIntersectors (AActor *actor)
|
|||
return;
|
||||
|
||||
AActor *thing;
|
||||
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
|
||||
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if (!thing->intersects(actor))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(thing->flags & MF_SOLID))
|
||||
{ // Can't hit thing
|
||||
continue;
|
||||
|
@ -3932,9 +3952,13 @@ void P_FindBelowIntersectors (AActor *actor)
|
|||
return;
|
||||
|
||||
AActor *thing;
|
||||
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
|
||||
FBlockThingsIterator it(FBoundingBox(actor->x, actor->y, actor->radius));
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if (!thing->intersects(actor))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(thing->flags & MF_SOLID))
|
||||
{ // Can't hit thing
|
||||
continue;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1056,6 +1056,10 @@ void APlayerPawn::ActivateMorphWeapon ()
|
|||
if (player->ReadyWeapon == NULL)
|
||||
{
|
||||
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon));
|
||||
if (player->ReadyWeapon != NULL)
|
||||
{
|
||||
player->ReadyWeapon->GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in P_UndoPlayerMorph
|
||||
}
|
||||
}
|
||||
if (player->ReadyWeapon != NULL)
|
||||
{
|
||||
|
|
19
src/r_data.h
19
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:
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -46,6 +46,26 @@
|
|||
|
||||
TAutoGrowArray<FRemapTablePtr, FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
|
||||
|
||||
const BYTE IcePalette[16][3] =
|
||||
{
|
||||
{ 10, 8, 18 },
|
||||
{ 15, 15, 26 },
|
||||
{ 20, 16, 36 },
|
||||
{ 30, 26, 46 },
|
||||
{ 40, 36, 57 },
|
||||
{ 50, 46, 67 },
|
||||
{ 59, 57, 78 },
|
||||
{ 69, 67, 88 },
|
||||
{ 79, 77, 99 },
|
||||
{ 89, 87,109 },
|
||||
{ 99, 97,120 },
|
||||
{ 109,107,130 },
|
||||
{ 118,118,141 },
|
||||
{ 128,128,151 },
|
||||
{ 138,138,162 },
|
||||
{ 148,148,172 }
|
||||
};
|
||||
|
||||
/****************************************************/
|
||||
/****************************************************/
|
||||
|
||||
|
@ -428,25 +448,6 @@ void R_InitTranslationTables ()
|
|||
// Doom palette has no good substitutes for these bluish-tinted grays, so
|
||||
// they will just look gray unless you use a different PLAYPAL with Doom.
|
||||
|
||||
static const BYTE IcePalette[16][3] =
|
||||
{
|
||||
{ 10, 8, 18 },
|
||||
{ 15, 15, 26 },
|
||||
{ 20, 16, 36 },
|
||||
{ 30, 26, 46 },
|
||||
{ 40, 36, 57 },
|
||||
{ 50, 46, 67 },
|
||||
{ 59, 57, 78 },
|
||||
{ 69, 67, 88 },
|
||||
{ 79, 77, 99 },
|
||||
{ 89, 87,109 },
|
||||
{ 99, 97,120 },
|
||||
{ 109,107,130 },
|
||||
{ 118,118,141 },
|
||||
{ 128,128,151 },
|
||||
{ 138,138,162 },
|
||||
{ 148,148,172 }
|
||||
};
|
||||
BYTE IcePaletteRemap[16];
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
@ -495,6 +489,31 @@ namespace FMOD
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
'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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -658,8 +658,8 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
|
|||
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[3] = MAKE_ID(0xf0,0x7f,0x7f,0x04); // dwParms[0]
|
||||
events[4] = MAKE_ID(0x01,0x7f,0x7f,0xf7); // dwParms[1]
|
||||
events += 5;
|
||||
DoInitialSetup();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include "sc_man.h"
|
||||
#include "templates.h"
|
||||
#include "vectors.h"
|
||||
#include "r_translate.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
// On the Alpha, accessing the shorts directly if they aren't aligned on a
|
||||
// 4-byte boundary causes unaligned access warnings. Why it does this at
|
||||
|
@ -177,6 +179,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
|
|||
Unload ();
|
||||
if (Parts != NULL)
|
||||
{
|
||||
for(int i=0; i<NumParts;i++)
|
||||
{
|
||||
if (Parts[i].textureOwned && Parts[i].Texture != NULL) delete Parts[i].Texture;
|
||||
if (Parts[i].Translation != NULL) delete Parts[i].Translation;
|
||||
}
|
||||
delete[] Parts;
|
||||
Parts = NULL;
|
||||
}
|
||||
|
@ -274,6 +281,70 @@ const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spa
|
|||
return Pixels + column*Height;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMultiPatchTexture :: GetColumn
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
BYTE * GetBlendMap(PalEntry blend, BYTE *blendwork)
|
||||
{
|
||||
|
||||
switch (blend.a==0 ? blend.r : -1)
|
||||
{
|
||||
case BLEND_INVERSEMAP:
|
||||
return InverseColormap;
|
||||
|
||||
case BLEND_GOLDMAP:
|
||||
return GoldColormap;
|
||||
|
||||
case BLEND_REDMAP:
|
||||
return RedColormap;
|
||||
|
||||
case BLEND_GREENMAP:
|
||||
return GreenColormap;
|
||||
|
||||
case BLEND_ICEMAP:
|
||||
return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap;
|
||||
|
||||
default:
|
||||
if (blend.r >= BLEND_DESATURATE1 && blend.r <= BLEND_DESATURATE31)
|
||||
{
|
||||
return DesaturateColormap[blend - BLEND_DESATURATE1];
|
||||
}
|
||||
else
|
||||
{
|
||||
blendwork[0]=0;
|
||||
if (blend.a == 255)
|
||||
{
|
||||
for(int i=1;i<256;i++)
|
||||
{
|
||||
int rr = (blend.r * GPalette.BaseColors[i].r) / 255;
|
||||
int gg = (blend.g * GPalette.BaseColors[i].g) / 255;
|
||||
int bb = (blend.b * GPalette.BaseColors[i].b) / 255;
|
||||
|
||||
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
|
||||
}
|
||||
return blendwork;
|
||||
}
|
||||
else if (blend.a != 0)
|
||||
{
|
||||
for(int i=1;i<256;i++)
|
||||
{
|
||||
int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255;
|
||||
int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255;
|
||||
int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255;
|
||||
|
||||
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
|
||||
}
|
||||
return blendwork;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMultiPatchTexture :: MakeTexture
|
||||
|
@ -285,14 +356,20 @@ void FMultiPatchTexture::MakeTexture ()
|
|||
// Add a little extra space at the end if the texture's height is not
|
||||
// a power of 2, in case somebody accidentally makes it repeat vertically.
|
||||
int numpix = Width * Height + (1 << HeightBits) - Height;
|
||||
BYTE blendwork[256];
|
||||
|
||||
Pixels = new BYTE[numpix];
|
||||
memset (Pixels, 0, numpix);
|
||||
|
||||
for (int i = 0; i < NumParts; ++i)
|
||||
{
|
||||
BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL;
|
||||
if (Parts[i].Blend != BLEND_NONE)
|
||||
{
|
||||
trans = GetBlendMap(Parts[i].Blend, blendwork);
|
||||
}
|
||||
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
|
||||
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate);
|
||||
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,14 +381,69 @@ void FMultiPatchTexture::MakeTexture ()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
|
||||
int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
|
||||
{
|
||||
int retv = -1;
|
||||
FCopyInfo info;
|
||||
|
||||
for(int i=0;i<NumParts;i++)
|
||||
{
|
||||
int ret = Parts[i].Texture->CopyTrueColorPixels(buffer, buf_pitch, buf_height,
|
||||
x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
|
||||
int ret;
|
||||
|
||||
if (!Parts[i].Texture->bComplex || inf == NULL)
|
||||
{
|
||||
memset (&info, 0, sizeof (info));
|
||||
if (Parts[i].Translation != NULL)
|
||||
{
|
||||
// Using a translation forces downconversion to the base palette
|
||||
ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation);
|
||||
}
|
||||
else
|
||||
{
|
||||
PalEntry b = Parts[i].Blend;
|
||||
if (b.a == 0 && b.r != BLEND_NONE)
|
||||
{
|
||||
info.blend = EBlend(b.r);
|
||||
inf = &info;
|
||||
}
|
||||
else if (b.a != 0)
|
||||
{
|
||||
if (b.a == 255)
|
||||
{
|
||||
info.blendcolor[0] = b.r * FRACUNIT / 255;
|
||||
info.blendcolor[1] = b.g * FRACUNIT / 255;
|
||||
info.blendcolor[2] = b.b * FRACUNIT / 255;
|
||||
info.blend = BLEND_MODULATE;
|
||||
inf = &info;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.blendcolor[3] = b.a * FRACUNIT / 255;
|
||||
info.blendcolor[0] = b.r * (FRACUNIT-info.blendcolor[3]);
|
||||
info.blendcolor[1] = b.g * (FRACUNIT-info.blendcolor[3]);
|
||||
info.blendcolor[2] = b.b * (FRACUNIT-info.blendcolor[3]);
|
||||
|
||||
info.blend = BLEND_OVERLAY;
|
||||
inf = &info;
|
||||
}
|
||||
}
|
||||
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, inf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the patch is a texture with some kind of processing involved
|
||||
// and being drawn with additional processing
|
||||
// the copying must be done in 2 steps: First create a complete image of the patch
|
||||
// including all processing and then copy from that intermediate image to the destination
|
||||
FBitmap bmp1;
|
||||
if (bmp1.Create(Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight()))
|
||||
{
|
||||
Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0);
|
||||
bmp->CopyPixelDataRGB(x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(),
|
||||
bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret > retv) retv = ret;
|
||||
}
|
||||
|
@ -328,6 +460,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf
|
|||
|
||||
FTextureFormat FMultiPatchTexture::GetFormat()
|
||||
{
|
||||
if (bComplex) return TEX_RGB;
|
||||
if (NumParts == 1) return Parts[0].Texture->GetFormat();
|
||||
return UseBasePalette() ? TEX_Pal : TEX_RGB;
|
||||
}
|
||||
|
@ -344,6 +477,7 @@ FTextureFormat FMultiPatchTexture::GetFormat()
|
|||
|
||||
bool FMultiPatchTexture::UseBasePalette()
|
||||
{
|
||||
if (bComplex) return false;
|
||||
for(int i=0;i<NumParts;i++)
|
||||
{
|
||||
if (!Parts[i].Texture->UseBasePalette()) return false;
|
||||
|
@ -490,18 +624,8 @@ FMultiPatchTexture::TexPart::TexPart()
|
|||
Rotate = 0;
|
||||
textureOwned = false;
|
||||
Texture = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMultiPatchTexture :: TexPart :: TexPart
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMultiPatchTexture::TexPart::~TexPart()
|
||||
{
|
||||
if (textureOwned && Texture != NULL) delete Texture;
|
||||
Texture = NULL;
|
||||
Translation = NULL;
|
||||
Blend = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -674,6 +798,17 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
|
|||
}
|
||||
|
||||
|
||||
static bool Check(char *& range, char c)
|
||||
{
|
||||
while (isspace(*range)) range++;
|
||||
if (*range==c)
|
||||
{
|
||||
range++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
||||
{
|
||||
FString patchname;
|
||||
|
@ -690,10 +825,20 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
|
||||
part.textureOwned = true;
|
||||
}
|
||||
else if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./"))
|
||||
{
|
||||
int lumpnum = Wads.CheckNumForName(sc.String, ns_patches);
|
||||
if (lumpnum >= 0)
|
||||
{
|
||||
part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch);
|
||||
TexMan.AddTexture(part.Texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
part.Texture = TexMan[texno];
|
||||
bComplex |= part.Texture->bComplex;
|
||||
}
|
||||
if (part.Texture == NULL)
|
||||
{
|
||||
|
@ -728,6 +873,113 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
|||
}
|
||||
part.Rotate = (sc.Number / 90) & 3;
|
||||
}
|
||||
else if (sc.Compare("Translation"))
|
||||
{
|
||||
bComplex = true;
|
||||
if (part.Translation != NULL) delete part.Translation;
|
||||
part.Translation = NULL;
|
||||
part.Blend = 0;
|
||||
static const char *maps[] = { "inverse", "gold", "red", "green", "ice", "desaturate", NULL };
|
||||
sc.MustGetString();
|
||||
int match = sc.MatchString(maps);
|
||||
if (match >= 0)
|
||||
{
|
||||
part.Blend.r = 1 + match;
|
||||
if (part.Blend.r == BLEND_DESATURATE1)
|
||||
{
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
part.Blend.r += clamp(sc.Number-1, 0, 30);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.UnGet();
|
||||
part.Translation = new FRemapTable;
|
||||
part.Translation->MakeIdentity();
|
||||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
|
||||
char *range = sc.String;
|
||||
int start,end;
|
||||
|
||||
start=strtol(range, &range, 10);
|
||||
if (!Check(range, ':')) return;
|
||||
end=strtol(range, &range, 10);
|
||||
if (!Check(range, '=')) return;
|
||||
if (!Check(range, '['))
|
||||
{
|
||||
int pal1,pal2;
|
||||
|
||||
pal1=strtol(range, &range, 10);
|
||||
if (!Check(range, ':')) return;
|
||||
pal2=strtol(range, &range, 10);
|
||||
|
||||
part.Translation->AddIndexRange(start, end, pal1, pal2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// translation using RGB values
|
||||
int r1,g1,b1,r2,g2,b2;
|
||||
|
||||
r1=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
g1=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
b1=strtol(range, &range, 10);
|
||||
if (!Check(range, ']')) return;
|
||||
if (!Check(range, ':')) return;
|
||||
if (!Check(range, '[')) return;
|
||||
r2=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
g2=strtol(range, &range, 10);
|
||||
if (!Check(range, ',')) return;
|
||||
b2=strtol(range, &range, 10);
|
||||
if (!Check(range, ']')) return;
|
||||
|
||||
part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
|
||||
}
|
||||
}
|
||||
while (sc.CheckString(","));
|
||||
}
|
||||
|
||||
}
|
||||
else if (sc.Compare("Blend"))
|
||||
{
|
||||
bComplex = true;
|
||||
if (part.Translation != NULL) delete part.Translation;
|
||||
part.Translation = NULL;
|
||||
part.Blend = 0;
|
||||
|
||||
if (!sc.CheckNumber())
|
||||
{
|
||||
sc.MustGetString();
|
||||
part.Blend = V_GetColor(NULL, sc.String);
|
||||
}
|
||||
else
|
||||
{
|
||||
int r,g,b;
|
||||
|
||||
sc.MustGetNumber();
|
||||
sc.MustGetStringName(",");
|
||||
r = sc.Number;
|
||||
sc.MustGetNumber();
|
||||
sc.MustGetStringName(",");
|
||||
g = sc.Number;
|
||||
sc.MustGetNumber();
|
||||
sc.MustGetStringName(",");
|
||||
b = sc.Number;
|
||||
part.Blend = MAKERGB(r, g, b);
|
||||
}
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
|
||||
}
|
||||
else part.Blend.a = 255;
|
||||
bComplex = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Mirror & 2)
|
||||
|
@ -790,7 +1042,9 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
{
|
||||
TexPart part;
|
||||
ParsePatch(sc, part);
|
||||
parts.Push(part);
|
||||
if (part.Texture != NULL) parts.Push(part);
|
||||
part.Texture = NULL;
|
||||
part.Translation = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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,
|
||||
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, int bank, int gm_num, int sf_ix)
|
||||
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,436 +200,226 @@ 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)
|
||||
{
|
||||
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))
|
||||
if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data)))
|
||||
{
|
||||
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);
|
||||
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->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 = (tmp[0] * 8 + 4) & 0x7f;
|
||||
{
|
||||
sp->panning = patch_data.Balance & 0x0F;
|
||||
sp->panning = (sp->panning << 3) | (sp->panning >> 1);
|
||||
}
|
||||
else
|
||||
sp->panning = (BYTE)(panning & 0x7F);
|
||||
{
|
||||
sp->panning = panning & 0x7f;
|
||||
}
|
||||
sp->panning |= sp->panning << 7;
|
||||
|
||||
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;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
/* envelope, tremolo, and vibrato */
|
||||
if (18 != fp->Read(tmp, 18)) goto fail;
|
||||
|
||||
if (!tmp[13] || !tmp[14])
|
||||
/* 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");
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo\n");
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
if (!tmp[16] || !tmp[17])
|
||||
/* vibrato */
|
||||
if (patch_data.VibratoRate == 0 || patch_data.VibratoDepth == 0)
|
||||
{
|
||||
sp->vibrato_sweep_increment = 0;
|
||||
sp->tremolo_sweep_increment = 0;
|
||||
sp->vibrato_control_ratio = 0;
|
||||
sp->vibrato_depth = 0;
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato\n");
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
READ_CHAR(sp->modes);
|
||||
READ_SHORT(sp->freq_center);
|
||||
READ_SHORT(sp->freq_scale);
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
sp->modes = patch_data.Modes;
|
||||
|
||||
/* 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);
|
||||
{
|
||||
sp->scale_note = note_to_use;
|
||||
sp->scale_factor = 0;
|
||||
}
|
||||
else
|
||||
sp->note_to_use = 0;
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (sp->modes & MODES_LOOPING)
|
||||
sp->modes |= MODES_SUSTAIN;
|
||||
if (sp->modes & PATCH_LOOPEN)
|
||||
{
|
||||
sp->modes |= PATCH_SUSTAIN;
|
||||
}
|
||||
|
||||
/* Strip any loops and envelopes we're permitted to */
|
||||
if ((strip_loop == 1) &&
|
||||
(sp->modes & (MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||||
(sp->modes & (PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
|
||||
{
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
|
||||
sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain\n");
|
||||
sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
|
||||
}
|
||||
|
||||
if (strip_envelope == 1)
|
||||
{
|
||||
if (sp->modes & MODES_ENVELOPE)
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
|
||||
sp->modes &= ~MODES_ENVELOPE;
|
||||
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 & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
|
||||
if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
|
||||
{
|
||||
/* 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");
|
||||
sp->modes &= ~(PATCH_SUSTAIN | PATCH_NO_SRELEASE);
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n");
|
||||
}
|
||||
else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
|
||||
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 &= ~MODES_ENVELOPE;
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope");
|
||||
sp->modes &= ~PATCH_NO_SRELEASE;
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n");
|
||||
}
|
||||
else if (!(sp->modes & MODES_SUSTAIN))
|
||||
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 &= ~MODES_ENVELOPE;
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope");
|
||||
sp->modes &= ~PATCH_NO_SRELEASE;
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n");
|
||||
}
|
||||
}
|
||||
|
||||
sp->attenuation = 0;
|
||||
|
||||
for (j = ATTACK; j < DELAY; j++)
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
sp->envelope_rate[j] = convert_envelope_rate(song, tmp[j]);
|
||||
sp->envelope_offset[j] = convert_envelope_offset(tmp[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]);
|
||||
}
|
||||
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))
|
||||
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 + 1);
|
||||
sp->data = (sample_t *)safe_malloc(sp->data_length);
|
||||
|
||||
if (sp->data_length != fp->Read(sp->data, sp->data_length))
|
||||
goto fail;
|
||||
|
@ -670,13 +427,13 @@ fail:
|
|||
convert_sample_data(sp, sp->data);
|
||||
|
||||
/* Reverse reverse loops and pass them off as normal loops */
|
||||
if (sp->modes & MODES_REVERSE)
|
||||
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. */
|
||||
|
||||
cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
|
||||
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];
|
||||
|
||||
|
@ -684,35 +441,31 @@ fail:
|
|||
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 */
|
||||
sp->modes &= ~PATCH_BACKWARD;
|
||||
sp->modes |= PATCH_LOOPEN; /* just in case */
|
||||
}
|
||||
|
||||
if (amp != -1)
|
||||
{
|
||||
sp->volume = (amp) / 100.f;
|
||||
}
|
||||
else if (sf2flag)
|
||||
{
|
||||
sp->volume = (sample_volume) / 255.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;
|
||||
int i;
|
||||
sample_t maxamp = 0, a;
|
||||
sample_t *tmp;
|
||||
for (i = numsamps, tmp = sp->data; i; --i)
|
||||
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", sp->volume);
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume);
|
||||
#else
|
||||
sp->volume = 1;
|
||||
#endif
|
||||
|
@ -724,27 +477,25 @@ fail:
|
|||
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);
|
||||
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->note_to_use && !(sp->modes & MODES_LOOPING))
|
||||
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");
|
||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail\n");
|
||||
sp->data_length = sp->loop_end;
|
||||
}
|
||||
} /* end of sample loop */
|
||||
} /* end of stereo layer loop */
|
||||
} /* end of vlayer loop */
|
||||
|
||||
|
||||
}
|
||||
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) */
|
||||
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
|
||||
)))
|
||||
(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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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,14 +107,15 @@ void apply_envelope_to_amp(Voice *v)
|
|||
static int update_envelope(Voice *v)
|
||||
{
|
||||
v->envelope_volume += v->envelope_increment;
|
||||
/* Why is there no ^^ operator?? */
|
||||
if (((v->envelope_increment < 0) && (v->envelope_volume <= v->envelope_target)) ||
|
||||
((v->envelope_increment > 0) && (v->envelope_volume >= v->envelope_target)))
|
||||
{
|
||||
v->envelope_volume = v->envelope_target;
|
||||
if (recompute_envelope(v))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -119,7 +123,7 @@ static void update_tremolo(Voice *v)
|
|||
{
|
||||
int depth = v->sample->tremolo_depth << 7;
|
||||
|
||||
if (v->tremolo_sweep)
|
||||
if (v->tremolo_sweep != 0)
|
||||
{
|
||||
/* Update sweep position */
|
||||
|
||||
|
@ -151,12 +155,14 @@ static void update_tremolo(Voice *v)
|
|||
/* Returns 1 if the note died */
|
||||
static int update_signal(Voice *v)
|
||||
{
|
||||
if (v->envelope_increment && update_envelope(v))
|
||||
if (v->envelope_increment != 0 && update_envelope(v))
|
||||
{
|
||||
return 1;
|
||||
|
||||
if (v->tremolo_phase_increment)
|
||||
}
|
||||
if (v->tremolo_phase_increment != 0)
|
||||
{
|
||||
update_tremolo(v);
|
||||
|
||||
}
|
||||
apply_envelope_to_amp(v);
|
||||
return 0;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -491,25 +494,10 @@ void Renderer::ComputeOutput(float *buffer, int count)
|
|||
for (int i = 0; i < voices; i++, v++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::MarkInstrument(int banknum, int percussion, int instr)
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -43,11 +43,10 @@ config.h
|
|||
#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
|
||||
/* Default polyphony, and maximum polyphony. */
|
||||
#define DEFAULT_VOICES 32
|
||||
#define MAX_VOICES 256
|
||||
|
||||
#define MAXCHAN 16
|
||||
#define MAXNOTE 128
|
||||
|
||||
|
@ -56,11 +55,6 @@ config.h
|
|||
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
|
||||
|
||||
/* How many bits to use for the fractional part of sample positions.
|
||||
This affects tonal accuracy. The entire position counter must fit
|
||||
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
||||
|
@ -106,9 +100,9 @@ typedef float final_volume_t;
|
|||
|
||||
/* Vibrato and tremolo Choices of the Day */
|
||||
#define SWEEP_TUNING 38
|
||||
#define VIBRATO_AMPLITUDE_TUNING 1.0L
|
||||
#define VIBRATO_AMPLITUDE_TUNING 1.0
|
||||
#define VIBRATO_RATE_TUNING 38
|
||||
#define TREMOLO_AMPLITUDE_TUNING 1.0L
|
||||
#define TREMOLO_AMPLITUDE_TUNING 1.0
|
||||
#define TREMOLO_RATE_TUNING 38
|
||||
|
||||
#define SWEEP_SHIFT 16
|
||||
|
@ -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,110 +210,170 @@ 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];
|
||||
};
|
||||
|
||||
|
||||
|
@ -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,8 +452,6 @@ struct Channel
|
|||
rpn, nrpn;
|
||||
bool
|
||||
nrpn_mode;
|
||||
char
|
||||
transpose;
|
||||
float
|
||||
pitchfactor; /* precomputed pitch bend factor to save some fdiv's */
|
||||
};
|
||||
|
@ -413,75 +459,64 @@ struct Channel
|
|||
/* Causes the instrument's default panning to be used. */
|
||||
#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))))
|
||||
|
||||
|
@ -500,8 +535,6 @@ tables.h
|
|||
#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
|
||||
|
||||
/*
|
||||
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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
210
src/v_video.cpp
210
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<class T>
|
||||
void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step)
|
||||
{
|
||||
for(int i=0;i<count;i++)
|
||||
{
|
||||
pout[0]=T::B(pin);
|
||||
pout[1]=T::G(pin);
|
||||
pout[2]=T::R(pin);
|
||||
pout[3]=T::A(pin);
|
||||
pout+=4;
|
||||
pin+=step;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*CopyFunc)(BYTE *pout, const BYTE *pin, int count, int step);
|
||||
|
||||
static CopyFunc copyfuncs[]={
|
||||
iCopyColors<cRGB>,
|
||||
iCopyColors<cRGBA>,
|
||||
iCopyColors<cIA>,
|
||||
iCopyColors<cCMYK>,
|
||||
iCopyColors<cBGR>,
|
||||
iCopyColors<cBGRA>,
|
||||
iCopyColors<cI16>,
|
||||
iCopyColors<cRGB555>,
|
||||
iCopyColors<cPalEntry>
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Clips the copy area for CopyPixelData functions
|
||||
//
|
||||
//===========================================================================
|
||||
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
|
||||
const BYTE *&patch, int &srcwidth, int &srcheight,
|
||||
int &pstep_x, int &pstep_y, int rotate)
|
||||
{
|
||||
int pixxoffset;
|
||||
int pixyoffset;
|
||||
|
||||
int step_x;
|
||||
int step_y;
|
||||
|
||||
// First adjust the settings for the intended rotation
|
||||
switch (rotate)
|
||||
{
|
||||
default:
|
||||
case 0: // normal
|
||||
pixxoffset = 0;
|
||||
pixyoffset = 0;
|
||||
step_x = pstep_x;
|
||||
step_y = pstep_y;
|
||||
break;
|
||||
|
||||
case 1: // rotate 90° right
|
||||
pixxoffset = 0;
|
||||
pixyoffset = srcheight - 1;
|
||||
step_x = -pstep_y;
|
||||
step_y = pstep_x;
|
||||
break;
|
||||
|
||||
case 2: // rotate 180°
|
||||
pixxoffset = srcwidth - 1;
|
||||
pixyoffset = srcheight - 1;
|
||||
step_x = -pstep_x;
|
||||
step_y = -pstep_y;
|
||||
break;
|
||||
|
||||
case 3: // rotate 90° left
|
||||
pixxoffset = srcwidth - 1;
|
||||
pixyoffset = 0;
|
||||
step_x = pstep_y;
|
||||
step_y = -pstep_x;
|
||||
break;
|
||||
|
||||
case 4: // flip horizontally
|
||||
pixxoffset = srcwidth - 1;
|
||||
pixyoffset = 0;
|
||||
step_x = -pstep_x;
|
||||
step_y = pstep_y;
|
||||
break;
|
||||
|
||||
case 5: // flip horizontally and rotate 90° right
|
||||
pixxoffset = srcwidth - 1;
|
||||
pixyoffset = srcheight - 1;
|
||||
step_x = -pstep_y;
|
||||
step_y = -pstep_x;
|
||||
break;
|
||||
|
||||
case 6: // flip vertically
|
||||
pixxoffset = 0;
|
||||
pixyoffset = srcheight - 1;
|
||||
step_x = pstep_x;
|
||||
step_y = -pstep_y;
|
||||
break;
|
||||
|
||||
case 7: // flip horizontally and rotate 90° left
|
||||
pixxoffset = 0;
|
||||
pixyoffset = 0;
|
||||
step_x = pstep_y;
|
||||
step_y = pstep_x;
|
||||
break;
|
||||
}
|
||||
if (rotate&1)
|
||||
{
|
||||
int v = srcwidth;
|
||||
srcwidth = srcheight;
|
||||
srcheight = v;
|
||||
}
|
||||
|
||||
patch += pixxoffset * pstep_x + pixyoffset * pstep_y;
|
||||
pstep_x = step_x;
|
||||
pstep_y = step_y;
|
||||
|
||||
// clip source rectangle to destination
|
||||
if (originx<0)
|
||||
{
|
||||
srcwidth+=originx;
|
||||
patch-=originx*step_x;
|
||||
originx=0;
|
||||
if (srcwidth<=0) return false;
|
||||
}
|
||||
if (originx+srcwidth>texwidth)
|
||||
{
|
||||
srcwidth=texwidth-originx;
|
||||
if (srcwidth<=0) return false;
|
||||
}
|
||||
|
||||
if (originy<0)
|
||||
{
|
||||
srcheight+=originy;
|
||||
patch-=originy*step_y;
|
||||
originy=0;
|
||||
if (srcheight<=0) return false;
|
||||
}
|
||||
if (originy+srcheight>texheight)
|
||||
{
|
||||
srcheight=texheight-originy;
|
||||
if (srcheight<=0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// True Color texture copy function
|
||||
//
|
||||
//===========================================================================
|
||||
void DFrameBuffer::CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
|
||||
const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y,
|
||||
int rotate, int ct)
|
||||
{
|
||||
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
{
|
||||
buffer+=4*originx + texpitch*originy;
|
||||
for (int y=0;y<srcheight;y++)
|
||||
{
|
||||
copyfuncs[ct](&buffer[y*texpitch], &patch[y*step_y], srcwidth, step_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Paletted to True Color texture copy function
|
||||
//
|
||||
//===========================================================================
|
||||
void DFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
|
||||
const BYTE * patch, int srcwidth, int srcheight,
|
||||
int step_x, int step_y, int rotate, PalEntry * palette)
|
||||
{
|
||||
int x,y,pos;
|
||||
|
||||
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
|
||||
{
|
||||
buffer+=4*originx + texpitch*originy;
|
||||
|
||||
for (y=0;y<srcheight;y++)
|
||||
{
|
||||
pos=y*texpitch;
|
||||
for (x=0;x<srcwidth;x++,pos+=4)
|
||||
{
|
||||
int v=(unsigned char)patch[y*step_y+x*step_x];
|
||||
if (palette[v].a==0)
|
||||
{
|
||||
buffer[pos]=palette[v].b;
|
||||
buffer[pos+1]=palette[v].g;
|
||||
buffer[pos+2]=palette[v].r;
|
||||
buffer[pos+3]=255;
|
||||
}
|
||||
else if (palette[v].a!=255)
|
||||
{
|
||||
// [RH] Err... This can't be right, can it?
|
||||
buffer[pos ] = (buffer[pos ] * palette[v].a + palette[v].b * (1-palette[v].a)) / 255;
|
||||
buffer[pos+1] = (buffer[pos+1] * palette[v].a + palette[v].g * (1-palette[v].a)) / 255;
|
||||
buffer[pos+2] = (buffer[pos+2] * palette[v].a + palette[v].r * (1-palette[v].a)) / 255;
|
||||
buffer[pos+3] = clamp<int>(buffer[pos+3] + (( 255-buffer[pos+3]) * (255-palette[v].a))/255, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Texture precaching
|
||||
|
|
113
src/v_video.h
113
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__
|
||||
|
|
|
@ -205,6 +205,7 @@ ACTOR WolfensteinSS 84
|
|||
DeathSound "wolfss/death"
|
||||
ActiveSound "wolfss/active"
|
||||
AttackSound "wolfss/attack"
|
||||
Obituary "$OB_WOLFSS"
|
||||
Dropitem "Clip"
|
||||
States
|
||||
{
|
||||
|
|
|
@ -124,7 +124,7 @@ class Actor extends Thinker
|
|||
action native A_FLoopActiveSound();
|
||||
action native A_LoopActiveSound();
|
||||
action native A_StopSound();
|
||||
action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional bool looping, optional eval int attenuation);
|
||||
action native A_PlaySoundEx(sound whattoplay, coerce name slot, optional eval bool looping, optional eval int attenuation);
|
||||
action native A_StopSoundEx(coerce name slot);
|
||||
action native A_SeekerMissile(eval int threshold, eval int turnmax);
|
||||
action native A_Jump(eval int chance, state label, ...);
|
||||
|
@ -174,8 +174,8 @@ class Actor extends Thinker
|
|||
action native A_LookEx(optional eval int flags, optional eval float minseedist, optional eval float maxseedist, optional eval float maxheardist, optional eval float fov, optional state label);
|
||||
action native A_ClearTarget();
|
||||
action native A_JumpIfTargetInLOS (state label, optional eval float fov);
|
||||
action native A_DamageMaster(int amount, optional name damagetype);
|
||||
action native A_DamageChildren(int amount, optional name damagetype);
|
||||
action native A_DamageMaster(eval int amount, optional name damagetype);
|
||||
action native A_DamageChildren(eval int amount, optional name damagetype);
|
||||
action native A_SelectWeapon(class<Weapon> whichweapon);
|
||||
action native A_Punch();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue