1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-05 02:39:41 +01:00
Commit graph

69 commits

Author SHA1 Message Date
Misa
510ec07021 Re-fix resumemusic/musicfadein once again
So it looks like facb079b35 (PR #316) had
a few issues.

The SDL performance counter doesn't really work that well. Testing
reveals that unfocusing and focusing the game again results in
the resumemusic() script command resuming the track at the wrong time.
Even when not unfocusing the game at all, stopping a track and resuming
it resumes it at the wrong time. (Only disabling the unfocus pause fixes
this.)

Furthermore, there's also the fact that the SDL performance counter
keeps incrementing when the game is paused under GDB. So... yeah.

Instead of dealing with the SDL performance counter, I'm just going to
pause and resume the music directly (so the stopmusic() script command
just pauses the music instead). As a result, we no longer can keep
constantly calling Mix_PauseMusic() or Mix_ResumeMusic() when focused or
unfocused, so I've moved those calls to happen directly when the
relevant SDL events are received (the constant calls were originally in
VCE, and whoever added them (I'm pretty sure it was Leo) was not the
sharpest tool in the shed...).

And we are going to switch over to using our own fade system instead of
the SDL mixer fade system. In fact, we were already using our own fade
system for fadeins after collecting a trinket or a custom level
crewmate, but we were still using the mixer system for the rest. This is
an inconsistency that I am glad to correct, so we're also doing our own
fadeouts now.

There is, however, an issue with the fade system where the length it
goes for is inaccurate, because it's based on a volume-per-frame second
calculation that gets truncated. But that's an issue to fix later - at
least what I'm doing right now makes resumemusic() and musicfadein()
work better than before.
2021-04-02 16:13:54 -04:00
Misa
6d3a73c540 Add pause(), pauseef(), and resumeef() to musicclass
musicclass already had a resume() function for music.

These are just wrappers around the appropriate SDL_mixer functions, to
avoid direct function calls to the mixer API. So if we ever need to do
something with all callers of pausing and resuming in the future, or we
switch to a different audio backend, the work is already done for us.

Also it just looks cleaner to be calling our musicclass function instead
of doing a direct API call to the mixer.
2021-04-02 16:13:54 -04:00
Misa
92b3c0b413 Factor fade amount calculation to separate function
This makes it so to reuse this code, we don't have to copy-paste it.

Additionally, I added a check for the milliseconds being 0, to avoid a
division by zero. Logically and mathematically, if the fade amount is 0
milliseconds, then that means the fade should happen instantly -
however, dividing by zero is undefined (both in math and in C/C++), so
this check needs to be added.
2021-04-02 16:13:54 -04:00
Misa
babd86916c Move resumesong assignment to songend()
This fixes a bug where the resumemusic() script command would always
play MMMMMM track 15 (or, if you're using PPPPPP, just not work). This
is because musicclass::haltdasmusik() assigns resumesong AFTER calling
Mix_HaltMusic(), but the songend() callback fires before the resumesong
assignment, meaning resumesong gets set to -1 instead of whatever
currentsong was previously.

To fix this, just move the assignment into the callback itself (I don't
know why this wasn't done before). I could have moved it to before the
Mix_HaltMusic() call, but moving it into the callback itself fixes it
for all cases of the music stopping (such as when the music fades out).
2021-03-10 09:45:20 -05:00
Misa
3171a97160 Replace all SDL_RWFromMem() with SDL_RWFromConstMem()
Since we're not going to be writing to any of these RWops, we might as
well just ensure that we don't by using SDL_RWFromConstMem().
2021-02-25 19:39:48 -05:00
Misa
6a3a1fe147
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.

This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.

I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 17:23:59 -05:00
Misa
141181dee7 Refactor extra binary blob tracks to not use STL data marshalling
Just like I refactored text splitting to no longer use std::vectors,
std::strings, or temporary heap allocations, decreasing memory usage and
improving performance; there's no reason to use a temporary
heap-allocated std::vector to grab all extra binary blob indices, when
instead the iteration can just be more immediate.

Instead, what I've done is replaced binaryBlob::getExtra() with
binaryBlob::nextExtra(), which takes in a pointer to an index variable,
and will increment the index variable until it reaches an extra track.
After the caller processes the extra track, it is the caller's
responsibility to increment the variable again before passing it back to
getExtra().

This avoids all heap allocations and brings down the memory usage of
processing extra tracks.
2021-02-19 07:07:39 -05:00
Misa
7f3ebda8ea Clear musicWriteBlob after writing BinaryMusic.vvv
Since musicWriteBlob is a temporary object that gets destroyed at the
end of musicclass::init(), in order to make sure we don't leak memory
and lose all the pointers to the blocks we just allocated in
musicWriteBlob, we need to call its clear() method after writing
BinaryMusic.vvv.
2021-02-15 23:07:35 -05:00
Misa
77748f29f9 Separate musicReadBlob into mmmmmm_blob and pppppp_blob
musicReadBlob was used for both MMMMMM and PPPPPP soundtracks. This
causes a memory leak if you have mmmmmm.vvv installed, because the
pointers holding each allocated block of MMMMMM would be lost when
PPPPPP got loaded. Valgrind complains about this memory leak.

This is in contrast to 2.2 and previous behavior, where musicReadBlob
was only a temporary object instead of being held in musicclass.
However, this wasn't really a memory leak (moreso something that just
didn't get cleaned up when closing the game), but it did get turned into
a leak when per-level assets mounting and unmounting got introduced in
2.3 (loading a level with custom assets after starting the game with an
mmmmmm.vvv, or exiting out of a level that had an mmmmmm.vvv, would
cause the game to leak memory). Leo recognized this, and moved
musicReadBlob onto musicclass in a separate 2.3 PR, but either he didn't
think about what was happening here too closely, or he didn't use
Valgrind, because he forgot about the memory leak caused by re-using the
same binaryBlob for PPPPPP and MMMMMM.

So instead, just use two different binaryBlob objects for MMMMMM and
PPPPPP. That way, no memory leaks happen.
2021-02-15 23:07:35 -05:00
Misa
f39174b3e3 Refactor TRACK_NAMES to take in a blob parameter
I'm going to introduce another binaryBlob object in to the mix, and I
want to be able to re-use an existing FOREACH_TRACK #define without
having to copy-paste it again. So, TRACK_NAMES now takes in a blob
parameter, which will be passed to the temporary FOREACH_TRACK #define.
2021-02-15 23:07:35 -05:00
Misa
0ea1a0e28e Move musicclass cleanup to separate function musicclass::destroy()
This removes the music cleanup code from musicclass::init(), and
requires that we also call destroy() in Graphics::reloadresources().

This is because we'll need to re-use the musicclass cleanup code
elsewhere, and we don't want to copy-paste the cleanup code. Or at
least, I don't (but I'm not a game dev, game devs copy-paste all the
friggin' time).
2021-02-15 23:07:35 -05:00
Misa
f06701ff90 Fix wrong function being used for musicclass::play() check
Whoops.
2021-01-16 15:37:22 -05:00
Misa
e9c62ea9a3 Clean up unnecessary exports and add static keywords
This patch cleans up unnecessary exports from header files (there were
only a few), as well as adds the static keyword to all symbols that
aren't exported and are specific to a file. This helps the linker out in
not doing any unnecessary work, speeding it up and avoiding silent
symbol conflicts (otherwise two symbols with the same name (and
type/signature in C++) would quietly resolve as okay by the linker).
2021-01-10 12:23:59 -05:00
Misa
5e557ffd1a Fix regression with playing the same track after it fades out
With commit 48313169b6 (PR #453),
AllyTally added a single-case patch for a regression, instead of fixing
it at its root cause.

In fact, that commit only fixes the music if Presenting VVVVVV is
playing while exiting to the menu, not if you enter a level that plays
Presenting VVVVVV - so it only fixes it going one way, and not going the
other way around; neither fixing also all the other cases this could
happen.

It doesn't, say, fix the case where you are exited to the menu
automatically after collecting the last crewmate in the level (or if the
level calls gamestate 1013 itself), which is what happens in my MIRA-VIU
TAS video at the end, and which I noted in the description of that video
( https://www.youtube.com/watch?v=OYQO4ePbYW4&t=111 ).

So, the problem here is that when musicclass::play() is called, it sees
that currentsong is the same as its input, and decides that since the
music is already playing, it shouldn't play the music again. Thus, the
music fades out, and we get silence instead of the music playing again.

But I said this was a regression. Why didn't this happen in 2.2? Well,
it's because of the fact that 2.2 sets currentsong to -1 (no music
playing at all) immediately when starting a fadeout, and not when the
fadeout completes (commit facb079b35,
PR #316). As you can imagine, this discrepancy could lead to bugs, given
that the game would think that music wasn't playing when in actuality it
was, but fixing this bug could also break code that expected this wrong
behavior. And in this case, it has.

So to properly fix the root cause of this, instead of naïvely
single-case patching out every case that comes up randomly, in
musicclass::play(), the function will now ignore if the input given is
the same as currentsong if the music is currently fading out.
2021-01-04 19:16:35 -05:00
Misa
8e5714439a Unindent musicclass::play() from previous two commits
As always, the actual unindenting happens in a separate commit in order
to minimize diff noise.
2021-01-04 05:09:23 -05:00
Misa
f64cf4f831 Invert t comparison with -1 and un-nest rest of function
This is also another conditional where the rest of the function is
nested. Furthermore, in order to not repeat ourselves, I've also decided
to unconditionally assign currentsong to t, because if t is -1
currentsong gets assigned to -1 anyway - so it's the same thing, but
it's much easier to see and think about.
2021-01-04 05:09:23 -05:00
Misa
fe5bacfdc2 Invert currentsong check and un-nest rest of function
This removes an indentation level, and makes it easier to reason about
the function since you essentially now view it as the function returning
right there.
2021-01-04 05:09:23 -05:00
Misa
96c479a11f Fix whitespace inconsistency in musicclass::play()
Spaces are used around operators and keywords accordingly, and blank
lines are used to visually separate lines of code from each other.
2021-01-04 05:09:23 -05:00
Misa
eb7b540346 Fix no-draw frames when exiting a level with custom assets
When exiting a level, music.init() gets called again, and every time it
gets called after the first time it gets called, it will free all music
tracks.

To do so, it calls Mix_FreeMusic(). Unfortunately, if there is music
fading, Mix_FreeMusic() will call SDL_Delay(), which will result in
annoying no-draw frames. Meaning, the screen freezes and doesn't draw
anything, and has to wait a bit before continuing.

Here's the relevant piece of code from SDL2_mixer's music.c:

    if (music == music_playing) {
        /* Wait for any fade out to finish */
        while (music->fading == MIX_FADING_OUT) {
            Mix_UnlockAudio();
            SDL_Delay(100);
            Mix_LockAudio();
        }
        if (music == music_playing) {
            music_internal_halt();
        }
    }

This is especially annoying if you're a TASer, because no-draw frames in
a libTAS movie aren't guaranteed to last for a consistent number of
frames when you change your inputs around.

After this patch, as long as your computer can unmount and re-mount
assets fast enough (it doesn't seem like mine can, unfortunately), then
you won't get any freezes when exiting a level that has custom assets.
(This freeze didn't happen when loading a level because the title screen
music fadeout upon pressing ACTION had enough time to fully complete
before the level got loaded.)
2020-12-28 16:01:05 -05:00
Misa
12e3c579ed Don't set music.usingmmmmmm to true when (un)loading custom assets
For some reason, music.usingmmmmmm automatically gets set to true in
musicclass::init(). I assume this was because it would get re-assigned
by game.usingmmmmmm in the game startup code anyway, but now that
musicclass::init() can be called more than once, this variable will just
get set to true when it shouldn't be, causing a confusing desync just
like the one I described in my previous commit, where you would have
PPPPPP or MMMMMM on the title screen, but closing the game and
re-launching it would play the other soundtrack instead.

Again, these duplicate variables should be removed, but that's going to
be a separate patch. In the meantime, I'm removing this variable
assignment.
2020-11-12 19:11:13 -05:00
Misa
98ef7a8675 Don't reset entire musicclass when mounting and unmounting assets
musicclass::init() re-initializes every attribute of musicclass
unnecessarily, when initialization should be put in a constructor
instead. This is bad, because music.init() gets called whenever we enter
and exit a custom level that has assets.

Otherwise, this would result in a bug where music.usingmmmmmm would be
reset, causing you to revert to PPPPPP on the title screen whenever you
enter a level with MMMMMM selected and exit it.

This also causes a confusing desync between game.usingmmmmmm and
music.usingmmmmmm since the values of the two variables are now
different (these duplicate variables should probably be removed, too,
and a lot of other duplicate variables like these exist, too, which are
a real headache). Which means despite MMMMMM playing on the title
screen, exiting the game and re-launching it will play PPPPPP instead.
What's even more is that going to game options and switching to PPPPPP
will play PPPPPP, but afterwards launching and re-entering will play
MMMMMM. Again, having duplicate variables is very bad, and should
probably be fixed, but that's a separate patch.
2020-11-12 19:11:13 -05:00
Misa
05b7a38f76 Clean up don't-quick-fade signaling
First, the variable has been inverted, because it's bad practice to have
booleans with negative names. Secondly, instead of magically setting a
signaling variable when calling fadeout(), fadeout() now has a parameter
to set the quick_fade attribute, which is much cleaner than doing the
magical assignment that could potentially look unrelated.
2020-11-06 06:09:31 -05:00
Misa
87af9bba04 Merge fadeoutqueuesong into nicechange
fadeoutqueuesong basically does the same thing as nicechange - they both
queue a song to be played when the current track is done fading out.
Except, for some reason, I decided to add fadeoutqueuesong instead of
using the existing nicechange/nicefade system.

This has consequences where fadeoutqueuesong would step on the toes of
nicechange. In the case of #390, nicechange would say "let's play
Potential for Anything" when entering the Super Gravitron, but
fadeoutqueuesong had previously said "let's play Pipe Dream" because of
the player having just exited the Super Gravitron. fadeoutqueuesong took
priority because it came first in musicclass::processfade(), and when it
called play(), the Mix_PlayingMusic() in the nicechange check afterwards
would say music would already be playing at that point, so the
nicechange wouldn't take effect.

In the end, the solution is to just merge the new system into the
already-existing system.

Fixes #390.
2020-11-06 06:09:31 -05:00
Misa
410d80b731 Fix song 0/7 check using num_pppppp_tracks instead of num_mmmmmm_tracks
Just looked over this and had to do a double-take. It should be
num_mmmmmm_tracks, not num_pppppp_tracks, because MMMMMM comes first in
the vector of music tracks.
2020-11-06 06:09:31 -05:00
Misa
9698b42432 Initialize nicechange to -1 for consistency
The game uses -1 to denote "no song" elsewhere, especially when a
niceplay() has finished processing and it sets nicechange to -1 there,
too.
2020-11-06 06:09:31 -05:00
Misa
c1ca57e096 Change nicefade to bool instead of int
If it's treated like a bool, why shouldn't it be one?
2020-11-06 06:09:31 -05:00
Misa
f0b9bdc007 Fix niceplay() check having hardcoded number of MMMMMM tracks
The number of MMMMMM tracks is no longer guaranteed to be 16 anymore,
and instead it should use num_mmmmmm_tracks.
2020-11-06 06:09:31 -05:00
Misa
3434ad8777 Fix variables shadowing other variables
In C++, when you have two variables in different scopes with the same
name, the inner scope wins. Except you have to be really careful because
sometimes they're not (#507). So it's better to just always have unique
variable names and make sure to never clash a name with a variable in an
outer scope - after all, the C++ compiler and standard might be fine
with it, but that doesn't mean humans can't make mistakes reading or
writing it.

Usually I just renamed the inner variables, but for tx/ty in editor.cpp,
I just got rid of the ridiculous overcomplicated modulo calculations and
replaced them with actual simple modulo calculations, because the
existing ones were just ridiculous. Actually, somebody ought to find
every instance of the overcomplicated modulos and replace them with the
actual good ones, because it's really stupid, quite frankly...
2020-11-04 08:38:19 -05:00
Misa
71c8c54313 Clean up music handling to one place
Previously, setting the actual volume of the music was all over the
place. Which isn't bad, but when I added being able to press N to mute
the music specifically, I should've made it so that there would be a
volume variable somewhere that the game looks at if the music is
unmuted, and otherwise sets the actual volume to 0 if the game is muted.

This resulted in things like #400 and #505 and having to add a bunch of
special-cased checks like game.musicmuted and game.completestop. But
instead of adding a bunch of special-case code, just make it so there's
a central place where Mix_VolumeMusic() actually gets called, and if
some piece of code wants to set the music volume, they can set
music.musicVolume. But the music handling logic in main.cpp gets the
final say on whether to listen to music.musicVolume, or to mute the game
entirely.

This is how the music handling code should have been from the start
(when pressing N to mute the music was added).

Fixes #505.
2020-10-11 16:16:57 -04:00
Misa
d0b3cfa08c Don't hardcode MIX_MAX_VOLUME value of 128
The value of the macro might not change in the future, but it's there
for a reason. That reason being to improve code readability, because
otherwise 128 would just be a magic number that plopped in out of
nowhere. Sometimes the game uses MIX_MAX_VOLUME, other times it uses
128, so to be consistent I'm just going to enforce MIX_MAX_VOLUME
entirely.
2020-10-11 16:16:57 -04:00
Misa
ba04c361c6 Revert "Fix #400"
This reverts commit cf5ad166e3.

My implementation will make it so single-case patches like this commit
won't be necessary anymore (there's no need to add a special-case check
for game.musicmuted, the way that I'm gonna do it). In fact, it's better
if I just revert the commit entirely.
2020-10-11 16:16:57 -04:00
Misa
cbceeccf78 Clean up and prevent unnecessary qualifiers to self
By "unnecessary qualifiers to self", I mean something like using the
'game.' qualifier for a variable on the Game class when you're inside a
function on the Game class itself. This patch is to enforce consistency
as most of the code doesn't have these unnecessary qualifiers.

To prevent further unnecessary qualifiers to self, I made it so the
extern in each header file can be omitted by using a define. That way,
if someone writes something referring to 'game.' on a Game function,
there will be a compile error.

However, if you really need to have a reference to the global name, and
you're within the same .cpp file as the implementation of that object,
you can just do the extern at the function-level. A good example of this
is editorinput()/editorrender()/editorlogic() in editor.cpp. In my
opinion, they should probably be split off into their own separate file
because editor.cpp is getting way too big, but this will do for now.
2020-09-28 01:34:40 -04:00
Misa
7b20d90446 Don't manually write out INBOUNDS_VEC() checks
This is because if they are manually written out, they are more likely
to contain mistakes.

In fact, after further review, there are several functions with
incorrect manually-written bounds checks:
 * entityclass::entitycollide()
 * entityclass::removeentity()
 * entityclass::removeblock()
 * entityclass::copylinecross()
 * entityclass::revertlinecross()

All of those functions forgot to do 'greater than or equal to' instead
of 'greater than' when comparing against the size of the vector. So they
were erroneous. But they are now fixed.
2020-09-25 13:51:47 -04:00
Misa
7ed495c373 Rename INBOUNDS() macro to INBOUNDS_VEC()
Since there's an INBOUNDS_ARR() macro, it's much better to specify the
macro for the vector is a macro for the vector, to avoid confusion.

All usages of this macro have been renamed accordingly.
2020-09-25 13:51:47 -04:00
Misa
c95b95f5b7 Check rw in musicclass::init()
It's possible that SDL_RWFromMem could return NULL, and if this is the
case, then we really shouldn't be passing it to MusicTrack().
2020-08-14 09:51:19 -04:00
Misa
6bed5fc88c Check divisor in musicclass::play()
Previously, it was assuming that the number of PPPPPP/MMMMMM tracks
would always be 16, since if that wasn't the case... then the game would
rudely and abruptly segfault when attempting to load the file. Huh.

But now that the game properly deals with invalid headers, it's possible
for the number of tracks to be 0. So I'll need to remove this
assumption.
2020-08-14 09:51:19 -04:00
Misa
4bfd9de371 Check index of tracks in musicclass::init()
It's possible that musicReadBlob.getIndex() could return the sentinel
value of -1 in case the header with that name is invalid, in which case
we should simply not do anything. Otherwise it'll lead to segfaults. I
opted to do the full bounds check just to be safe, too.

For further safety, I hardcoded the max number of headers, 128, less, so
128 is copy-pasted less and in the future if it needs to be changed
it'll only have to be changed in one place.
2020-08-14 09:51:19 -04:00
AllyTally
cf5ad166e3 Fix #400 2020-08-01 16:09:24 -04:00
Misa
52f7a587fe Separate includes into sections and alphabetize them
Okay, so basically here's the include layout that this game now
consistently uses:

[The "main" header file, if any (e.g. Graphics.h for Graphics.cpp)]
[blank line]
[All system includes, such as tinyxml2/physfs/utfcpp/SDL]
[blank line]
[All project includes, such as Game.h/Entity.h/etc.]

And if applicable, another blank line, and then some special-case
include screwy stuff (take a look at editor.cpp or FileSystemUtils.cpp,
for example, they have ifdefs and defines with their includes).
2020-07-19 21:37:40 -04:00
Misa
b5ff65c84e Remove unnecessary includes from header files
Including a header file inside another header file means a bunch of
files are going to be unnecessarily recompiled whenever that inner
header file is changed. So I minimized the amount of header files
included in a header file, and only included the ones that were
necessary (system includes don't count, I'm only talking about includes
from within this project). Then the includes are only in the .cpp files
themselves.

This also minimizes problems such as a NO_CUSTOM_LEVELS build failing
because some file depended on an include that got included in editor.h,
which is another benefit of removing unnecessary includes from header
files.
2020-07-19 21:37:40 -04:00
Ethan Lee
5ff5ae7294 mmmmmm is initialized earlier in init() 2020-07-15 11:58:00 -04:00
Misa
7703b2c1c2 Ensure that all member attributes are initialized
I ran the game through cppcheck and it spat out a bunch of member
attributes that weren't being initialized. So I initialized them.

In the previous version of this commit, I added constructors to
GraphicsResources, otherlevelclass, labclass, warpclass, and finalclass,
but flibit says this changes the code flow enough that it's risky to
merge before 2.4, so I got rid of those constructors, too.
2020-07-08 19:14:21 -04:00
Misa
5fe3b9d0de Add bounds check to musicclass::play()
If the song number (after we've processed it) is out-of-bounds, then
just return and log the error.
2020-06-30 21:07:05 -04:00
Misa
7c2b418761 Account for extra tracks in musicclass::play()
Since each soundtrack is no longer guaranteed to be 16, we'll have to
account for their different lengths when playing music.
2020-06-30 21:07:05 -04:00
Misa
08fe655a5f Parse extra headers from binary blob
Not just the ones that contain specific names.
2020-06-30 21:07:05 -04:00
Misa
09dbe8113b De-duplicate track names
Instead of copy-pasting the entire list three times over, why not put it
in an easy to use "X" macro?
2020-06-30 21:07:05 -04:00
Misa
22738cdb97 Remove unused/useless vars music.custompd/musicfade(in)/volume
I have no idea why these are here, but it'll simplify readability and
reduce the chance of confusion if I remove them.
2020-06-27 17:23:07 -04:00
Misa
facb079b35 Fix resumemusic/musicfadein not working
It seems like they were unfinished. This commit makes them properly
work.

When a track is stopped with stopmusic() or musicfadeout(),
resumemusic() will resume from where the track stopped. musicfadein()
does the same but does it with a gradual fade instead of suddenly
playing it at full volume.

I changed several interfaces around for this. First, setting currentsong
to -1 when music is stopped is handled in the hook callback that gets
called by SDL_mixer whenever the music stops. Otherwise, it'd be
problematic if currentsong was set to -1 when the song starts fading out
instead of when the song actually ends.

Also, music.play() has a few optional arguments now, to reduce the
copying-and-pasting of music code.

Lastly, we have to roll our own tracker of music length by using
SDL_GetPerformanceCounter(), because there's no way to get the music
position if a song fades out. (We could implicitly keep the music
position if we abruptly stopped the song using Mix_PauseMusic(), and
resume it using Mix_ResumeMusic(), but ignoring the fact that those two
functions are also used on the unfocus-pause (which, as it turns out, is
basically a non-issue because the unfocus-pause can use some other
functions), there's no equivalent for fading out, i.e. there's no
"fade out and pause when it fully fades out" function in SDL_mixer.) And
then we have to account for the unfocus-pause in our manual tracker.

Other than that, these commands are now fully functional.
2020-06-27 17:23:07 -04:00
Misa
14afae1a40 Add bounds checks to script commands that didn't have them
Continuing from #280, another potential source of out-of-bounds indexing
(and thus, Undefined Behavior badness) comes from script commands. A
majority of them don't do any input validation at all, which means the
potential for out-of-bounds indexing and segfaulting in custom levels.
So it's always good to add bounds checks to them.

Interesting note, the only existing command that has bounds checks is
the flag() command. That means you can't turn out-of-bounds flags on or
off. But there's no bounds checks for ifflag(), or customifflag(), which
means you CAN index out-of-bounds with those commands! That's a bit bad
to do, so.

Also, I decided to add the bounds checks for playef() at the
musicclass::playef() level, instead of just the level of the playef()
command. I don't know of any other cases outside of the command where
musicclass::playef() will index out of bounds, but musicclass is the one
containing the indexed vector anyway, I wanted to cover more cases, and
it's better to be safe than sorry.
2020-06-13 01:24:42 -04:00
leo60228
abbf6bafb9 Don't leak sounds/music 2020-06-07 22:40:03 -04:00