Or rather: I am an absolute cretin who has no clue on how to work this bloody thing.
Also I apologize should a topic like that already exist, if so, I didn't find it. Anyway, since I wasn't planning to utilize IRQs in my little project in any way.
I tried writing to $5000 somewhere in the RESET code but that doesn't seem to work. If I include an IRQ handler, it executes that code, which I obviously don't want.
All code is contained in fixed banks, so I really don't know what to do now. Am I missing something?
Anyway, I'd greatly appreciate any help.
scrimpeh wrote:
Anyway, since I wasn't planning to utilize IRQs in my little project in any way.
If it's small project, then why don't try NROM instead of MMC3?
Quote:
I tried writing to $5000 somewhere in the RESET code but that doesn't seem to work.
I can't find about $5000 register for MMC3 either in Nesdevwiki and
Dish's mapper listSo I assume writing to $5000 do anything(?).
Quote:
If I include an IRQ handler, it executes that code, which I obviously don't want.
Then don't include IRQ.
Simply fill IRQ vector addres as 00.
Actually I figured the problem out to be a different one, related to more or less having a coding hole in the game. The $5000 was a typo, but as it turns out, it doesn't have any relevance. So, thank you for your time anyway
Denine wrote:
Then don't include IRQ.
Simply fill IRQ vector addres as 00.
This is actually a very bad idea. $0000 is a perfectly valid IRQ address, which will cause the CPU to jump to $0000 (which is RAM) when IRQs fire. This will likely crash the program, because you probably have variables there, not code.
The quickest fix is actually to execute a SEI instruction at the start of the program. As long as that flag is set no IRQs will happen, even if the cart tries to fire one. You can even put any value you want for the IRQ vector, as it will never be used.
Denine wrote:
Quote:
If I include an IRQ handler, it executes that code, which I obviously don't want.
Then don't include IRQ.
Simply fill IRQ vector addres as 00.
Not a good solution by itself. The correct solution is to disable IRQs with SEI, and keep them disabled. It's also good practice to disable it using mapper registers.
If you do have IRQs disabled, technically the IRQ vector can be 0, but I'd suggest placing some "fatal error handler" in there, maybe something that displays an error message. So if an IRQ happens to trigger anyways due to programming error, at least you'll know instead of CPU executing random crap.
EDIT: ninja'd =)
Empty IRQ handler talk?
Make your IRQ handler do nothing except disable any known sources of IRQs. So your IRQ handler simply acknowledges and disables APU Frame IRQs, or mapper IRQs if they exist, then returns.
I'm only mentioning this because Stars SE assumed that there would never be any interrupts, and disabled them. But the Music Code included enabled Frame IRQ interrupts due to a programming mistake, so the program crashes.
It also doesn't hurt to make your IRQ vector point to the same RTI instruction used by the NMI handler. That should prevent crashes from happening, but ideally you should disable IRQs altogether (use SEI and whatever the mapper requires).
EDIT: Like it's been pointed, if you don't acknowledge the IRQ you might actually get stuck in the IRQ handler, so simply pointing to an RTI will not prevent crashes. So yeah, what I wrote above is wrong.
tokumaru wrote:
It also doesn't hurt to make your IRQ vector point to the same RTI instruction used by the NMI handler. That should prevent crashes from happening, but ideally you should disable IRQs altogether (use SEI and whatever the mapper requires).
It's worth noting that unless the IRQ is automatically acknowledged in some way, which may or may not be the case (most often isn't), the program will get stuck in an infinite loop, as a new IRQ will be triggered right after RTI.
I really think it's the best to have some kind of error handler in the IRQ handler in debug builds if they shouldn't happen. In release builds it may be best to do some damage control instead of showing an error, for example modify the processor status on the stack to disable interrupts, then RTI.
RTI pops the interrupt enable flag, so that won't do you any good.
Dwedit wrote:
RTI pops the interrupt enable flag, so that won't do you any good.
If this was to me, I said to modify the processor status on the stack rather than using SEI.
If the I flag is set, it will disable all sources of IRQs exept BRK instructions. So if you don't plan on executing any BRK instructions, you can be sure that if an IRQ happens a crash happened, so it really doesn't matter where the IRQ points.
If you actually use IRQs, it's best to leave the I flag clear all the time and to disable all sources of IRQs properly when you don't want them to trigger. Only use SEI when you want to prevent IRQs for a very urgent reason, when it would be disasterful if a IRQ happened, such as during MMC1 mapper writes, etc...
Welp, might as well use my thread for all my beginner problems.
Namely, I have a question:
As my code gets larger and more complex, I find myself dealing with a "branch address out of range" error.
Now, this can be solved pretty simple through a series of linked JMP instructions functioning as a bridge, but I can't really imagine that is good programming practice. Is there a way around that? I'd love to know.
Branch over a JMP instruction. Replace this:
Code:
bcc faraway
with this (assuming ca65 syntax):
Code:
bcs :+
jmp faraway
:
If you're using CA65 you can use this, or maybe a macro like this can be adapted to another assembler:
http://www.cc65.org/doc/ca65-13.html#ss13.2
Then it will automatically jump or branch depending on how far it is.