I'm trying to learn about setting up irq's yet again with my MMC5 Zelda hack.
I read this site,
http://bobrost.com/nes/files/mmc3irqs.txt on learning about setting 40 to 4017 & setting CLI.
So what I did was I loaded/stored 40 into $4017 at the beginning of my reset vector, i set the CLI at the end of my reset vector, just before the infinite jmp loop.
Then at the beginning of my NMI, I loaded/stored 80 into $5204
Now with all of that done, I rebooted my rom, and watched $FFFE-$FFFF, and it was firing up, I had it point to just an RTI, to see if this was actualy getting logged.
So now that I actually have the IRQ register being recognized, I started inserting asm for the irq scanline, to perform a split screen.
Now this is where I cant for the life of me figure this out.
In a lot of the Megaman games, you can have the split start allllllmost at the top of the screen without a lot of fluctuation/hiccups. Like I can have the scanline for those games at about 38, meaning the split is 3 quarters up the screen with no hiccups.
Now, with my Zelda game, the sprite 0 does not kick on unless there is an active scroll taking place, keeping the info bar stationary at the top of the screen. But during regular game play, the entire screen can be moved horizontaly/verticaly. Anyways..
Why is it that I cant have my irq split that far up the screen? Here are some issues
1. If only Link is on the screen, and no other sprites, I can have a pretty decent still irq split, but it has to be waaayyy past the center of the screen downwards.
2. If there are multiple sprites on the screen, the irq split goes absolute haywire! (however, this does not happen in the megaman games, and that's with the irq so far up the screen!)
So what I would like to know, is am I missing a specific routine to write to the nes, to stop the sprites from causing the irq going haywire? Is there a way for me to have total freedom in where I want the split to occur???
I appreciate any help on this, this time around has been the closest I've gotten to installing a custom irq engine, in a game that never had one.
Thank You!
Code:
lda #$20
ldy #$00
sty $2006
sta $2006
lda $FF
ORA #$01
sta $2000
lda #$00
sta $2005
sta $2005
lda #$B0
sta $5203
rti
Below is a video of it in action
http://www.youtube.com/watch?v=ZeIk-yo_XYk
Ok since no one has an answer to that, how about this.
How can you alter the frames per second of a rom? Im thinking my issue is, is that too much is going on for the irq to appear/remain stationary correctly.
If you construct your IRQ and other rendering code carefully it should be able to render reliably whether or not your gameplay code has occasional lag frames.
I can't tell you what's wrong based on your description or video alone. Posting a ROM might help, posting your entire IRQ routine might help, etc. Here's some ideas:
1. I presume you're not using sprite 0 hit for anything, right?
2. Check to make sure your IRQ is initialized and enabled with consistent timing (i.e. do it in your NMI before any branching).
3. Check to make sure subsequent splits are also initialized with consistent timing in the IRQ routine.
4. Check the "thread safety" of variables used by the IRQ routine. Are you depending on variables that code outside the IRQ routine can alter? Can the timing of when those variables updated cause a problem for the IRQ routine trying to use them?
Everything that im about to write here, is everything i have that has an irq firing up. Again i'm new to inserting a custom irq engine in a game that does not originaly have one, *like the Megaman 3-6 games* I'm really just going by the seat of my pants with all of this, tried looking online, studying, and this is the first time that i'm actualy getting results, good results, but if i can figure out/learn, how to make this tighter/better, be able to have the split anywhere i want verticaly, then i'll be in fantastic shape!
And to answer to one of your questions, since the others I'm not sure on cause I'm new to irq's from scratch, there is no sprite 0's going on during my irq usage, the only time a sprite 0 kicks on, is during a scroll.
Code:
End of Reset Vector
------------------------
CLI
JMP $E563 ;infinite jmp loop
Start of NMI
---------------
PHA
TXA
PHA
TYA
PHA
JMP $FFF0
$FFF0
-------
LDA #$80
STA $5204 ;Acknowledge mmc5 to enable irq
JMP $FF7F ;JMP to continuing the start of NMI
End of NMI
--------------
PLA
TAY
PLA
TAX
PLA
RTI
Start of IRQ
--------------
LDA $5204
LDA #$20
LDY #$00
STY $2006
STA $2006
LDA $FF
ORA #$01
STA $2000
LDA #$00 ;X position of split
STA $2005
STA $2005
LDA #$B0 ;Y position of split
STA $5203
RTI
I'm not 100% sure, but IIRC, NMIs set the I flag when they fire. This means that as long as the NMI handler is running, IRQs will not fire. Since you have the game logic running inside the NMI, more processing increases the time IRQs are ignored, causing the glitches you're seeing. You could try adding a CLI to the beginning of the NMI handler as a quick fix.
Or at least add the CLI after rendering is turned back on, so that an IRQ is delayed only until the end of vblank processing.
tepples wrote:
Or at least add the CLI after rendering is turned back on, so that an IRQ is delayed only until the end of vblank processing.
Or that, but since well programmed IRQs won't fire during VBlank, I guess it wouldn't hurt to run the CLI before rendering starts.
In Zelda, $2001 has 1E constantly being stored to it during game play, which I believe is rendering turned on.
When I put a CLI after $2001, im able to have the irq split anywhere! BUT, the game horrificly glitches/crashes in seconds.
$2001 is not relevant to an IRQ problem. It merely controls whether graphics make it to the screen. The relevant thing is the NMI, which is controlled by $2000.
When an IRQ or NMI is running
there is an implicit SEI but also remember that the status register is also restored when you RTI. This means that NMI will suspend the triggering of an IRQ until you RTI from it, normally.
You don't want the vblank portion of your NMI to be interrupted by an IRQ because the timing is critical here. Also, it's offscreen, so you're not going to want an IRQ during vblank anyway. That's fine. What tokumaru was suggesting is that if your NMI is still running some ways into the screen, it will block your IRQ, normally. Here's one way you can structure your NMI routine:
1. NMI begins at start of vblank (implicit SEI)
2. Start your IRQ timer (consistent starting point for timer)
3. upload sprites, nametable, palette, and any other PPU data
4. CLI to allow your IRQ to fire any time after this point (we should still be offscreen in vblank at this point)
5. rest of NMI, non-rendering related stuff (music, gameplay, whatever you want here)
6. RTI to end NMI (implicit CLI, if I was clear before NMI entered)
If you put your gameplay inside your NMI routine, you should create a flag that exits the NMI routine immediately if there is already an NMI in progress, i.e. prevent re-entrant NMI. This is to prevent the next frame's NMI from interrupting the current one (and probably causing chaos) if you have a lag frame that takes too long to process.
You should really move your main game logic outside of NMI. What I do is, at the very end of my NMI routine, I set a flag in memory, so I'll do something like write $01 to $000F. Then, I have a "wait for vblank" subroutine that reads $000F over and over again in a loop until it finally reads as $01. Then the routine sets it back to $00 and returns.
So basically, you have your main game code run, and at the very end, you JSR to the wait-for-vblank subroutine, so the CPU will get stuck in there until the NMI happens, which is where you set $000F to $01. Once NMI exits, the CPU returns to that wait-for-vblank subroutine, but $000F is now $01, so the routine sets it back to $00 and returns. After that, you JMP back to the beginning of your main game logic loop.
The advantage of doing it this way is, if your main loop has a LOT of processing to do, to where it takes more than one frame to do it, the NMI and other IRQs will still happen like usual, and once their respective routines finish, control returns to the main game loop where it left off. If your game logic is running inside an interrupt, you can't interrupt an interrupt, so IRQs won't work the way you want them to.
It's hard to explain this because it explains a different mentality to design code with.
Im confused on what you all mean by (outside the nmi)
I dont understand how I do that? I thought the main game is through $FFFA-$FFFB, and the reset vector is through $FFFC-$FFFD, while the irq/brk is at $FFFE-$FFFF?
So im confused as to how this is supposed to work.
And what is an implicit sei? Is that just a fancy term for using a regular SEI (78) ?
infidelity wrote:
Im confused on what you all mean by (outside the nmi)
Some old games and some NES programming tutorials place the game logic inside the NMI handler. This is fine in some cases, but it's not ideal. There are complications that may happen when the game logic takes too long to complete. In short, another NMI will fire before the previous one finishes, interrupting it. If you're not prepared to handle this, all sorts of bad things can happen, like glitched graphics and even crashes.
A better, more versatile way to organize your code is to put the game logic outside of the NMI, in the main loop (instead of just having a JMP there), and use the NMI only for PPU/APU updates. NMI can still fire before the previous frame is finished, but it's a little easier to manage since the video and audio are separated from the game logic.
Quote:
I dont understand how I do that? I thought the main game is through $FFFA-$FFFB, and the reset vector is through $FFFC-$FFFD, while the irq/brk is at $FFFE-$FFFF?
That's an oversimplification of how things really are. In reality, the CPU has these 3 addresses it jumps to at certain times, but the way you divide the tasks you need to perform across these addresses is up to you. There are many possibilities, each with their pros and cons.
Quote:
And what is an implicit sei? Is that just a fancy term for using a regular SEI (78) ?
No, if it was regular he wouldn't have said "implicit"! =)
What he meant is that when the NMI fires, the I flag gets set. So even if you CLI in your reset code, a "hidden" (i.e. implicit) SEI happens and sets the I flag when the NMI fires. This means you have to clear it again if you expect IRQs to happen before the NMI handler is finished (RTI).
If you are running your game logic in your NMI, it is very important to prevent re-entry. This is one way to do it:
Code:
.segment "ZEROPAGE"
nmi_running: .res 1
.segment "CODE"
nmi:
... push registers
lda nmi_running ; use flag to prevent beginning second NMI if first one is not finished
beq :+
... pop registers
rti
:
lda #1
sta nmi_running
... rest of NMI code
lda #0
sta nmi_running
... pop registers
rti
If you do not prevent re-entry, your game will almost certainly crash, or at least behave very strangely whenever your game logic takes longer than a frame to complete.
Now, a lot of people are suggesting not to do your game logic in the NMI. This is because when your game logic runs too slow it will break your required rendering IRQs as well as causing the music to slow down too. This is not good! Here is one way to structure your code to do the gameplay logic outside the NMI:
Code:
.segment "ZEROPAGE"
nmi_counter: .res 1
nmi_running: .res 1
.segment "CODE"
nmi:
... push registers
... prevent re-entry
... set your first IRQ timer
... upload OAM
... upload palette and nametable changes
... set scroll
cli ; allow IRQ scroll splits while NMI is still running
... run music routine
inc nmi_counter ; increment frame to tell the game it can now execute gameplay for a new frame
... clear re-entry variable (nmi_running)
... pop registers
rti
reset:
... standard reset stuff
... setup game
cli
... turn on NMI (set high bit of $2000)
@game_loop:
lda nmi_counter
:
cmp nmi_counter
beq :- ; wait until nmi_counter is changed by NMI routine
... run game logic here
jmp @game_loop
irq:
... irq routine
rti
There's more details to this, of course, but this should get you started. If you structure your code like this, the gameplay logic will no longer interfere with music or your IRQ splits, since these will now happen every frame reliably. If your gameplay logic runs too long, only gameplay will slow down and nothing else will be affected.
I appreciate all the help and time you are all putting into this, but these code pastes are way over my head. Ive tried pasting them into online assemblers, to see if I can view the binary versions of them, but they will not compile.
Its one thing if I coded this game from scratch, but its not, all I've been doing is modifying a game from 1986, which back then wasn't properly written since the nes was fairly new at the time.
If I had some sort of template to work with, I think that would be helpful.
There some other issues im having trouble with.
1. What is an irq timer? I don't see anything about a timer in the 005 notes for the mmc5 irq engine, just stuff on how to enable/disable. Am I supposed to simply read a 'frame counter' register as a timer for the irq?
2. I apologize but I'm still lost on the whole 'outside the nmi' Does the game logic still take place within "$FFFC-$FFFD? Or does the game logic need to somehow be within the reset vector loop?
Again I'm sorry for all of this, I thought this would be a simple solution, but again I'm in uncharted waters here, I'm willing to learn but this stuff is pretty advanced even for me. Everything you all have been saying on this issue, has got me thinking this could even fix my sprite limitation issues I've had to limit myself with, cause horrific slowdown with my sound engine would kick in.
editThis is what I have new for my NMI so far, is this correct? The game continues to run the same however.
Code:
Start of NMI
---------------
PHA
TXA
PHA
TYA
PHA
LDA $F2
BEQ ;to LDA #$01
PLA
TAY
PLA
TAX
PLA
RTI
BEQ'd Branch
---------------
LDA #$01
STA $F2
4C#### ;start entire NMI routine
End of NMI
------------
PLA
TAY
PLA
TAX
PLA
LDA #$00
STA $F2
RTI
Does the usage of commands and everything appear correct? Do I have this atleast correct? Thank you.
Sorry, I made a mistake with the re-entry flag. That last LDA needs to happen before the last PLA before the RTI. The PLA is there to restore the state of A before returning, so:
Code:
End of NMI
------------
LDA #$00
STA $F2
PLA
TAY
PLA
TAX
PLA
RTI
The second thing you need to do is place that CLI at the end of your vblank PPU update.
The IRQ from the MMC3 is connected to a timer that works by counting scanlines. This is what I meant by "IRQ timer", sorry if the terminology was unexpected.
ok I fixed the code you sent, and the game continues to run the same.
Also, am I correct with vblank in saying, is that what deals with the ppu rendering being on/off? Cause in the rom, there is this routine...
Code:
LDY $17
BNE ;to STA $2001
ORA #$1E
STA $2001
STA $FE
it is after that code that I insert a CLI, and when I reboot the rom, the game crashes. If I fireup a savestate, the irq appears way up where I'd like it, but there are horrific glitches/crashes.
No, writing $2001 has really nothing directly to do with vblank. All it does is turn the rendering display on and off.
The vblank PPU update most likely ends with a pair of two writes to $2005 to set the scroll. Maybe look for that, and put the CLI after it.
OK I found some.
Code:
$FE4C4
---------
LDA #$00
STA $2005
STA $2005
$FD104 (irq)
--------------
LDA #$00
STA $2005
STA $2005
$FE516
---------
LDA $2002
LDA $FD
STA $2005
LDA $FC
STA $2005
it was at $FE4C4 (which is right in the vicinity of my original placement of the CLI) where I placed the new location for the CLI, right after the two STA $2005's. The game still wont boot, but I noticed that it gets stuck in a constant loop within the irq? That is the only thing running while the screen is gray.
I do a breakpoint by the CLI I set, the CLI gets noticed, the I flag is removed, then it will load the following opcode after itself, then at this point the IRQ pointer is loaded so I'm now within the IRQ, the I flag is set, and when I step into each command and reach the RTI, it goes back to the beginning of the irq routine, it just loops over and over.
Hmm, maybe the IRQ line is being asserted from the previous frame's IRQ or something? Let's try a different approach.
Find the code that sets up the first IRQ to be fired this frame. Put the CLI right after it is finished setting up, i.e. wait for the IRQ device to be acknowledged and enabled before using CLI.
The only CLI I have going on, is at the end of the reset vector. The irq $FFFE-$FFFF would fire up once the reset vector loop completed.
So I removed the CLI from my reset vector, placed the CLI after the 2 STA's to $2005, and I still get the same result.
edit
What I also noticed, for Megaman 4 for example, I step into the first CLI I encounter, and the game does not jump right to the irq routine like my rom is doing when I use a CLI.
The RTI does not necessarily clear the interrupt flag, it merely restores the flag to its state before the NMI started. If you don't CLI in your reset vector code, interrupts will still be inhibited when the NMI completes. You don't want this. Put that CLI back.
If when you reach a CLI we immediately jump to your IRQ vector, this means that you had an unacknowledged IRQ pending. This is why I told you to acknowledge and enable the IRQ device right before you CLI in your NMI so there won't be a pending IRQ. (You should disable the IRQ device before the CLI in your reset code, though.)
What I might recommend at this point, though, is to create your own test ROM with entirely your own code to learn how the IRQ works. It's much easier to try things out and experiment in a from-scratch project than it is in a romhack. Once you know your way around a working NES program, even a small test program, this experience will help you a lot in finding your way around a romhack.
I'm suggesting this because right now you seem to be asking a lot of questions that you could answer on your own if you weren't trying to do a romhack at the same time. I'm at arms length from whatever you're doing, so me telling you what to do bit by bit is a very slow and laborious way to try to get through this.
This so confusing.
So I put back the CLI in my reset vector.
Now within my NMI, when I'm about to use a CLI, your saying I need to acknowledge and enable the irq device
before I use the CLI?
To acknowledge it within mmc5, do I just simply use an LDA of $5204? do I write to $5204?
You say to disable the IRQ in my reset vector? is that again using $5204 to disable?
and your suggestion, wont that put me in a false state of hope, considering how my romhack is layed out, and if I get promising results from my test rom, that the actual attempt on my romhack will prove otherwise?
editYeah this isn't working at all. I did everything you wrote and it gives the same result with a looping irq going on and nothing else.
Code:
END OF RESET VECTOR
--------------------------
LDA #$00
STA $5204 ;irq disabled
CLI
JMP $D176 ;loop on jmp
NMI
----
LDA $5204 ;Reading $5204 will clear the pending flag (acknowledging the IRQ).
LDA #$80
STA $5204 ;IRQ Enable
CLI
With all that, I get the same looping result
If when you RTI from the IRQ vector routine you immediately re-enter it, what do you think this means?
What scanline have you told the IRQ device to trigger on?
I do not know how to determine the scanline. All I know is I have the split to appear just below the info bar in the game. Loading 3F and storing it into $5203 sets the vertical position below the info bar. I don't know how to pin-point snap the debugger to see if the scanline column actualy registers a value, and if it did, I don't know what value I'm supposed to look for.
As to your question on why I cant get out of the irq's interrupt? I don't have a clue, which is so confusing because the last post you wrote, I did what you said and I'm still getting the same result.
This is everything I have that's new code
Code:
Start of NMI
---------------
PHA
TXA
PHA
TYA
PHA
LDA $F0
BEQ ;to LDA #$01
PLA
TAY
PLA
TAX
PLA
RTI
BEQ'd Branch
---------------
LDA #$01
STA $F0
4C#### ;start entire NMI routine
End of NMI
------------
LDA #$00
STA $F0
PLA
TAY
PLA
TAX
PLA
RTI
End of Reset Vector
----------------------
LDA #$00 ;disable irq
STA $5204
CLI
JMP $D176 ;jmp on itself
Insert CLI After 2 Writes To $2005
---------------------------------------
LDA $5204 ;Reading $5204 will clear the pending flag (acknowledging the IRQ).
LDA #$80 ;IRQ Enable
STA $5204
CLI
That's everything I have from today.
If you can't get out of your IRQ vector routine, consider that the problem may be with your IRQ vector routine.
I figured it was ok...
Code:
LDA $5204
LDA #$20
LDY #$00
STY $2006
STA $2006
LDA $FF
ORA #$01
STA $2000
LDA #$00
STA $2005
STA $2005
LDA #$3F
STA $5203
RTI
I just tried adding the push registers before my irq engine, and then pull my registers at the end of my irq engine, and still got the same result.
EDITWOAH! idk how but this almost works! The game wont boot though, but when I load a savestate, the friggin irq is working!
I completely started over with what I had 2 days ago, just being able to go mid way with the scanline before it went all crazy.
All I did just now, was edit my irq routine, and add that CLI after the 2 stores to $2005, and it's working! I just can't figure out why the rom refuses to boot with this, but with my savestates during gameplay, it's fine.
Ill post what I did in a minute.
Code:
Add CLI After 2 Writes To $2005 In NMI
---------------------------------------------
CLI
New IRQ Routine
-------------------
PHP
PHA
TXA
PHA
TYA
PHA
LDA $5204
LDA #$20
LDY #$00
STY $2006
STA $2006
LDA $FF
ORA #$01
STA $2000
LDA #$00
STA $2005
STA $2005
LDA #$3F
STA $5203
PLA
TAY
PLA
TAX
PLA
PLP
RTI
So with those changes, I can freely move the irq anywhere when loading a savestate! BUT, the game wont boot....? It again gets stuck within the irq routine at bootup. If I insert the CLI after the two writes to $2005's once the game has booted, it's fine. Same thing goes for in-game play, if I insert it then, its fine.
Okay, don't insert CLIs in random places, any previous advice about this was given on less complete information. I will tell you the specific things to do here. Get rid of any existing code that attempts to do things with the IRQ and do the following:
Code:
; 1.
; this goes in the reset-vector code, just before the infinite loop jumping to itself
;
lda #0
sta $5204 ; disable scanline IRQ
cli ; allow IRQs to fire outside of NMI routine (in case your NMI exits early)
; infinite loop here
; 2.
; this goes in the NMI vector routine, put it near the beginning after the registers are pushed
;
lda #$3F
sta $5203 ; set scanline of IRQ to $3F
lda $5204 ; acknowledge and clear any pending IRQ
lda #$80
sta $5204 ; enable scanline IRQ
cli ; allow pending IRQs to trigger IRQ vector routine while NMI is still running
; 3.
; this is your new IRQ vector routine, replace the entire irq vector routine with this.
;
pha
txa
pha
pya
pha
lda $2002 ; reset latch
ldy #$04
lda #0
sty $2006 ; sets nametable select to $2400
sta $2005 ; set scroll position within nametable to 0,0
sta $2005
sta $2006
lda $5204 ; acknowledge pending IRQ
lda #0
sta $5204 ; disable IRQ so that it cannot fire again this frame
pla
tay
pla
tax
pla
rti ; return from interrupt
1. This code enables IRQs (CLI) outside the NMI, this is important in case your NMI routine reaches RTI before your IRQ needs to fire. Note that it also disables the MMC5 IRQ device so there is no chance of a pending IRQ that will immediately fire when you CLI.
2. This initializes the MMC5 IRQ and sets it to fire at scanline $3F. The CLI enables interrupts for the remainder of the NMI routine.
3. This does a scroll split at the time the IRQ is fired. After doing this, the pending IRQ is acknowledged, and the MMC5 IRQ is disabled so that it cannot fire again this frame. Unless you want multiple scroll splits there is zero reason to leave the MMC5 IRQ enabled at this point.
I don't really like writing code for you to solve your problem. I would much rather help you learn how to do it, but I am hoping that this example at least helps you understand. (Again, you will learn a lot more easily if you stop trying to do advanced techniques in a romhack first, and instead write for yourself simple test ROMs.)
Did you see my previous post?
No, sorry, it took me many minutes to write that so I didn't catch your edit, but after reading it my advice is the same.
The routine that I discovered works a better when projectiles are thrown, I experience no flickering/shaking with the irq. However with your routine, I get that slightly with projectiles. I went to the same screen id with the same enemies, and tested both routines, and those are the results I got.
I don't want you thinking you spoon fed with me with the answer you pasted. When you told me there must be something up with the irq routine, I looked at hard, and realized I never had that interrupt setup properly by pushing/pulling. Also, I added PHP & PLP to the irq routine, and that seems to really do the trick. I learned a lot from you and everyone else in this thread, dealing with this irq issue I've been having. I believe I now understand how to get this fully working from the ground up. I'm still experiencing the game not booting with that CLI within the two STA $2005's. But this could be just the way the game was originaly written, and since what I need is not needed throughout the entire game, I just need it for maybe 2 screens, I should be in the clear.
Before the first CLI after reset, make sure you disable all three potential IRQ sources:
write $00 to $5204 to disable MMC5 IRQ
write $00 to $4010 to disable DPCM IRQ
write $C0 to $4017 to disable frame IRQ
infidelity wrote:
I added PHP & PLP to the irq routine, and that seems to really do the trick.
That shouldn't be necessary. The CPU automatically saves its flags when IRQs and NMIs fire and restores them when you RTI. Putting PHP and PLP inside these handlers is redundant and shouldn't cause any changes at all. If something changes when you do that, there's probably something wrong elsewhere.
@ tokomaru, you are right. I removed the PHP & PLP's and I still have proper irq usage going on.
@ rainwarrior, i'll add your suggestions and see what happens.
Code:
LDA $5204
LDA #$20
LDY #$00
STY $2006
STA $2006
LDA $FF
ORA #$01
STA $2000
LDA #$00
STA $2005
STA $2005
LDA #$3F
STA $5203
Where did you acquire this scroll split code? It works, but it looks very unusual to me.
1. The first two writes to $2006 set the latch to the PPU $2000 nametable, but you're currently trying to start rendering from the $2400 nametable. The useful thing you are getting here is setting the latch also sets the Y scroll position, so these two writes set the Y scroll position to 0. You should be writing $24,00 instead of $20,00.
2. The ORA #$10 and the STA $2000 would be unnecessary if you would latch to $2400 instead of $2000 when you make your two $2006 writes.
3. The two writes to $2005 set the X scroll to 0, and the fine Y scroll to 0 (but does not update coarse Y).
The routine I suggested accomplishes the same thing but more directly. There's more information about how scroll splits work here:
http://wiki.nesdev.com/w/index.php/The_skinny_on_NES_scrollingAt any rate, if you have IRQ stability problems with the implementation I suggested, it may be a different problem outside the IRQ that just happens to manifest as an interference with it. If you're just talking about a single line of misplaced X scrolling, that is probably just a horizontal timing issue which you can fix that by putting a delay in your IRQ response before the scroll writes.
The code was taken from an old megaman project of mine. Looks ugly, yes, but it xan be written better like you suggested.
I do have one more question, non irq related.
I have signifigant slowdown when i have more than 3 active sprites. By active, i mean it has asm that controls its AI, x/y, etc.
The Capcom 6C80 is vastly superior in asm, compared to the original sound engine. And in inserting this new sound engine, it has contributed to my slowdown issues.
My question is, is it possible for my sound engine to be read from within the reset vector loop, and if so, will that solve my slowdown issues?
Determining where the game logic begins might be tricky, since this is a romhack, and i remember you showing a method of having the game logic within the reset vector.
Thank you to everyone for theyre assistance and info!
The suggestion was that if you put your game update outside your NMI (i.e. in the loop reached by the reset vector) the music will not be forced to slow down if the game update takes too long. The game will still slow down in this case, just the music will run unaffected.
Putting the music engine outside the NMI wouldn't help anything. Game performance will be unaffected and the music will still slow down when the game update runs too long.
Ok thank you. Ill try to figure out the origin of the game logic, and try to relocate within the reset vector.