diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0e5eee40..ec7214a6 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,158 @@ +April 25, 2008 (SBarInfo Update #18) +- Simplified the DrawGraphic function in sbarinfo_display.cpp +- Added xOffset, yOffset, and alpha to every drawing function in + sbarinfo_display.cpp. So Strife popups can be handeled better and allow for + other effects (translucent bars?). I'm thinking about making a struct for + these five (also x and y) arguments so that the argument lists don't become a + mess. +- Changed DRAWIMAGE in sbarinfo_display.cpp to not use so many calls to + DrawGraphic. +- DrawKeyBar wasn't using screen->DrawTexture. +- Added a Fade transition for popups. It takes two args fade in rate and fade + out rate. Both are floats (1.0 = 1 tic to complete 0.5 = 2 tics to complete + and so on). +- Added a translucency arg to statusbars. 1.0 = opaque and 0.0 = invisible. + +April 24, 2008 +- Fixed: When an instrument's envelope runs out, it does not immediately ramp + to zero. Rather, it lets the remainder of the sample finish playing. +- Fixed: When playing a MIDI file with EMIDI track designations to turn a + track off, any ticks that had only events on the disabled track would cause + the delay for that track to be thrown away, and the following notes on + enabled tracks would play too soon. This could be heard quite clearly in + xplasma.mid, where track 4 (FMGlass Drone 1) would interfere with the timing + of tracks 13 and 14 (EP1 Melody and EP1 Echo). + +April 24, 2008 (Changes by Graf Zahl) +- Fixed: DFlashFader did some operations in its destructor that had to be moved + to its Destroy method. +- Fixed: Dropped weapons from dying players should not double ammo. + +April 23, 2008 +- Fixed: When note_on() is called and another copy of the same note is + already playing on the channel, it should stop it with finish_note(), not + kill_note(). This can be clearly heard in the final cymbal crashes of + D_DM2TTL where TiMidity cuts them off because the final cymbals are played + with a velocity of 1 before the preceding cymbals have finished. (I wonder + if I should be setting the self_nonexclusive flag for GUS patches to + disable even this behavior, though, since gf1note.c doesn't turn off + duplicate notes.) +- Changed envelope handling to hopefully match the GUS player's. The most + egregious mistake TiMidity makes is to treat bit 6 as an envelope enable + bit. This is not what it does; every sample has an envelope. Rather, this + is a "no sampled release" flag. Also, despite fiddling with the + PATCH_SUSTAIN flag during instrument loading, TiMidity never actually + used it. Nor did it do anything at all with the PATCH_FAST_REL flag. + +April 23, 2008 (Changes by Graf Zahl) +- Fixed: wbstartstruct's lump name fields were only 8 characters long + and not properly zero-terminated when all 8 characters were used. +- Fixed: Local sound sequence definitions caused a crash because a proper + NULL check was missing. + +April 22, 2008 (Changes by Graf Zahl) +- Added translucent blending modes to FMultipatchTexture (not tested yet!) +- Also changed all true color texture creation functions to use proper alpha + values instead of inverted ones. +- Changed FRemapTable so that all palette entries must contain proper alpha + values. + +April 21, 2008 (Changes by Graf Zahl) +- Fixed: The F1 screen check in m_menu.cpp was missing a NULL pointer check. + +April 20, 2008 (Changes by Graf Zahl) +- Changed: The boss brain's explosions play weapons/rocklx which is an + unlimited sound. This can become extremely loud. Replaced with a new + sound which is just an alias to weapons/rocklx but has a limit of 4. + +April 19, 2008 +- Fixed: MugShotFrame::getTexture() allocated space for the sprite name that + it never freed. I'm not sure it's a good assumption that 9 characters is + always long enough, either, since you can have longer file names than that + inside a zip. +- Fixed: DSBarInfo::DrawGem() crashed if chain or gem was NULL. +- Fixed: Sound sequences are not thinkers, therefore they must be explicitly + marked as roots for the GC. +- Reduced the range that area sounds require to interpolate between 2D and + 3D panning. +- The listener's velocity is now set at 0 for the sound engine. The player + moves so fast that you can hear the doppler shift just by running around, + otherwise. +- Changed the sound code so that all sounds that start playing on a single + tic actually start playing at the exact same sample position. +- Added the writewave command to write the internal TiMidity's output to a + wave file. +- Changed the default channel velocity for MUS files from 64 to 100 to + better match apparent MIDI practice. (Would like to know what this is + supposed to be.) +- Changed the mus2midi channel assignments to match the internal player's. +- Fixed: apply_envelope_to_amp() should clamp the mix levels to 0. + +April 18, 2008 +- Made the maximum number of TiMidity voices configurable through the + timidity_voices cvar. +- Added stats lines for the OPL and Timidity MIDI devices. +- Completely changed the way TiMidity volume calculations are done. It + should now be extremely close to the output a real GUS would produce with + its official MIDI player (excepting where TiMidity normalizes sample + volumes). The new equations more closely match what is specified by the DLS + and SF2 specs (but not quite), so I presume it's also more musically + correct than what TiMidity (and TiMidity++) do. + +April 18, 2008 (Changes by Graf Zahl) +- Fixed: FBlockThingsIterator didn't set the current block coordinates if + they were outside the blockmap. This could cause extreme delays if an + iteration started outside the valid boundaries. + +April 17, 2008 +- Fixed: The music stream needs to zero the FMOD_REVERB_CHANNELPROPERTIES + before sending it to Channel::getReverbProperties(). +- Fixed: The earthquake effect did not play its sound as an actual looping + sound. I'm a bit surprised this only recently started causing problems. + +April 17, 2008 (Changes by Graf Zahl) +- Added Martin Howe's fixes for morphing and DECORATE function prototypes. +- Minor fixes in texture code. + +April 16, 2008 +- 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. + +April 16, 2008 (Changes by Graf Zahl) +- Made translation support for multipatch textures operational. + +April 15, 2008 +- 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. + +April 15, 2008 (Changes by Graf Zahl) +- 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. + April 14, 2008 (Changes by Graf Zahl) - Added rotation 90° angles only) and mirroring to the Multipatch texture composition code. diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index b8e33a44..73d619ba 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -187,6 +187,7 @@ static void BrainishExplosion (fixed_t x, fixed_t y, fixed_t z) AActor *boom = Spawn("Rocket", x, y, z, NO_REPLACE); if (boom != NULL) { + boom->DeathSound = S_FindSound("misc/brainexplode"); boom->momz = pr_brainscream() << 9; boom->SetState (&ABossBrain::States[S_BRAINEXPLODE]); boom->effects = 0; diff --git a/src/g_level.cpp b/src/g_level.cpp index 20c6fb94..2eb6b448 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1863,6 +1863,10 @@ void G_DoCompleted (void) strncpy (wminfo.lname1, nextinfo->pname, 8); } } + wminfo.next[8]=0; + wminfo.lname0[8]=0; + wminfo.lname1[8]=0; + wminfo.current[8]=0; CheckWarpTransMap (wminfo.next, true); diff --git a/src/g_shared/a_flashfader.cpp b/src/g_shared/a_flashfader.cpp index f46fd7ca..2442dd6d 100644 --- a/src/g_shared/a_flashfader.cpp +++ b/src/g_shared/a_flashfader.cpp @@ -19,7 +19,7 @@ DFlashFader::DFlashFader (float r1, float g1, float b1, float a1, Blends[1][0]=r2; Blends[1][1]=g2; Blends[1][2]=b2; Blends[1][3]=a2; } -DFlashFader::~DFlashFader () +void DFlashFader::Destroy () { SetBlend (1.f); } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 223a548d..a6131ea0 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -131,7 +131,7 @@ public: DFlashFader (float r1, float g1, float b1, float a1, float r2, float g2, float b2, float a2, float time, AActor *who); - ~DFlashFader (); + void Destroy (); void Serialize (FArchive &arc); void Tick (); AActor *WhoFor() { return ForWho; } diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 3f392957..f6e37b6a 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -175,8 +175,7 @@ AInventory *AWeapon::CreateCopy (AActor *other) // // A weapon that's tossed out should contain no ammo, so you can't cheat // by dropping it and then picking it back up. -// -//=========================================================================== +//======================= AInventory *AWeapon::CreateTossable () { diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index 510da22b..2e1b5829 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -53,6 +53,7 @@ enum PopupTransition { TRANSITION_NONE, TRANSITION_SLIDEINBOTTOM, + TRANSITION_FADE, }; struct Popup @@ -63,6 +64,8 @@ struct Popup int height; int width; int speed; + int speed2; + int alpha; int x; int y; @@ -74,6 +77,7 @@ struct Popup bool isDoneMoving(); int getXOffset(); int getYOffset(); + int getAlpha(int maxAlpha=FRACUNIT); }; //SBarInfo @@ -81,6 +85,8 @@ struct SBarInfoBlock { TArray commands; bool forceScaled; + int alpha; + SBarInfoBlock(); }; @@ -372,15 +378,15 @@ public: void ShowPop(int popnum); void SetMugShotState(const char* stateName, bool waitTillDone=false); private: - void doCommands(SBarInfoBlock &block, int xOffset=0, int yOffset=0); - void DrawGraphic(FTexture* texture, int x, int y, int flags=0); - void DrawString(const char* str, int x, int y, EColorRange translation, int spacing=0); - void DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing=0, bool fillzeros=false); - void DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y); + void doCommands(SBarInfoBlock &block, int xOffset=0, int yOffset=0, int alpha=FRACUNIT); + void DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yOffset, int alpha, bool translate=false, bool dim=false, bool center=false); + void DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, EColorRange translation, int spacing=0); + void DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, EColorRange translation, int spacing=0, bool fillzeros=false); + void DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y, int xOffset, int yOffset, int alpha); int updateState(bool xdth, bool animatedgodmode); - void DrawInventoryBar(int type, int num, int x, int y, bool alwaysshow, + void DrawInventoryBar(int type, int num, int x, int y, int xOffset, int yOffset, int alpha, bool alwaysshow, int counterx, int countery, EColorRange translation, bool drawArtiboxes, bool noArrows, bool alwaysshowcounter); - void DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, int padleft, int padright, int chainsize, + void DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, int xOffset, int yOffset, int alpha, int padleft, int padright, int chainsize, bool wiggle, bool translate); FRemapTable* getTranslation(); diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index de87777c..2244c5b5 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -310,22 +310,25 @@ void DSBarInfo::Draw (EHudState state) SetScaled(true); setsizeneeded = true; } - doCommands(SBarInfoScript->huds[hud]); + doCommands(SBarInfoScript->huds[hud], 0, 0, SBarInfoScript->huds[hud].alpha); if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR)) { if(state == HUD_StatusBar) - doCommands(SBarInfoScript->huds[STBAR_INVENTORY]); + doCommands(SBarInfoScript->huds[STBAR_INVENTORY], 0, 0, SBarInfoScript->huds[STBAR_INVENTORY].alpha); else if(state == HUD_Fullscreen) - doCommands(SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN]); + doCommands(SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN], 0, 0, SBarInfoScript->huds[STBAR_INVENTORYFULLSCREEN].alpha); } if(currentPopup != POP_None) { + int popbar = 0; if(currentPopup == POP_Log) - doCommands(SBarInfoScript->huds[STBAR_POPUPLOG], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); + popbar = STBAR_POPUPLOG; else if(currentPopup == POP_Keys) - doCommands(SBarInfoScript->huds[STBAR_POPUPKEYS], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); + popbar = STBAR_POPUPKEYS; else if(currentPopup == POP_Status) - doCommands(SBarInfoScript->huds[STBAR_POPUPSTATUS], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset()); + popbar = STBAR_POPUPSTATUS; + doCommands(SBarInfoScript->huds[popbar], SBarInfoScript->popups[currentPopup].getXOffset(), SBarInfoScript->popups[currentPopup].getYOffset(), + SBarInfoScript->popups[currentPopup].getAlpha(SBarInfoScript->huds[popbar].alpha)); } } @@ -469,7 +472,7 @@ void DSBarInfo::SetMugShotState(const char* stateName, bool waitTillDone) } } -void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) +void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int alpha) { //prepare ammo counts AAmmo *ammo1, *ammo2; @@ -489,8 +492,6 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) for(unsigned int i = 0;i < block.commands.Size();i++) { SBarInfoCommand& cmd = block.commands[i]; - cmd.x += xOffset; - cmd.y += yOffset; switch(cmd.type) //read and execute all the commands { case SBARINFO_DRAWSWITCHABLEIMAGE: //draw the alt image if we don't have the item else this is like a normal drawimage @@ -545,49 +546,50 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) if(drawAlt != 0) //draw 'off' image { if(cmd.special != -1 && drawAlt == 1) - DrawGraphic(Images[cmd.special], cmd.x, cmd.y, cmd.flags); + DrawGraphic(Images[cmd.special], cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); else if(cmd.special2 != -1 && drawAlt == 2) - DrawGraphic(Images[cmd.special2], cmd.x, cmd.y, cmd.flags); + DrawGraphic(Images[cmd.special2], cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); else if(cmd.special3 != -1 && drawAlt == 3) - DrawGraphic(Images[cmd.special3], cmd.x, cmd.y, cmd.flags); + DrawGraphic(Images[cmd.special3], cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); break; } } case SBARINFO_DRAWIMAGE: + { + FTexture *texture = NULL; if((cmd.flags & DRAWIMAGE_PLAYERICON)) - DrawGraphic(TexMan[CPlayer->mo->ScoreIcon], cmd.x, cmd.y, cmd.flags); + texture = TexMan[CPlayer->mo->ScoreIcon]; else if((cmd.flags & DRAWIMAGE_AMMO1)) { if(ammo1 != NULL) - DrawGraphic(TexMan[ammo1->Icon], cmd.x, cmd.y, cmd.flags); + texture = TexMan[ammo1->Icon]; } else if((cmd.flags & DRAWIMAGE_AMMO2)) { if(ammo2 != NULL) - DrawGraphic(TexMan[ammo2->Icon], cmd.x, cmd.y, cmd.flags); + texture = TexMan[ammo2->Icon]; } else if((cmd.flags & DRAWIMAGE_ARMOR)) { if(armor != NULL && armor->Amount != 0) - DrawGraphic(TexMan(armor->Icon), cmd.x, cmd.y, cmd.flags); + texture = TexMan(armor->Icon); } else if((cmd.flags & DRAWIMAGE_WEAPONICON)) { AWeapon *weapon = CPlayer->ReadyWeapon; if(weapon != NULL && weapon->Icon > 0) { - DrawGraphic(TexMan[weapon->Icon], cmd.x, cmd.y, cmd.flags); + texture = TexMan[weapon->Icon]; } } else if((cmd.flags & DRAWIMAGE_INVENTORYICON)) - { - DrawGraphic(TexMan[cmd.sprite], cmd.x, cmd.y, cmd.flags); - } + texture = TexMan[cmd.sprite]; else if(cmd.sprite != -1) - { - DrawGraphic(Images[cmd.sprite], cmd.x, cmd.y, cmd.flags); - } + texture = Images[cmd.sprite]; + + DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); break; + } case SBARINFO_DRAWNUMBER: { int value = cmd.value; @@ -695,12 +697,12 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) } } bool fillzeros = !!(cmd.flags & DRAWNUMBER_FILLZEROS); + EColorRange translation = cmd.translation; if(cmd.special3 != -1 && value <= cmd.special3) //low - DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation2, cmd.special2, fillzeros); + translation = cmd.translation2; else if(cmd.special4 != -1 && value >= cmd.special4) //high - DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation3, cmd.special2, fillzeros); - else - DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation, cmd.special2, fillzeros); + translation = cmd.translation3; + DrawNumber(value, cmd.special, cmd.x, cmd.y, xOffset, yOffset, alpha, translation, cmd.special2, fillzeros); break; } case SBARINFO_DRAWMUGSHOT: @@ -711,7 +713,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) xdth = true; if(cmd.flags & DRAWMUGSHOT_ANIMATEDGODMODE) animatedgodmode = true; - DrawFace(cmd.string[0], cmd.special, xdth, animatedgodmode, cmd.x, cmd.y); + DrawFace(cmd.string[0], cmd.special, xdth, animatedgodmode, cmd.x, cmd.y, xOffset, yOffset, alpha); break; } case SBARINFO_DRAWSELECTEDINVENTORY: @@ -719,11 +721,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { if((cmd.flags & DRAWSELECTEDINVENTORY_ARTIFLASH) && artiflash) { - DrawDimImage(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0); + DrawGraphic(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, xOffset, yOffset, alpha, false, CPlayer->mo->InvSel->Amount <= 0); } else { - DrawDimImage(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, CPlayer->mo->InvSel->Amount <= 0); + DrawGraphic(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, xOffset, yOffset, alpha, false, CPlayer->mo->InvSel->Amount <= 0); } if((cmd.flags & DRAWSELECTEDINVENTORY_ALWAYSSHOWCOUNTER) || CPlayer->mo->InvSel->Amount != 1) { @@ -731,12 +733,12 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { drawingFont = cmd.font; } - DrawNumber(CPlayer->mo->InvSel->Amount, 3, cmd.special2, cmd.special3, cmd.translation, cmd.special4); + DrawNumber(CPlayer->mo->InvSel->Amount, 3, cmd.special2, cmd.special3, xOffset, yOffset, alpha, cmd.translation, cmd.special4); } } else if((cmd.flags & DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY)) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } break; case SBARINFO_DRAWINVENTORYBAR: @@ -757,7 +759,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { drawingFont = cmd.font; } - DrawInventoryBar(cmd.special, cmd.value, cmd.x, cmd.y, alwaysshow, cmd.special2, cmd.special3, cmd.translation, artibox, noarrows, alwaysshowcounter); + DrawInventoryBar(cmd.special, cmd.value, cmd.x, cmd.y, xOffset, yOffset, alpha, alwaysshow, cmd.special2, cmd.special3, cmd.translation, artibox, noarrows, alwaysshowcounter); break; } case SBARINFO_DRAWBAR: @@ -905,8 +907,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) int cx, cy, cw, ch, cr, cb; // Calc real screen coordinates for bar - x = cmd.x + ST_X; - y = cmd.y + ST_Y; + x = cmd.x + ST_X + xOffset; + y = cmd.y + ST_Y + yOffset; w = fg->GetScaledWidth(); h = fg->GetScaledHeight(); if (Scaled) @@ -920,6 +922,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) screen->DrawTexture(fg, x, y, DTA_DestWidth, w, DTA_DestHeight, h, + DTA_Alpha, alpha, TAG_DONE); } else @@ -930,6 +933,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) screen->DrawTexture(bg, x, y, DTA_DestWidth, w, DTA_DestHeight, h, + DTA_Alpha, alpha, TAG_DONE); } else @@ -939,8 +943,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) } // Calc clipping rect for background - cx = cmd.x + ST_X + cmd.special3; - cy = cmd.y + ST_Y + cmd.special3; + cx = cmd.x + ST_X + cmd.special3 + xOffset; + cy = cmd.y + ST_Y + cmd.special3 + yOffset; cw = fg->GetScaledWidth() - fg->GetScaledLeftOffset() - cmd.special3 * 2; ch = fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2; if (Scaled) @@ -987,6 +991,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) DTA_ClipTop, cy, DTA_ClipRight, cr, DTA_ClipBottom, cb, + DTA_Alpha, alpha, TAG_DONE); } else @@ -1003,6 +1008,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) DTA_ClipTop, cy, DTA_ClipRight, cr, DTA_ClipBottom, cb, + DTA_Alpha, alpha, TAG_DONE); } break; @@ -1028,7 +1034,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { wiggle = !!(cmd.flags & DRAWGEM_WIGGLE); } - DrawGem(Images[cmd.special], Images[cmd.sprite], value, cmd.x, cmd.y, cmd.special2, cmd.special3, cmd.special4+1, wiggle, translate); + DrawGem(Images[cmd.special], Images[cmd.sprite], value, cmd.x, cmd.y, xOffset, yOffset, alpha, cmd.special2, cmd.special3, cmd.special4+1, wiggle, translate); break; } case SBARINFO_DRAWSHADER: @@ -1040,10 +1046,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) }; bool vertical = !!(cmd.flags & DRAWSHADER_VERTICAL); bool reverse = !!(cmd.flags & DRAWSHADER_REVERSE); - screen->DrawTexture (shaders[(vertical << 1) + reverse], ST_X+cmd.x, ST_Y+cmd.y, + screen->DrawTexture (shaders[(vertical << 1) + reverse], ST_X+cmd.x+xOffset, ST_Y+cmd.y+yOffset, DTA_DestWidth, cmd.special, DTA_DestHeight, cmd.special2, DTA_Bottom320x200, Scaled, + DTA_Alpha, alpha, DTA_AlphaChannel, true, DTA_FillColor, 0, TAG_DONE); @@ -1054,7 +1061,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) { drawingFont = cmd.font; } - DrawString(cmd.string[0], cmd.x - drawingFont->StringWidth(cmd.string[0]), cmd.y, cmd.translation, cmd.special); + DrawString(cmd.string[0], cmd.x - drawingFont->StringWidth(cmd.string[0]), cmd.y, xOffset, yOffset, alpha, cmd.translation, cmd.special); break; case SBARINFO_DRAWKEYBAR: { @@ -1071,9 +1078,9 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) goto FinishDrawKeyBar; } if(!vertical) - DrawImage(TexMan[item->Icon], cmd.x+(cmd.special*i), cmd.y); + DrawGraphic(TexMan[item->Icon], cmd.x+(cmd.special*i), cmd.y, xOffset, yOffset, alpha); else - DrawImage(TexMan[item->Icon], cmd.x, cmd.y+(cmd.special*i)); + DrawGraphic(TexMan[item->Icon], cmd.x, cmd.y+(cmd.special*i), xOffset, yOffset, alpha); item = item->Inventory; if(item == NULL) break; @@ -1087,7 +1094,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) ((cmd.flags & GAMETYPE_COOPERATIVE) && multiplayer && !deathmatch) || ((cmd.flags & GAMETYPE_TEAMGAME) && teamplay)) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } break; case SBARINFO_PLAYERCLASS: @@ -1096,14 +1103,14 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) int spawnClass = CPlayer->cls->ClassIndex; if(cmd.special == spawnClass || cmd.special2 == spawnClass || cmd.special3 == spawnClass) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } break; } case SBARINFO_ASPECTRATIO: if(CheckRatio(screen->GetWidth(), screen->GetHeight()) == cmd.value) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } break; case SBARINFO_ISSELECTED: @@ -1114,16 +1121,16 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) if(weapon2 != NULL) { if((cmd.flags & SBARINFOEVENT_NOT) && (weapon1 != CPlayer->ReadyWeapon->GetSpecies() && weapon2 != CPlayer->ReadyWeapon->GetSpecies())) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); else if(!(cmd.flags & SBARINFOEVENT_NOT) && (weapon1 == CPlayer->ReadyWeapon->GetSpecies() || weapon2 == CPlayer->ReadyWeapon->GetSpecies())) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } else { if(!(cmd.flags & SBARINFOEVENT_NOT) && weapon1 == CPlayer->ReadyWeapon->GetSpecies()) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); else if((cmd.flags & SBARINFOEVENT_NOT) && weapon1 != CPlayer->ReadyWeapon->GetSpecies()) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } } break; @@ -1150,11 +1157,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) if(((cmd.flags & SBARINFOEVENT_OR) && (match1 || match2)) || ((cmd.flags & SBARINFOEVENT_AND) && (match1 && match2))) { if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } else if(cmd.flags & SBARINFOEVENT_NOT) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } } else //Every thing here could probably be one long if statement but then it would be more confusing. @@ -1162,11 +1169,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) if((usesammo1 && (AmmoType1 == IfAmmo1)) || (usesammo2 && (AmmoType2 == IfAmmo1))) { if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } else if(cmd.flags & SBARINFOEVENT_NOT) { - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } } } @@ -1178,66 +1185,57 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset) if(cmd.flags & SBARINFOEVENT_AND) { if((item1 != NULL && item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); else if((item1 == NULL || item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } else if(cmd.flags & SBARINFOEVENT_OR) { if((item1 != NULL || item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); else if((item1 == NULL && item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); } else if((item1 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); else if((item1 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset); + doCommands(cmd.subBlock, xOffset, yOffset, alpha); break; } } - cmd.x -= xOffset; - cmd.y -= yOffset; } } //draws an image with the specified flags -void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags) +void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yOffset, int alpha, + bool translate, bool dim, bool center) //flags { if (texture == NULL) - { return; - } - if((flags & DRAWIMAGE_OFFSET_CENTER)) + + if(center) { x -= (texture->GetWidth()/2)-texture->LeftOffset; y -= (texture->GetHeight()/2)-texture->TopOffset; } - x += ST_X; - y += ST_Y; + + x += ST_X + xOffset; + y += ST_Y + yOffset; int w = texture->GetScaledWidth(); int h = texture->GetScaledHeight() + y; if(Scaled) screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); h -= y; - if((flags & DRAWIMAGE_TRANSLATABLE)) - { - screen->DrawTexture(texture, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_Translation, getTranslation(), - TAG_DONE); - } - else - { - screen->DrawTexture(texture, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - TAG_DONE); - } + screen->DrawTexture(texture, x, y, + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_Translation, translate ? getTranslation() : 0, + DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_Alpha, alpha, + TAG_DONE); } -void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translation, int spacing) +void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, EColorRange translation, int spacing) { x += spacing; while(*str != '\0') @@ -1261,8 +1259,8 @@ void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translatio } if(SBarInfoScript->spacingCharacter == '\0') //If we are monospaced lets use the offset x += (character->LeftOffset+1); //ignore x offsets since we adapt to character size - int rx = x + ST_X; - int ry = y + ST_Y; + int rx = x + ST_X + xOffset; + int ry = y + ST_Y + yOffset; int rw = character->GetScaledWidth(); int rh = character->GetScaledHeight(); if(Scaled) @@ -1271,6 +1269,7 @@ void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translatio DTA_DestWidth, rw, DTA_DestHeight, rh, DTA_Translation, drawingFont->GetColorTranslation(translation), + DTA_Alpha, alpha, TAG_DONE); if(SBarInfoScript->spacingCharacter == '\0') x += width + spacing - (character->LeftOffset+1); @@ -1281,7 +1280,7 @@ void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translatio } //draws the specified number up to len digits -void DSBarInfo::DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing, bool fillzeros) +void DSBarInfo::DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, EColorRange translation, int spacing, bool fillzeros) { FString value; int maxval = (int) ceil(pow(10., len))-1; @@ -1306,11 +1305,11 @@ void DSBarInfo::DrawNumber(int num, int len, int x, int y, EColorRange translati x -= int(drawingFont->StringWidth(value)+(spacing * value.Len())); else //monospaced so just multiplay the character size x -= int((drawingFont->GetCharWidth((int) SBarInfoScript->spacingCharacter) + spacing) * value.Len()); - DrawString(value, x, y, translation, spacing); + DrawString(value, x, y, xOffset, yOffset, alpha, translation, spacing); } //draws the mug shot -void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y) +void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y, int xOffset, int yOffset, int alpha) { int angle = updateState(xdth, animatedgodmode); int level = 0; @@ -1320,18 +1319,7 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin]; FTexture *face = currentState->getCurrentFrameTexture(defaultFace, skin, level, angle); if (face != NULL) - { - x += ST_X; - y += ST_Y; - int w = face->GetScaledWidth(); - int h = face->GetScaledHeight(); - if(Scaled) - screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); - screen->DrawTexture(face, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - TAG_DONE); - } + DrawGraphic(face, x, y, xOffset, yOffset, alpha); } } @@ -1454,7 +1442,7 @@ int DSBarInfo::updateState(bool xdth, bool animatedgodmode) return 0; } -void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, bool alwaysshow, +void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, int xOffset, int yOffset, int alpha, bool alwaysshow, int counterx, int countery, EColorRange translation, bool drawArtiboxes, bool noArrows, bool alwaysshowcounter) { //yes, there is some Copy & Paste here too AInventory *item; @@ -1468,46 +1456,46 @@ void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, bool alwayssho { if(drawArtiboxes) { - DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y); + DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y, xOffset, yOffset, alpha); } - DrawDimImage (TexMan(item->Icon), x+i*31, y, item->Amount <= 0); + DrawGraphic(TexMan(item->Icon), x+i*31, y, xOffset, yOffset, alpha, false, item->Amount <= 0); if(alwaysshowcounter || item->Amount != 1) { - DrawNumber(item->Amount, 3, counterx+i*31, countery, translation); + DrawNumber(item->Amount, 3, counterx+i*31, countery, xOffset, yOffset, alpha, translation); } if(item == CPlayer->mo->InvSel) { if(type == GAME_Heretic) { - DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29); + DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29, xOffset, yOffset, alpha); } else { - DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y); + DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y, xOffset, yOffset, alpha); } } } for (; i < num && drawArtiboxes; ++i) { - DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y); + DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y, xOffset, yOffset, alpha); } // Is there something to the left? if (!noArrows && CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst) { DrawGraphic(Images[!(gametic & 4) ? - invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x-12, y); + invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x-12, y, xOffset, yOffset, alpha); } // Is there something to the right? if (!noArrows && item != NULL) { DrawGraphic(Images[!(gametic & 4) ? - invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x+num*31+2, y); + invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x+num*31+2, y, xOffset, yOffset, alpha); } } } //draws heretic/hexen style life gems -void DSBarInfo::DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, int padleft, int padright, int chainsize, +void DSBarInfo::DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, int xOffset, int yOffset, int alpha, int padleft, int padright, int chainsize, bool wiggle, bool translate) { if(chain == NULL) @@ -1520,9 +1508,9 @@ void DSBarInfo::DrawGem(FTexture* chain, FTexture* gem, int value, int x, int y, y += chainWiggle; int chainWidth = chain->GetWidth(); int offset = (int) (((double) (chainWidth-padleft-padright)/100)*value); - DrawGraphic(chain, x+(offset%chainsize), y); + DrawGraphic(chain, x+(offset%chainsize), y, xOffset, yOffset, alpha); if(gem != NULL) - DrawGraphic(gem, x+padleft+offset, y, translate ? DRAWIMAGE_TRANSLATABLE : 0); + DrawGraphic(gem, x+padleft+offset, y, xOffset, yOffset, alpha, translate); } FRemapTable* DSBarInfo::getTranslation() diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index fb683e6b..92026720 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -255,18 +255,25 @@ void SBarInfo::ParseSBarInfo(int lump) barNum = sc.MustMatchString(StatusBars); } this->huds[barNum] = SBarInfoBlock(); - while(sc.CheckToken(',')) + if(sc.CheckToken(',')) { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("forcescaled")) + while(sc.CheckToken(TK_Identifier)) { - this->huds[barNum].forceScaled = true; - } - else - { - sc.ScriptError("Unkown flag '%s'.", sc.String); + if(sc.Compare("forcescaled")) + { + this->huds[barNum].forceScaled = true; + } + else + { + sc.ScriptError("Unkown flag '%s'.", sc.String); + } + if(!sc.CheckToken('|') || !sc.CheckToken(',')) + goto FinishStatusBar; //No more args so we must skip over anything else and go to the end. } + sc.MustGetToken(TK_FloatConst); + this->huds[barNum].alpha = fixed_t(FRACUNIT * sc.Float); } + FinishStatusBar: sc.MustGetToken('{'); if(barNum == STBAR_AUTOMAP) { @@ -336,6 +343,16 @@ void SBarInfo::ParseSBarInfo(int lump) sc.MustGetToken(TK_IntConst); popup.speed = sc.Number; } + else if(sc.Compare("fade")) + { + popup.transition = TRANSITION_FADE; + sc.MustGetToken(','); + sc.MustGetToken(TK_FloatConst); + popup.speed = fixed_t(FRACUNIT * sc.Float); + sc.MustGetToken(','); + sc.MustGetToken(TK_FloatConst); + popup.speed2 = fixed_t(FRACUNIT * sc.Float); + } else sc.ScriptError("Unkown transition type: '%s'", sc.String); } @@ -1264,6 +1281,7 @@ SBarInfoCommand::~SBarInfoCommand() SBarInfoBlock::SBarInfoBlock() { forceScaled = false; + alpha = FRACUNIT; } const MugShotState *FindMugShotState(FString state) @@ -1286,6 +1304,7 @@ Popup::Popup() speed = 0; x = 320; y = 200; + alpha = FRACUNIT; opened = false; moving = false; } @@ -1298,6 +1317,12 @@ void Popup::init() { x = 0; } + else if(transition == TRANSITION_FADE) + { + alpha = 0; + x = 0; + y = 0; + } } void Popup::tick() @@ -1316,9 +1341,22 @@ void Popup::tick() else moving = false; } + else if(transition == TRANSITION_FADE) + { + if(moving) + { + if(opened) + alpha = clamp(alpha + speed, 0, FRACUNIT); + else + alpha = clamp(alpha - speed2, 0, FRACUNIT); + } + if(alpha == 0 || alpha == FRACUNIT) + moving = false; + else + moving = true; + } else { - moving = false; if(opened) { y = 0; @@ -1329,6 +1367,7 @@ void Popup::tick() y = height; x = width; } + moving = false; } } @@ -1347,6 +1386,13 @@ int Popup::getYOffset() return y; } +int Popup::getAlpha(int maxAlpha) +{ + double a = (double) alpha / (double) FRACUNIT; + double b = (double) maxAlpha / (double) FRACUNIT; + return fixed_t((a * b) * FRACUNIT); +} + void Popup::open() { opened = true; diff --git a/src/gl/gl_missingtexture.cpp b/src/gl/gl_missingtexture.cpp index 2561e0eb..0c6eb9af 100644 --- a/src/gl/gl_missingtexture.cpp +++ b/src/gl/gl_missingtexture.cpp @@ -698,7 +698,7 @@ void GLDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bo else lightlevel=abs(ceiling? GetCeilingLight(sec) : GetFloorLight(sec)); } - gl_SetFog(lightlevel, Colormap.FadeColor, STYLE_Normal, Colormap.LightColor.a); + gl_SetFog(lightlevel, Colormap.FadeColor, false, Colormap.LightColor.a); gl_SetColor(lightlevel, extralight*gl_weaponlight, &Colormap,1.0f); gltexture->Bind(Colormap.LightColor.a); gl_SetPlaneTextureRotation(&plane, gltexture); diff --git a/src/gl/gl_texture.cpp b/src/gl/gl_texture.cpp index 936fa1aa..8fd8341b 100644 --- a/src/gl/gl_texture.cpp +++ b/src/gl/gl_texture.cpp @@ -324,6 +324,7 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count) { int gray = (pin[i].r*77 + pin[i].g*143 + pin[i].b*37) >> 8; gl_InverseMap(gray, pout[i].r, pout[i].g, pout[i].b); + pout[i].a = pin[i].a; } break; @@ -333,6 +334,7 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count) { int gray = (pin[i].r*77 + pin[i].g*143 + pin[i].b*37) >> 8; gl_GoldMap(gray, pout[i].r, pout[i].g, pout[i].b); + pout[i].a = pin[i].a; } break; @@ -342,6 +344,7 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count) { int gray = (pin[i].r*77 + pin[i].g*143 + pin[i].b*37) >> 8; gl_RedMap(gray, pout[i].r, pout[i].g, pout[i].b); + pout[i].a = pin[i].a; } break; @@ -351,6 +354,7 @@ void ModifyPalette(PalEntry * pout, PalEntry * pin, int cm, int count) { int gray = (pin[i].r*77 + pin[i].g*143 + pin[i].b*37) >> 8; gl_GreenMap(gray, pout[i].r, pout[i].g, pout[i].b); + pout[i].a = pin[i].a; } break; @@ -447,10 +451,10 @@ void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int { for(int i=0;i<256;i++) { - if (palette[i].a!=255) - penew[i]=PalEntry(255-i,255,255,255); + if (palette[i].a != 0) + penew[i]=PalEntry(255,255,255,255); else - penew[i]=0xffffffff; // If the palette contains transparent colors keep them. + penew[i]=PalEntry(0,255,255,255); // If the palette contains transparent colors keep them. } } else @@ -503,13 +507,14 @@ void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int for (x=0;x(buffer[pos+3] + (( 255-buffer[pos+3]) * (255-penew[v].a))/255, 0, 255); } + */ } } } diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 2151a7d2..e3afe73c 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -1464,7 +1464,7 @@ void M_DrawReadThis () else { // Did the mapper choose a custom help page via MAPINFO? - if (level.info->f1[0] != 0) + if ((level.info != NULL) && level.info->f1[0] != 0) { tex = TexMan.FindTexture(level.info->f1); } @@ -3513,7 +3513,7 @@ void M_Init (void) for (i = 0; i < 256; i++) { FireRemap.Remap[i] = ColorMatcher.Pick (i/2+32, 0, i/4); - FireRemap.Palette[i] = PalEntry(i/2+32, 0, i/4); + FireRemap.Palette[i] = PalEntry(255, i/2+32, 0, i/4); } } else @@ -3522,7 +3522,7 @@ void M_Init (void) for (i = 0; i < 256; ++i) { FireRemap.Remap[i] = ColorMatcher.Pick (i/4, i*13/40+7, i/4); - FireRemap.Palette[i] = PalEntry(i/4, i*13/40+7, i/4); + FireRemap.Palette[i] = PalEntry(255, i/4, i*13/40+7, i/4); } } } diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 125e889e..f70085ae 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -541,77 +541,53 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li { if(thing) { - sector_t *front, *back; - fixed_t thingbot, thingtop; thingbot = thing->z; thingtop = thingbot + thing->height; - front = linedef->frontsector; - back = linedef->backsector; - - extsector_t::xfloor &xf = front->e->XFloor; - extsector_t::xfloor &xb = back->e->XFloor; + extsector_t::xfloor *xf[2] = {&linedef->frontsector->e->XFloor, &linedef->backsector->e->XFloor}; // Check for 3D-floors in the sector (mostly identical to what Legacy does here) - if(xf.ffloors.Size() || xb.ffloors.Size()) + if(xf[0]->ffloors.Size() || xf[1]->ffloors.Size()) { - F3DFloor* rover; - unsigned i; - fixed_t lowestceiling = open.top; fixed_t highestfloor = open.bottom; - fixed_t lowestfloor = open.lowfloor; - fixed_t delta1; - fixed_t delta2; + fixed_t lowestfloor[2] = {open.lowfloor, open.lowfloor}; int highestfloorpic = -1; int lowestceilingpic = -1; thingtop = thing->z + (thing->height==0? 1:thing->height); - // Check for frontsector's 3D-floors - for(i=0;iflags&FF_EXISTS)) continue; - if (!(rover->flags & FF_SOLID)) continue; - - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); - fixed_t ff_top=rover->top.plane->ZatPoint(x, y); - - delta1 = abs(thing->z - ((ff_bottom + ff_top) / 2)); - delta2 = abs(thingtop - ((ff_bottom + ff_top) / 2)); - - if(ff_bottom < lowestceiling && delta1 >= delta2) lowestceiling = ff_bottom; - - if(ff_top > highestfloor && delta1 < delta2) highestfloor = ff_top; - else if(ff_top > lowestfloor && delta1 < delta2) lowestfloor = ff_top; - } - - // Check for backsector's 3D-floors - for(i=0;iflags&FF_EXISTS)) continue; - if (!(rover->flags & FF_SOLID)) continue; - - fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); - fixed_t ff_top=rover->top.plane->ZatPoint(x, y); - - delta1 = abs(thing->z - ((ff_bottom + ff_top) / 2)); - delta2 = abs(thingtop - ((ff_bottom + ff_top) / 2)); - - if(ff_bottom < lowestceiling && delta1 >= delta2) lowestceiling = ff_bottom; - - if(ff_top > highestfloor && delta1 < delta2) + // Check for frontsector's 3D-floors + for(unsigned i=0;iffloors.Size();i++) { - highestfloor = ff_top; - highestfloorpic = *rover->top.texture; + F3DFloor *rover = xf[j]->ffloors[i]; + + if (!(rover->flags&FF_EXISTS)) continue; + if (!(rover->flags & FF_SOLID)) continue; + + fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); + fixed_t ff_top=rover->top.plane->ZatPoint(x, y); + + fixed_t delta1 = abs(thingbot - ((ff_bottom + ff_top) / 2)); + fixed_t delta2 = abs(thingtop - ((ff_bottom + ff_top) / 2)); + + if(ff_bottom < lowestceiling && delta1 >= delta2) + { + lowestceiling = ff_bottom; + lowestceilingpic = *rover->bottom.texture; + } + + if(ff_top > highestfloor && delta1 < delta2) + { + highestfloor = ff_top; + highestfloorpic = *rover->top.texture; + } + if(ff_top > lowestfloor[j] && ff_top <= thing->z) lowestfloor[j] = ff_top; } - else if(ff_top > lowestfloor && delta1 < delta2) lowestfloor = ff_top; } if(highestfloor > open.bottom) @@ -626,7 +602,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li open.ceilingpic = lowestceilingpic; } - if(lowestfloor > open.lowfloor) open.lowfloor = lowestfloor; + open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]); } } } diff --git a/src/p_user.cpp b/src/p_user.cpp index e74a25f0..2cb2d519 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1115,6 +1115,7 @@ void APlayerPawn::Die (AActor *source, AActor *inflictor) { static_cast(item)->AmmoGive2 = weap->Ammo2->Amount; } + item->ItemFlags |= IF_IGNORESKILL; } } else @@ -1123,11 +1124,13 @@ void APlayerPawn::Die (AActor *source, AActor *inflictor) if (item != NULL) { item->Amount = weap->Ammo1->Amount; + item->ItemFlags |= IF_IGNORESKILL; } item = P_DropItem (this, weap->AmmoType2, -1, 256); if (item != NULL) { item->Amount = weap->Ammo2->Amount; + item->ItemFlags |= IF_IGNORESKILL; } } } diff --git a/src/r_data.h b/src/r_data.h index b2153e59..18702f2a 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -107,16 +107,19 @@ protected: SWORD OriginX, OriginY; BYTE Rotate; bool textureOwned; + BYTE op; FRemapTable *Translation; PalEntry Blend; FTexture *Texture; + fixed_t Alpha; TexPart(); }; int NumParts; TexPart *Parts; - bool bRedirect; + bool bRedirect:1; + bool bTranslucentPatches:1; void MakeTexture (); diff --git a/src/r_defs.h b/src/r_defs.h index 4f28b2f3..fba579eb 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -827,7 +827,7 @@ public: virtual const BYTE *GetPixels () = 0; 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); + int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap, FCopyInfo *inf = NULL); virtual bool UseBasePalette(); virtual int GetSourceLump() { return -1; } diff --git a/src/r_translate.cpp b/src/r_translate.cpp index 153f0e81..04aa4f88 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -160,9 +160,7 @@ void FRemapTable::Serialize(FArchive &arc) } for (int j = 0; j < NumEntries; ++j) { - arc << Palette[j].r - << Palette[j].g - << Palette[j].b; + arc << Palette[j]; } } @@ -179,6 +177,10 @@ void FRemapTable::MakeIdentity() { Palette[i] = GPalette.BaseColors[i]; } + for (i = 1; i < NumEntries; ++i) + { + Palette[i].a = 255; + } } bool FRemapTable::IsIdentity() const @@ -232,6 +234,7 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) { Remap[start] = pal1; Palette[start] = GPalette.BaseColors[pal1]; + Palette[start].a = start==0? 0:255; return; } palcol = pal1 << FRACBITS; @@ -240,6 +243,7 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) { Remap[i] = palcol >> FRACBITS; Palette[i] = GPalette.BaseColors[palcol >> FRACBITS]; + Palette[i].a = i==0? 0:255; } } @@ -278,6 +282,7 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in Remap[start] = ColorMatcher.Pick (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); Palette[start] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + Palette[start].a = start==0? 0:255; } else { @@ -288,7 +293,7 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in { Remap[i] = ColorMatcher.Pick (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); - Palette[i] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + Palette[i] = PalEntry(start==0? 0:255, r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); r += rs; g += gs; b += bs; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 51453521..7214753f 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -366,11 +366,18 @@ void S_Start () if (level.info && level.info->soundinfo) { LocalSndInfo = level.info->soundinfo; - LocalSndSeq = level.info->sndseq; } else { LocalSndInfo = ""; + } + + if (level.info && level.info->sndseq) + { + LocalSndSeq = level.info->sndseq; + } + else + { LocalSndSeq = ""; } diff --git a/src/sound/music_midi_midiout.cpp b/src/sound/music_midi_midiout.cpp index 77332087..bcadf6d2 100644 --- a/src/sound/music_midi_midiout.cpp +++ b/src/sound/music_midi_midiout.cpp @@ -549,11 +549,18 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay) break; } } - if (event != MIDI_META && (!track->Designated || (track->Designation & DesignationMask))) + if (event != MIDI_META) { events[0] = delay; events[1] = 0; - events[2] = event | (data1<<8) | (data2<<16); + if (!track->Designated || (track->Designation & DesignationMask)) + { + events[2] = event | (data1<<8) | (data2<<16); + } + else + { + events[2] = MEVT_NOP; + } events += 3; } } diff --git a/src/sound/music_timidity_mididevice.cpp b/src/sound/music_timidity_mididevice.cpp index e86e9140..a740d405 100644 --- a/src/sound/music_timidity_mididevice.cpp +++ b/src/sound/music_timidity_mididevice.cpp @@ -41,6 +41,7 @@ #include "w_wad.h" #include "v_text.h" #include "timidity/timidity.h" +#include // MACROS ------------------------------------------------------------------ @@ -597,38 +598,38 @@ FString TimidityMIDIDevice::GetStats() CritSec.Enter(); for (i = used = 0; i < Renderer->voices; ++i) { - switch (Renderer->voice[i].status) + int status = Renderer->voice[i].status; + + if (!(status & Timidity::VOICE_RUNNING)) { - case Timidity::VOICE_FREE: dots << TEXTCOLOR_PURPLE"."; - break; - - case Timidity::VOICE_ON: - dots << TEXTCOLOR_GREEN; - break; - - case Timidity::VOICE_SUSTAINED: - dots << TEXTCOLOR_BLUE; - break; - - case Timidity::VOICE_OFF: - dots << TEXTCOLOR_ORANGE; - break; - - case Timidity::VOICE_DIE: - dots << TEXTCOLOR_RED; - break; } - if (Renderer->voice[i].status != Timidity::VOICE_FREE) + else { used++; - if (Renderer->voice[i].envelope_increment == 0) + if (status & Timidity::VOICE_SUSTAINING) { - dots << TEXTCOLOR_BLUE"+"; + dots << TEXTCOLOR_BLUE; + } + else if (status & Timidity::VOICE_RELEASING) + { + dots << TEXTCOLOR_ORANGE; + } + else if (status & Timidity::VOICE_STOPPING) + { + dots << TEXTCOLOR_RED; } else { - dots << ('1' + Renderer->voice[i].envelope_stage); + dots << TEXTCOLOR_GREEN; + } + if (Renderer->voice[i].envelope_increment == 0) + { + dots << "+"; + } + else + { + dots << ('0' + Renderer->voice[i].envelope_stage); } } } diff --git a/src/svnrevision.h b/src/svnrevision.h index 9daf0a84..873bf730 100644 --- a/src/svnrevision.h +++ b/src/svnrevision.h @@ -3,5 +3,5 @@ // This file was automatically generated by the // updaterevision tool. Do not edit by hand. -#define ZD_SVN_REVISION_STRING "930" -#define ZD_SVN_REVISION_NUMBER 930 +#define ZD_SVN_REVISION_STRING "940" +#define ZD_SVN_REVISION_NUMBER 940 diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index 6fbc9824..25bfdc4b 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -233,7 +233,7 @@ void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *in typedef void (*CopyFunc)(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *inf); -static CopyFunc copyfuncs[9]= +static const CopyFunc copyfuncs[][9]={ { iCopyColors, iCopyColors, @@ -244,7 +244,74 @@ static CopyFunc copyfuncs[9]= iCopyColors, iCopyColors, iCopyColors - }; + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, + { + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors, + iCopyColors + }, +}; //=========================================================================== // @@ -373,13 +440,55 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) { BYTE *buffer = data + 4 * originx + Pitch * originy; + int op = inf==NULL? OP_COPY : inf->op; for (int y=0;y +void iCopyPaletted(BYTE *buffer, const BYTE * patch, int srcwidth, int srcheight, int Pitch, + int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf) +{ + int x,y,pos; + + for (y=0;y, + iCopyPaletted, + iCopyPaletted, + iCopyPaletted, + iCopyPaletted, + iCopyPaletted, + iCopyPaletted, +}; + //=========================================================================== // // Paletted to True Color texture copy function @@ -388,8 +497,6 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int void FBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf) { - int x,y,pos; - if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) { BYTE *buffer = data + 4*originx + Pitch*originy; @@ -397,39 +504,12 @@ void FBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int sr if (inf && inf->blend) { - // The palette's alpha is inverted so in order to use the - // True Color copy functions it has to be inverted temporarily. - memcpy(penew, palette, 4*256); - for(int i=0;i<256;i++) penew[i].a = 255-penew[i].a; - copyfuncs[CF_PalEntry]((BYTE*)penew, (BYTE*)penew, 256, 4, inf); - for(int i=0;i<256;i++) penew[i].a = 255-penew[i].a; + iCopyColors((BYTE*)penew, (const BYTE*)palette, 256, 4, inf); palette = penew; } - - for (y=0;y(buffer[pos+3] + (( 255-buffer[pos+3]) * (255-palette[v].a))/255, 0, 255); - } - } - } + copypalettedfuncs[inf==NULL? OP_COPY : inf->op](buffer, patch, srcwidth, srcheight, Pitch, + step_x, step_y, rotate, palette, inf); } } diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 6fd2ed6b..75401547 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -37,6 +37,7 @@ #define __BITMAP_H__ #include "doomtype.h" +#include "templates.h" struct FCopyInfo; @@ -68,7 +69,7 @@ public: FreeBuffer = false; } - ~FBitmap() + virtual ~FBitmap() { Destroy(); } @@ -272,14 +273,24 @@ enum EBlend BLEND_OVERLAY = -2, }; +enum ECopyOp +{ + OP_COPY, + OP_BLEND, + OP_ADD, + OP_SUBTRACT, + OP_REVERSESUBTRACT, + OP_MODULATE, + OP_COPYALPHA +}; + struct FCopyInfo { - //ECopyOp op; + ECopyOp op; EBlend blend; fixed_t blendcolor[4]; -// fixed_t alpha; -// fixed_t invalpha; - + fixed_t alpha; + fixed_t invalpha; }; struct bCopy @@ -288,6 +299,41 @@ struct bCopy static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } }; +struct bBlend +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (d*i->invalpha + s*i->alpha) >> FRACBITS; } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; + +struct bAdd +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = MIN((d*FRACUNIT + s*i->alpha) >> FRACBITS, 255); } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; + +struct bSubtract +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = MAX((d*FRACUNIT - s*i->alpha) >> FRACBITS, 0); } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; + +struct bReverseSubtract +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = MAX((-d*FRACUNIT + s*i->alpha) >> FRACBITS, 0); } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; + +struct bModulate +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*d)/255; } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; + +struct bCopyAlpha +{ + static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; } + static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; } +}; diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 9c6f9ba9..599e70ee 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -381,7 +381,7 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC break; case JCS_GRAYSCALE: - for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map + for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height, 1, cinfo.output_width, rotate, pe, inf); break; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 0d4fd02a..0d20e37b 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -66,7 +66,7 @@ //========================================================================== FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) -: Pixels (0), Spans(0), Parts(0), bRedirect(false) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { union { @@ -361,15 +361,38 @@ void FMultiPatchTexture::MakeTexture () Pixels = new BYTE[numpix]; memset (Pixels, 0, numpix); - for (int i = 0; i < NumParts; ++i) + if (!bTranslucentPatches) { - BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL; - if (Parts[i].Blend != BLEND_NONE) + for (int i = 0; i < NumParts; ++i) { - trans = GetBlendMap(Parts[i].Blend, blendwork); + 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, trans); } - Parts[i].Texture->CopyToBlock (Pixels, Width, Height, - Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); + } + else + { + // In case there are translucent patches let's do the composition in + // True color to keep as much precision as possible before downconverting to the palette. + BYTE *buffer = new BYTE[Width * Height * 4]; + FillBuffer(buffer, Width * 4, Height, TEX_RGB); + for(int y = 0; y < Height; y++) + { + BYTE *in = buffer + Width * y * 4; + BYTE *out = Pixels + y; + for (int x = 0; x < Width; x--) + { + // I don't know if this is precise enough... + *out = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3]; + out += Height; + in += 4; + } + } + delete [] buffer; } } @@ -393,10 +416,13 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota if (!Parts[i].Texture->bComplex || inf == NULL) { memset (&info, 0, sizeof (info)); + info.alpha = Parts[i].Alpha; + info.invalpha = FRACUNIT - info.alpha; + info.op = ECopyOp(Parts[i].op); 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); + ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); } else { @@ -626,6 +652,8 @@ FMultiPatchTexture::TexPart::TexPart() Texture = NULL; Translation = NULL; Blend = 0; + Alpha = FRACUNIT; + op = OP_COPY; } //========================================================================== @@ -961,15 +989,14 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part) { int r,g,b; - sc.MustGetNumber(); - sc.MustGetStringName(","); r = sc.Number; - sc.MustGetNumber(); sc.MustGetStringName(","); + sc.MustGetNumber(); g = sc.Number; - sc.MustGetNumber(); sc.MustGetStringName(","); + sc.MustGetNumber(); b = sc.Number; + sc.MustGetStringName(","); part.Blend = MAKERGB(r, g, b); } if (sc.CheckString(",")) @@ -980,6 +1007,19 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part) else part.Blend.a = 255; bComplex = true; } + else if (sc.Compare("alpha")) + { + sc.MustGetFloat(); + part.Alpha = clamp(FLOAT2FIXED(sc.Float), 0, FRACUNIT); + // bComplex is not set because it is only needed when the style is not OP_COPY. + } + else if (sc.Compare("style")) + { + static const char *styles[] = {"copy", "blend", "add", "subtract", "reversesubtract", "modulate", "copyalpha", NULL }; + sc.MustGetString(); + part.op = sc.MustMatchString(styles); + bTranslucentPatches = bComplex = (part.op != OP_COPY); + } } } if (Mirror & 2) @@ -995,7 +1035,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part) FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) -: Pixels (0), Spans(0), Parts(0), bRedirect(false) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { TArray parts; diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index cd248deb..0a710a42 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -462,13 +462,13 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo c=0x0c; // Apparently there's many non-compliant PCXs out there... if (c !=0x0c) { - for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map + for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map } else for(int i=0;i<256;i++) { BYTE r,g,b; lump >> r >> g >> b; - pe[i] = PalEntry(r,g,b); + pe[i] = PalEntry(255, r,g,b); } lump.Seek(sizeof(header), SEEK_SET); ReadPCX8bits (Pixels, lump, &header); diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 8e36c89d..55f1908f 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -511,7 +511,7 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo } lump->Seek (33, SEEK_SET); - for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map + for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map (*lump) >> len >> id; while (id != MAKE_ID('I','D','A','T') && id != MAKE_ID('I','E','N','D')) @@ -534,7 +534,6 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo for(DWORD i=0;i> pe[i].a; - pe[i].a=255-pe[i].a; // use inverse alpha so the default palette can be used unchanged if (pe[i].a!=0 && pe[i].a!=255) transpal = true; } break; diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 8bea144c..6fde4384 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -483,20 +483,16 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt) 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 + for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); - - palette[0].a=0; + for(int i=1;i<256;i++) palette[i].a = 0; return 0; } -int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap) +int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap, FCopyInfo *inf) { PalEntry *palette = remap->Palette; - palette[0].a=255; // temporarily modify the first color's alpha - bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette); - - palette[0].a=0; + bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); return 0; } diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index cf544629..97fe0455 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -436,7 +436,7 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo r=g=b=a=0; break; } - pe[i] = PalEntry(255-a, r, g, b); + pe[i] = PalEntry(a, r, g, b); } } @@ -506,7 +506,7 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo switch (hdr.bpp) { case 8: - for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map + for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // gray map bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf); break; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 1501edfa..c96991df 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1283,11 +1283,11 @@ static void ActorStates (FScanner &sc, AActor *defaults, Baggage &bag) static void ActorRenderStyle (FScanner &sc, AActor *defaults, Baggage &bag) { static const char * renderstyles[]={ - "NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD",NULL}; + "NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD","SHADED", NULL}; static const int renderstyle_values[]={ STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, - STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add}; + STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded}; sc.MustGetString(); defaults->RenderStyle = LegacyRenderStyles[renderstyle_values[sc.MustMatchString(renderstyles)]]; diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp index a1541f6b..33890862 100644 --- a/src/timidity/instrum.cpp +++ b/src/timidity/instrum.cpp @@ -31,6 +31,7 @@ #include "timidity.h" #include "m_swap.h" #include "files.h" +#include "templates.h" namespace Timidity { @@ -359,6 +360,7 @@ fail: } } +#if 0 /* 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 @@ -411,11 +413,13 @@ fail: cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n"); } } +#endif for (j = 0; j < 6; j++) { sp->envelope_rate[j] = convert_envelope_rate(song, patch_data.EnvelopeRate[j]); - sp->envelope_offset[j] = convert_envelope_offset(patch_data.EnvelopeOffset[j]); + // GF1NEW clamps the offsets to the range [5,251], so we do too. + sp->envelope_offset[j] = convert_envelope_offset(clamp(patch_data.EnvelopeOffset[j], 5, 251)); } /* Then read the sample data */ diff --git a/src/timidity/mix.cpp b/src/timidity/mix.cpp index 275893f7..cd0443a7 100644 --- a/src/timidity/mix.cpp +++ b/src/timidity/mix.cpp @@ -38,35 +38,36 @@ int recompute_envelope(Voice *v) stage = v->envelope_stage; - if (stage > RELEASEC) + if (stage >= ENVELOPES) { /* Envelope ran out. */ - v->status = VOICE_FREE; - return 1; + /* play sampled release */ + v->status &= ~(VOICE_SUSTAINING | VOICE_LPE); + v->status |= VOICE_RELEASING; + v->envelope_increment = 0; + return 0; } - if (v->sample->modes & PATCH_NO_SRELEASE) + if (stage == RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN)) { - if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED) + v->status |= VOICE_SUSTAINING; + /* Freeze envelope until note turns off. Trumpets want this. */ + v->envelope_increment = 0; + } + else + { + v->envelope_stage = stage + 1; + + if (v->envelope_volume == v->sample->envelope_offset[stage]) { - if (stage > DECAY) - { - /* Freeze envelope until note turns off. Trumpets want this. */ - v->envelope_increment = 0; - return 0; - } + 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) + v->envelope_increment = -v->envelope_increment; } - 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) - v->envelope_increment = -v->envelope_increment; return 0; } @@ -78,10 +79,7 @@ void apply_envelope_to_amp(Voice *v) { env_vol *= v->tremolo_volume; } - if (v->sample->modes & PATCH_NO_SRELEASE) - { - env_vol *= v->envelope_volume / float(1 << 30); - } + env_vol *= v->envelope_volume / float(1 << 30); // Note: The pan offsets are negative. v->left_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->left_offset) * final_amp); v->right_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->right_offset) * final_amp); @@ -426,13 +424,13 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c) { return; } - if (v->status == VOICE_DIE) + if (v->status & VOICE_STOPPING) { if (count >= MAX_DIE_TIME) count = MAX_DIE_TIME; sp = resample_voice(song, v, &count); ramp_out(sp, buf, v, count); - v->status = VOICE_FREE; + v->status = 0; } else { diff --git a/src/timidity/playmidi.cpp b/src/timidity/playmidi.cpp index 1c8a332e..9671e21e 100644 --- a/src/timidity/playmidi.cpp +++ b/src/timidity/playmidi.cpp @@ -37,7 +37,7 @@ void Renderer::reset_voices() { for (int i = 0; i < voices; i++) { - voice[i].status = VOICE_FREE; + voice[i].status = 0; } } @@ -254,7 +254,7 @@ void Renderer::kill_key_group(int i) } while (j--) { - if (voice[j].status != VOICE_ON && voice[j].status != VOICE_SUSTAINED) continue; + if ((voice[j].status & VOICE_RUNNING) && !(voice[j].status & (VOICE_RELEASING | VOICE_STOPPING))) continue; if (i == j) continue; if (voice[i].channel != voice[j].channel) continue; if (voice[j].sample->key_group != voice[i].sample->key_group) continue; @@ -273,6 +273,7 @@ void Renderer::start_note(int chan, int note, int vel, int i) Instrument *ip; int bank = channel[chan].bank; int prog = channel[chan].program; + Voice *v = &voice[i]; if (ISDRUMCHANNEL(chan)) { @@ -301,66 +302,71 @@ void Renderer::start_note(int chan, int note, int vel, int i) } if (ip->sample->scale_factor != 1024) { - voice[i].orig_frequency = calculate_scaled_frequency(ip->sample, note & 0x7F); + v->orig_frequency = calculate_scaled_frequency(ip->sample, note & 0x7F); } else { - voice[i].orig_frequency = note_to_freq(note & 0x7F); + v->orig_frequency = note_to_freq(note & 0x7F); } select_sample(i, ip, vel); - voice[i].status = VOICE_ON; - voice[i].channel = chan; - voice[i].note = note; - voice[i].velocity = vel; - voice[i].sample_offset = 0; - voice[i].sample_increment = 0; /* make sure it isn't negative */ + v->status = VOICE_RUNNING; + v->channel = chan; + v->note = note; + v->velocity = vel; + v->sample_offset = 0; + v->sample_increment = 0; /* make sure it isn't negative */ - voice[i].tremolo_phase = 0; - voice[i].tremolo_phase_increment = voice[i].sample->tremolo_phase_increment; - voice[i].tremolo_sweep = voice[i].sample->tremolo_sweep_increment; - voice[i].tremolo_sweep_position = 0; + v->tremolo_phase = 0; + v->tremolo_phase_increment = voice[i].sample->tremolo_phase_increment; + v->tremolo_sweep = voice[i].sample->tremolo_sweep_increment; + v->tremolo_sweep_position = 0; - voice[i].vibrato_sweep = voice[i].sample->vibrato_sweep_increment; - voice[i].vibrato_sweep_position = 0; - voice[i].vibrato_control_ratio = voice[i].sample->vibrato_control_ratio; - voice[i].vibrato_control_counter = voice[i].vibrato_phase = 0; + v->vibrato_sweep = voice[i].sample->vibrato_sweep_increment; + v->vibrato_sweep_position = 0; + v->vibrato_control_ratio = voice[i].sample->vibrato_control_ratio; + v->vibrato_control_counter = voice[i].vibrato_phase = 0; kill_key_group(i); - memset(voice[i].vibrato_sample_increment, 0, sizeof(voice[i].vibrato_sample_increment)); + memset(v->vibrato_sample_increment, 0, sizeof(v->vibrato_sample_increment)); if (channel[chan].panning != NO_PANNING) { - voice[i].left_offset = channel[chan].left_offset; - voice[i].right_offset = channel[chan].right_offset; + v->left_offset = channel[chan].left_offset; + v->right_offset = channel[chan].right_offset; } else { - voice[i].left_offset = voice[i].sample->left_offset; - voice[i].right_offset = voice[i].sample->right_offset; + v->left_offset = v->sample->left_offset; + v->right_offset = v->sample->right_offset; } recompute_freq(i); - recompute_amp(&voice[i]); - if (voice[i].sample->modes & PATCH_NO_SRELEASE) + recompute_amp(v); + + /* Ramp up from 0 */ + v->envelope_stage = ATTACK; + v->envelope_volume = 0; + v->control_counter = 0; + recompute_envelope(v); + apply_envelope_to_amp(v); + + if (v->sample->modes & PATCH_LOOPEN) { - /* Ramp up from 0 */ - voice[i].envelope_stage = ATTACK; - voice[i].envelope_volume = 0; - voice[i].control_counter = 0; - recompute_envelope(&voice[i]); + v->status |= VOICE_LPE; } - else - { - voice[i].envelope_increment = 0; - } - apply_envelope_to_amp(&voice[i]); } void Renderer::kill_note(int i) { - voice[i].status = VOICE_DIE; + Voice *v = &voice[i]; + + if (v->status & VOICE_RUNNING) + { + v->status &= ~VOICE_SUSTAINING; + v->status |= VOICE_RELEASING | VOICE_STOPPING; + } } /* Only one instance of a note can be playing on a single channel. */ @@ -377,13 +383,20 @@ void Renderer::note_on(int chan, int note, int vel) while (i--) { - if (voice[i].status == VOICE_FREE) + if (!(voice[i].status & VOICE_RUNNING)) { lowest = i; /* Can't get a lower volume than silence */ } else if (voice[i].channel == chan && ((voice[i].note == note && !voice[i].sample->self_nonexclusive) || channel[chan].mono)) { - kill_note(i); + if (channel[chan].mono) + { + kill_note(i); + } + else + { + finish_note(i); + } } } @@ -400,7 +413,7 @@ void Renderer::note_on(int chan, int note, int vel) i = voices; while (i--) { - if (voice[i].status != VOICE_ON && voice[i].status != VOICE_DIE) + if ((voice[i].status & VOICE_RELEASING) && !(voice[i].status & VOICE_STOPPING)) { v = voice[i].attenuation; if (v < lv) @@ -420,7 +433,7 @@ void Renderer::note_on(int chan, int note, int vel) we could use a reserve of voices to play dying notes only. */ cut_notes++; - voice[lowest].status = VOICE_FREE; + voice[lowest].status = 0; start_note(chan, note, vel, lowest); } else @@ -431,44 +444,54 @@ void Renderer::note_on(int chan, int note, int vel) void Renderer::finish_note(int i) { - if (voice[i].sample->modes & PATCH_NO_SRELEASE) + Voice *v = &voice[i]; + + if ((v->status & (VOICE_RUNNING | VOICE_RELEASING)) == VOICE_RUNNING) { - /* We need to get the envelope out of Sustain stage */ - voice[i].envelope_stage = RELEASE; - voice[i].status = VOICE_OFF; - recompute_envelope(&voice[i]); - apply_envelope_to_amp(&voice[i]); - } - else - { - /* Set status to OFF so resample_voice() will let this voice out - of its loop, if any. In any case, this voice dies when it - hits the end of its data (ofs >= data_length). */ - voice[i].status = VOICE_OFF; + v->status &= ~VOICE_SUSTAINING; + v->status |= VOICE_RELEASING; + + if (!(v->sample->modes & PATCH_NO_SRELEASE)) + { + v->status &= ~VOICE_LPE; /* sampled release */ + } + if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL)) + { + /* ramp out to minimum volume with rate from final release stage */ + v->envelope_stage = RELEASEC; + recompute_envelope(v); + // Get rate from the final release ramp, but force the target to 0. + v->envelope_target = 0; + v->envelope_increment = -v->sample->envelope_rate[RELEASEC]; + } + else if (v->sample->modes & PATCH_SUSTAIN) + { + if (v->envelope_stage < RELEASE) + { + v->envelope_stage = RELEASE; + } + recompute_envelope(v); + } } } void Renderer::note_off(int chan, int note, int vel) { - int i = voices; - while (i--) + int i; + + for (i = voices; i-- > 0; ) { - if (voice[i].status == VOICE_ON && - voice[i].channel == chan && - voice[i].note == note) + if ((voice[i].status & VOICE_RUNNING) && !(voice[i].status & (VOICE_RELEASING | VOICE_STOPPING)) + && voice[i].channel == chan && voice[i].note == note) { if (channel[chan].sustain) { - voice[i].status = VOICE_SUSTAINED; + voice[i].status |= NOTE_SUSTAIN; } else { finish_note(i); } - if (!voice[i].sample->self_nonexclusive) - { - return; - } } } } @@ -479,11 +502,11 @@ void Renderer::all_notes_off(int chan) int i = voices; while (i--) { - if (voice[i].status == VOICE_ON && voice[i].channel == chan) + if ((voice[i].status & VOICE_RUNNING) && voice[i].channel == chan) { if (channel[chan].sustain) { - voice[i].status = VOICE_SUSTAINED; + voice[i].status |= NOTE_SUSTAIN; } else { @@ -500,8 +523,8 @@ void Renderer::all_sounds_off(int chan) while (i--) { if (voice[i].channel == chan && - voice[i].status != VOICE_FREE && - voice[i].status != VOICE_DIE) + (voice[i].status & VOICE_RUNNING) && + !(voice[i].status & VOICE_STOPPING)) { kill_note(i); } @@ -513,7 +536,7 @@ void Renderer::adjust_pressure(int chan, int note, int amount) int i = voices; while (i--) { - if (voice[i].status == VOICE_ON && + if ((voice[i].status & VOICE_RUNNING) && voice[i].channel == chan && voice[i].note == note) { @@ -535,8 +558,7 @@ void Renderer::adjust_panning(int chan) int i = voices; while (i--) { - if ((voice[i].channel == chan) && - (voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED)) + if ((voice[i].channel == chan) && (voice[i].status & VOICE_RUNNING)) { voice[i].left_offset = chanp->left_offset; voice[i].right_offset = chanp->right_offset; @@ -550,7 +572,7 @@ void Renderer::drop_sustain(int chan) int i = voices; while (i--) { - if (voice[i].status == VOICE_SUSTAINED && voice[i].channel == chan) + if (voice[i].channel == chan && (voice[i].status & NOTE_SUSTAIN)) { finish_note(i); } @@ -562,7 +584,7 @@ void Renderer::adjust_pitchbend(int chan) int i = voices; while (i--) { - if (voice[i].status != VOICE_FREE && voice[i].channel == chan) + if ((voice[i].status & VOICE_RUNNING) && voice[i].channel == chan) { recompute_freq(i); } @@ -574,8 +596,7 @@ void Renderer::adjust_volume(int chan) int i = voices; while (i--) { - if (voice[i].channel == chan && - (voice[i].status == VOICE_ON || voice[i].status == VOICE_SUSTAINED)) + if (voice[i].channel == chan && (voice[i].status & VOICE_RUNNING)) { recompute_amp(&voice[i]); apply_envelope_to_amp(&voice[i]); diff --git a/src/timidity/resample.cpp b/src/timidity/resample.cpp index 5569eea5..2b30dd55 100644 --- a/src/timidity/resample.cpp +++ b/src/timidity/resample.cpp @@ -81,7 +81,7 @@ static sample_t *rs_plain(sample_t *resample_buffer, Voice *v, int *countptr) if (ofs >= le) { FINALINTERP; - v->status = VOICE_FREE; + v->status = 0; *countptr -= count + 1; } @@ -309,7 +309,7 @@ static sample_t *rs_vib_plain(sample_t *resample_buffer, float rate, Voice *vp, if (ofs >= le) { FINALINTERP; - vp->status = VOICE_FREE; + vp->status = 0; *countptr -= count+1; break; } @@ -494,7 +494,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr) if (*countptr >= (vp->sample->data_length >> FRACTION_BITS) - ofs) { /* Note finished. Free the voice. */ - vp->status = VOICE_FREE; + vp->status = 0; /* Let the caller know how much data we had left */ *countptr = (vp->sample->data_length >> FRACTION_BITS) - ofs; @@ -511,9 +511,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr) if (vp->vibrato_control_ratio) { - if ((modes & PATCH_LOOPEN) && - ((modes & PATCH_NO_SRELEASE) || - (vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) + if (vp->status & VOICE_LPE) { if (modes & PATCH_BIDIR) return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr); @@ -527,9 +525,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr) } else { - if ((modes & PATCH_LOOPEN) && - ((modes & PATCH_NO_SRELEASE) || - (vp->status == VOICE_ON || vp->status == VOICE_SUSTAINED))) + if (vp->status & VOICE_LPE) { if (modes & PATCH_BIDIR) return rs_bidir(song->resample_buffer, vp, *countptr); diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp index 2927fc74..b1cd1cd5 100644 --- a/src/timidity/timidity.cpp +++ b/src/timidity/timidity.cpp @@ -500,7 +500,7 @@ void Renderer::ComputeOutput(float *buffer, int count) } for (int i = 0; i < voices; i++, v++) { - if (v->status != VOICE_FREE) + if (v->status & VOICE_RUNNING) { mix_voice(this, buffer, v, count); } diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h index db29e346..24f87adc 100644 --- a/src/timidity/timidity.h +++ b/src/timidity/timidity.h @@ -315,8 +315,8 @@ struct GF1PatchData int RootFrequency; SWORD Tune; BYTE Balance; - BYTE EnvelopeRate[6]; - BYTE EnvelopeOffset[6]; + BYTE EnvelopeRate[ENVELOPES]; + BYTE EnvelopeOffset[ENVELOPES]; BYTE TremoloSweep; BYTE TremoloRate; BYTE TremoloDepth; @@ -444,7 +444,7 @@ struct Channel { int bank, program, sustain, pitchbend, - mono, /* one note only on this channel -- not implemented yet */ + mono, /* one note only on this channel */ pitchsens; WORD volume, expression; @@ -462,8 +462,6 @@ struct Channel /* Causes the instrument's default panning to be used. */ #define NO_PANNING -1 -/* envelope points */ -#define MAXPOINT 6 struct Voice { @@ -496,11 +494,13 @@ struct Voice /* Voice status options: */ enum { - VOICE_FREE, - VOICE_ON, - VOICE_SUSTAINED, - VOICE_OFF, - VOICE_DIE + VOICE_RUNNING = (1<<0), + VOICE_SUSTAINING = (1<<1), + VOICE_RELEASING = (1<<2), + VOICE_STOPPING = (1<<3), + + VOICE_LPE = (1<<4), + NOTE_SUSTAIN = (1<<5), }; /* Envelope stages: */ diff --git a/src/version.h b/src/version.h index f3577f39..9870a84a 100644 --- a/src/version.h +++ b/src/version.h @@ -77,7 +77,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 922 +#define MINSAVEVER 932 #if ZD_SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/src/wi_stuff.h b/src/wi_stuff.h index e14d08dd..28be48f0 100644 --- a/src/wi_stuff.h +++ b/src/wi_stuff.h @@ -47,11 +47,11 @@ typedef struct wbstartstruct_s int finished_ep; int next_ep; - char current[8]; // [RH] Name of map just finished - char next[8]; // next level, [RH] actual map name + char current[9]; // [RH] Name of map just finished + char next[9]; // next level, [RH] actual map name - char lname0[8]; - char lname1[8]; + char lname0[9]; + char lname1[9]; int maxkills; int maxitems; diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 3a34231c..4fae6a99 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2086,13 +2086,13 @@ bool D3DPal::Update() for (i = 0; i < skipat; ++i) { - buff[i] = D3DCOLOR_ARGB(i == 0 ? 0 : 255, pal[i].r, pal[i].g, pal[i].b); + buff[i] = D3DCOLOR_ARGB(pal[i].a, pal[i].r, pal[i].g, pal[i].b); } for (++i; i < Remap->NumEntries; ++i) { - buff[i] = D3DCOLOR_ARGB(255, pal[i-1].r, pal[i-1].g, pal[i-1].b); + buff[i] = D3DCOLOR_ARGB(pal[i].a, pal[i-1].r, pal[i-1].g, pal[i-1].b); } - BorderColor = D3DCOLOR_ARGB(255, pal[i-1].r, pal[i-1].g, pal[i-1].b); + BorderColor = D3DCOLOR_ARGB(pal[i].a, pal[i-1].r, pal[i-1].g, pal[i-1].b); Tex->UnlockRect(0); return true; diff --git a/wadsrc/sndinfo.txt b/wadsrc/sndinfo.txt index d7a23189..9956593b 100644 --- a/wadsrc/sndinfo.txt +++ b/wadsrc/sndinfo.txt @@ -202,6 +202,13 @@ weapons/bfgf dsbfg weapons/bfgx dsrxplod weapons/railgf railgf1 +// Problem: weapons/rocklx needs to be unlimited but +// is also used for the MAP30 brain explosion. +// This alias remaps to the original but has its own limit +// attached so that it doesn't become too loud. +$alias misc/brainexplode weapons/rocklx +$limit misc/brainexplode 4 + $limit weapons/plasmaf 0 $limit weapons/chngun 0 $limit weapons/rocklf 0 // because normal running is almost as fast as a rocket