It is currently Mon May 20, 2019 8:44 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Tue Feb 12, 2019 11:53 am 
Offline

Joined: Wed Feb 17, 2010 5:42 pm
Posts: 394
Hi,
Im working on a MMC3 game, it requires an IRQ to split the screen.
The split and all works quite nice, but game crashes at seemingly random intervals, which can be influenced by having player do stuff.
I was able to trace the problem to IRQ getting triggered during a bank swap:
Code:
lda #somevalue
sta $8000
----IRQ happens here
lda #somevalue
----or here
sta $8001

The problem is IRQ code *needs* to swap banks for its own uses.
I was able to minimalize the frequency of crashes by:
Code:
lda #somevalue
ldx #somevalue
sta $8000
----IRQ can still happen here
stx $8001

But crashes can still hapen, albeit rarely.
Does anyone more familiar with MMC3 have a workaround for this kind of thing?
I guess I could disable irqs before swapping banks and enabling them after swap is done, but that would be slow. Any ideas?


Top
 Profile  
 
PostPosted: Tue Feb 12, 2019 12:03 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 514
Never used MMC3 before but you'd probably have to keep track of the current $8000 value.

Code:
lda #somevalue
sta register8000
sta $8000
lda #somevalue
sta $8001


Then in the IRC you'd put this at the end:

Code:
lda register8000
sta $8000


Quote:
I guess I could disable irqs before swapping banks and enabling them after swap is done, but that would be slow. Any ideas?

Maybe I misunderstand, but isn't this just a single SEI and CLI?


Top
 Profile  
 
PostPosted: Tue Feb 12, 2019 12:06 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8360
Location: Seattle
Always keep a "shadow" copy of the last value written to $8000 and the two PRG banks:

Code:
lda #whatever
sta shadow8000
sta $8000

Code:
lda #6
sta shadow8000
sta $8000
lda #whatever
sta shadowR6
sta $8001


Always restore registers from these shadows at the end of IRQ:
Code:
lda #6
sta $8000
lda shadowR6
sta $8001
lda #7
sta $8000
lda shadowR7
sta $8001
lda shadow8000
sta $8000
rti


If there's any possibility of IRQ and NMI colliding and both needing independent bank access, it gets a lot harder.


Top
 Profile  
 
PostPosted: Tue Feb 12, 2019 2:07 pm 
Offline

Joined: Wed Feb 17, 2010 5:42 pm
Posts: 394
Quote:
I guess I could disable irqs before swapping banks and enabling them after swap is done, but that would be slow. Any ideas?

Maybe I misunderstand, but isn't this just a single SEI and CLI?[/quote]
I think SEI and CLI pair would work, but it still would be slower. What I mean, is that IRQ *needs* to start as soon as it can.
I use IRQ to do a screen split, with some palette updates in Hblank.
If I disable IRQ before bank swap and reenable after, it will start instatnly, possibly increasing jitter.
If, IRQ was to happen before turning it off in one frame, but be "queued" right after it got disabled.

Shadow registers are great idea, thanks to you both :)


Top
 Profile  
 
PostPosted: Tue Feb 12, 2019 2:28 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8360
Location: Seattle
One thing I meant to say, but left implicit: make sure you update the copy of the shadow before you update the register. If you do it in the other order a perfectly timed IRQ could mess everything up:

Code:
 lda #value
 sta $8000
 --> IRQ
    pha
    lda #thing
    sta $8000
[...]
    lda shadow8000
    sta $8000
    pla
    rti
 sta shadow8000
will result in the desired value in the shadow, but the wrong value actually in the mapper


Top
 Profile  
 
PostPosted: Tue Feb 12, 2019 5:30 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2293
Location: Fukuoka, Japan
The more your game becomes complicated, the more caching is important. When you need to have the sound driver and the music data switched on every frame, this mechanism will be required so the sooner the better.

I remember when I started to implement the cache for the soundriver bank switching and it was crashing all the time until I got it right ^^;;;


Top
 Profile  
 
PostPosted: Wed Feb 13, 2019 1:37 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 935
I have a reentrancy check in my normal bank swap routine.

Code:
tryagain:
swapsafe = 1;
BANKSEL = 6;
BANKFILE = num;
if (!swapsafe) goto tryagain;

With the irq routine setting it to zero.


Top
 Profile  
 
PostPosted: Fri Feb 15, 2019 3:00 pm 
Offline

Joined: Wed Feb 17, 2010 5:42 pm
Posts: 394
The shadow method seems to work, thanks.

Banshaku wrote:
The more your game becomes complicated, the more caching is important. When you need to have the sound driver and the music data switched on every frame, this mechanism will be required so the sooner the better.

I remember when I started to implement the cache for the soundriver bank switching and it was crashing all the time until I got it right ^^;;;

I had a similiar situation where nmi happened when music driver was changing track...and I have music play in nmi, so that taught me a bit :)

calima wrote:
I have a reentrancy check in my normal bank swap routine.

Code:
tryagain:
swapsafe = 1;
BANKSEL = 6;
BANKFILE = num;
if (!swapsafe) goto tryagain;

With the irq routine setting it to zero.

To be fair, I dont really understand what does that mean.


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 10:06 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 91
Location: Gothenburg, Sweden
calima wrote:
I have a reentrancy check in my normal bank swap routine.

Code:
tryagain:
swapsafe = 1;
BANKSEL = 6;
BANKFILE = num;
if (!swapsafe) goto tryagain;

With the irq routine setting it to zero.

But that would only cover cases where the IRQ happens during a bank swap? If the IRQ happens after the if-statement it will switch banks and have the code following it on return read from the wrong bank. Therefore you would have to have the IRQ restore the bank to it's previous state, which would make the if-statement you wrote redundant. I think so at least but I am very new to bank swapping.. :P


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 11:54 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 935
The IRQ naturally restores the previous bank upon returning. The if is not redundant, since the IRQ can happen anywhere in there. Very careful ordering of the shadow bank var writes may or may not have the same result.


Top
 Profile  
 
PostPosted: Tue Feb 19, 2019 11:26 am 
Offline

Joined: Tue Oct 16, 2018 5:46 am
Posts: 91
Location: Gothenburg, Sweden
calima wrote:
The IRQ naturally restores the previous bank upon returning. The if is not redundant, since the IRQ can happen anywhere in there. Very careful ordering of the shadow bank var writes may or may not have the same result.


Cool, I did not know that! Is the same done with NMI?


Top
 Profile  
 
PostPosted: Wed Feb 20, 2019 1:31 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 935
Yes, if the NMI switches banks.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


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:  
cron
Powered by phpBB® Forum Software © phpBB Group