I believe he said he based that around the discussion on my forum around this. Which was before you and I talked via e-mail.ikari_01 wrote:Regarding resume someone has come up with something: https://github.com/mlarouche/sd2snes/co ... b0cb74d1d2
Certainly this would be much more in the spirit of MSU1's simplicity.
But the resume bit sounds like the older functionality that had some flaws around seek delays. If $2007.d2=1 forced a seek to a new resume location, then it would have to set the audio busy flags and wait for the media to seek+buffer samples at the new location. It forces two seeks, one for track select, one for resume.
So here's my current thinking on this. Note that it's not finalized yet, I'm open to discussion still.
Start with two 32-bit values, flushed at reset or power cycle (if possible, otherwise just on power):
uint32_t track = 0; //no track (note: since offset=0 below, this is equivalent to there being no track/seek)
uint32_t offset = 0; //no offset (note: value is in SAMPLES (32-bit), not bytes (8-bit))
Step 1: stop existing track
$2007.d2 is now the "save" bit. On writes to $2007:
A: if $2000.d6=1 (audio busy), stop right here, do nothing.
B: else, if $2007.d0=1, then unpause the track if need be, but do nothing with the track/offset variables and ignore the "save" bit entirely. The track is playing, so trying to cache the offset is pointless. You'd end up resuming too soon.
C: else ($2007.d0=0), if $2007.d2=1, then save current track# and current offset into track/offset variables. You can do this over and over if you like.
D: else ($2007.d2=0 && $2007.d0=0), this has no effect on the track/offset variables.
Step 2: play new track
Now go ahead and play your new track.
Upon writing to audio track high ($2005), it will compare the currently selected track# against the saved track#. If there's a match, then the offset will be taken from our saved variable. This allows the audio seek delay to happen all at once (for both track + track position). Otherwise (if the current track# != the saved variable track#), it will seek to the beginning of the track.
Step 3: stop the new track
When we stop our new track, we don't want to erase the old track/offset, so make sure $2007.d2=0 here.
Step 4: resume the old track
We select the old track, and on the $2005 write, the track#s match up, so we seek to the saved resume offset. Furthermore, we flush the track+resume variables back to 0, since there's no use for them anymore. We've already resumed. This is also needed for our edge case no-resume described below to work.
Upon playing the track with $2007.d0=1 (unpause), it will have resumed playback where it last left off.
Edge case: do -not- resume old track
You saved the position of a song, but now you want to discard it and start from the beginning instead.
IDEALLY, I'd love to make $2005.d7 = resume bit. But this would break backward-compatibility. Older MSU1 implementations would try and load audio track 32768+.
So we have be more pragmatic here. Instead, select your old track, and it'll automatically resume on $2005 write.
Now immediately write $2004-5 to select the same track# a second time.
Since the resume information was flushed away, it will definitely play from the beginning this time.
Unfortunately, doing this will require two seek operations.
The good news is, this edge case should be very rare. Let's take Chrono Trigger as the example game:
* if you are playing overworld theme -and- you're changing to battle music, you know you need to save the offset
* if you are playing overworld theme -and- you're changing to town music, you know you shouldn't save the offset
* if you are playing battle or town music and change to anything else, you know you never need to save those at all
There shouldn't be any cases where this edge case behavior is needed in most games.
Notes
The main takeaway here is that we're only capable of suspending and resuming one single track.
The thing is, you can have up to 65536 tracks on the MSU1. And if we saved a 32-bit sample# for each and every track (we could kill off the track# in that case), that would be 256KiB of memory required in the pathological worst case. That's too much memory for the sd2snes.
In the future, if there's some compelling reason to have 2+ track resume, we can consider changing the track/offset variables to:
uint32_t track[N];
uint32_t offset[N];
And use them to store in free slots where available. But I don't foresee us ever needing to do that. It would be jarring and weird to resume multiple tracks like that.
The advantages over DarkShock's example (my older tecnique):
* this will allow you to cache a new resume without having to flush an old one first (important as you may not know one was already cached)
* this will avoid the need for a seek operation on $2007 write (which was not part of MSU1 originally)
This new proposed behavior would be fully backward-compatible with the old MSU1.
The only effect would be that your resumed music would start over instead of resuming.
There's never really a case where this is going to *ruin* the game, it'll just be a bit less enjoyable.
Anyway, again, open to suggestions.