It is currently Fri Dec 14, 2018 10:51 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Sat Mar 10, 2018 3:30 pm 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 1107
Location: Pennsylvania, USA
In the past, I would always run my sound engine after nmi. In my current game I've introduced mmc3 splits. In some parts of the game, there are some splits near the top of the screen. In others, they are near the bottom. Having the sound engine always run after nmi caused some jitters (with the splits) in some cases. So, I moved it to running after the last split irq. However, in this case I ran into a subtle intermittent chr bankswitching bug where the next nmi would interrupt the currently running irq, due to the sound engine running slightly long on occasion.

My solution has been to configure the split system I have to run the sound engine after a specific split where I know there's more than enough time before the next irq.

I was kinda curious if anybody else has done this out there, either for homebrew or if anyone has seen it done in commercial games.


Top
 Profile  
 
PostPosted: Sat Mar 10, 2018 4:47 pm 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20874
Location: NE Indiana, USA (NTSC)
Here's what The Curse of Possum Hollow (MMC3) does:

All bank switching outside interrupt handlers is done by writing to two variables in RAM and then calling a subroutine that copies the values in RAM to MMC3 window registers 6 and 7. Though the NMI and IRQ handlers modify CHR-related window registers (0-5), they always finish by restoring these values to registers 6 and 7. So even if the subroutine that restores these values is interrupted, the result will still be correct. I took pains to ensure the correctness of this reentrancy.

Neither the NMI handler nor the IRQ handler interacts with audio at all. Audio runs on the main thread, where the loop for each game state periodically calls a subroutine that does this:

  1. If the master NMI counter (incremented by NMI) and music NMI counter are equal: Return.
  2. Switch $8000 to the audio engine's bank and $A000 to the bank containing the current song's music sequence data (of which there are three).
  3. If a music change was requested, start it.
  4. If a sound effect was requested, switch in the audio engine and start it. This queue is organized as a bitfield, with one bit per sound effect. For simplicity, only one sound effect can start in each frame, and lower-numbered sound effects get priority.
  5. Until the master NMI counter and music NMI counter are equal: Call the audio engine's update routine once and increment the music NMI counter.

Because of this catch-up mechanism, lag frames do not cause a loss of tempo, only a momentary stutter. And so long as this subroutine is called a couple times per game loop and at strategic points during blank screen updates, this stutter is unnoticeable in practice.


Top
 Profile  
 
PostPosted: Sat Mar 10, 2018 5:05 pm 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 1107
Location: Pennsylvania, USA
tepples wrote:
So even if the subroutine that restores these values is interrupted, the result will still be correct. I took pains to ensure the correctness of this reentrancy.

I do have code in place to ensure that if PRG bankswitching is done during nmi, nmi will return and the bank select register will be what it was supposed to be before nmi. I do all chr bankswitching during nmi, and never in the main thread so I do not protect it there.

I believe I was running into issues where the last mmc3 irq I configured was itself being interrupted by nmi before returning (due to the sound engine).

I am not sure I understand exactly what is happening when this scenario occurs; it seems it is probably better to ensure that it CAN'T occur, would you agree?

...I was considering doing music updates during the main thread, myself, but this approach of choosing a split after which to run the sound engine appears to be working well.


Top
 Profile  
 
PostPosted: Sat Mar 10, 2018 9:00 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7015
Location: Canada
GradualGames wrote:
My solution has been to configure the split system I have to run the sound engine after a specific split where I know there's more than enough time before the next irq.

That seems pretty sensible to me.


Top
 Profile  
 
PostPosted: Sun Mar 11, 2018 7:09 am 
Offline
User avatar

Joined: Wed Feb 13, 2008 9:10 am
Posts: 667
Location: Estonia, Rapla city (50 and 60Hz compatible :P)
I would make the sound engine just create list of IO writes allowing the engine to be called any time in the frame. Then in NMI you'll send that list to sound chip(s), it will surely take whole lot less cycles to do than running the entire sound engine there and you can even make the list writes take fixed amount of time allowing some additional possibilites.

_________________
http://www.tmeeco.eu


Top
 Profile  
 
PostPosted: Sun Mar 11, 2018 7:19 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 443
Use a sound engine that runs in a fixed number of cycles every frame 8-)


Top
 Profile  
 
PostPosted: Sun Mar 11, 2018 8:11 am 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 1107
Location: Pennsylvania, USA
pubby wrote:
Use a sound engine that runs in a fixed number of cycles every frame 8-)

:lol: I was actually thinking about your engine while solving this problem, but it's well in hand now.
TmEE wrote:
I would make the sound engine just create list of IO writes allowing the engine to be called any time in the frame. Then in NMI you'll send that list to sound chip(s), it will surely take whole lot less cycles to do than running the entire sound engine there and you can even make the list writes take fixed amount of time allowing some additional possibilites.

One of my goals is to keep the sound engine running at a consistent fps so even if the game slows down the sound/music does not.


Top
 Profile  
 
PostPosted: Sun Mar 11, 2018 8:24 am 
Offline
User avatar

Joined: Wed Feb 13, 2008 9:10 am
Posts: 667
Location: Estonia, Rapla city (50 and 60Hz compatible :P)
You can always have one extra MMC3 IRQ for the sound engine at some non critical area of the frame or perhaps call the engine right after the code of last split.

_________________
http://www.tmeeco.eu


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group