Page 1 of 1

Interrupt Service Routine

Posted: Fri Aug 04, 2017 4:39 pm
by NekadZut
So I understand that an interrupt vector is an address to some area of memory which contains code to acknowledge and handle an interrupt, but exactly what address is stored in little endian at 0xFFFE and 0xFFFF and what does that point to?

Thanks

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 5:09 pm
by dougeff
Whatever the programmer wants it to point to / wants it to do.

Typical IRQs handle mid-screen scroll shifts. So...the IRQ code would store values to $2005, then return (rti).

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 6:02 pm
by tokumaru
The vectors point to wherever the programmer has placed the interrupt handling routines. It could be any address from $0000 to $FFFF. Normally the vectors point to ROM, and you definitely want the reset code to be in ROM, but the NMI and IRQ handlers could very well be in RAM if the program has time to put code there.

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 6:57 pm
by Garth
The vector points to the beginning address of the interrupt-service routine.

I have a 6502 interrupts primer at http://wilsonminesco.com/6502interrupts/ . (Enjoy my outdated cartoons!)

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 7:13 pm
by NekadZut
Is there not some standard interrupt service routine for the three interrupts on the NES, or do I just write some 6502 assembly service routine and believe?

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 7:54 pm
by tepples
Apart from Famicom Disk System games, many of which use the NMI handler in the BIOS, each game engine will have its own NMI and IRQ handler. There really isn't a single library that the majority of games use, except for this one seen in several relatively simple homebrew games:

Code: Select all

nmi_handler:
  inc nmi_counter  ; some zero page variable
  rti
It's the minimum that lets the main thread know that the NMI has occurred.

Re: Interrupt Service Routine

Posted: Fri Aug 04, 2017 8:49 pm
by tokumaru
Also, simpler games don't typically use IRQs, so you can have the simplest NMI/IRQ combo possible (a small edit over tepples' code:

Code: Select all

nmi_handler:
  inc nmi_counter
irq_handler:
  rti
This is enough to get started with NES programming. Games using this will only "break" if 1 game frame takes longer than 1 hardware frame to be processed.

As for the reset handler, the wiki has some sample initialization code you can copy or study. Once the initialization is done, the actual game logic starts.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 8:06 am
by NekadZut
Why doesn't this reset/init code have an RTI or JMP to get the PC to the start of the cartridge ROM?

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 9:03 am
by tepples
The init code doesn't have an RTI because there's no return address on the stack. It doesn't have a JMP because if the beginning of the code that loads the title screen into video memory immediately follows the init code in ROM, you don't need a JMP.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 9:18 am
by NekadZut
Oh, I see. So whenever the NES is turned on or reset, this interrupt will occur and would set PC to the start of the ROM which is where this code would be supplied.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 9:50 am
by AWJ
RESET is similar to an interrupt from a hardware perspective, but unlike normal interrupts you don't "return" from it. The code pointed to by the RESET vector is your program's entry point.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 11:14 am
by tokumaru
The program doesn't necessarily begin at the start of the ROM, it begins wherever the reset handler is, that's why you need the vector to point to it. If it always started at a fixed location, there wouldn't be need for a pointer. When the CPU Powers up, the PC is set to the value stored in the reset vector.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 12:16 pm
by tepples
Some CPUs read an address from a fixed location in ROM to know where to start reading instructions. This is similar to an indirect jump.
  • 6502 reads the program counter from $FFFC, as if JMP ($FFFC).
  • 68000 reads the stack pointer from $000000 and the program counter from $000004, as if MOVE.L $000000,A7 MOVE.L $000004,A6 JMP (A6), except A6 isn't actually modified.
Others jump to a fixed location.
  • Z80 starts with JP 0000h
  • 8086 starts with JMP FFFFh:0000h (changed to F000h:FFF0h in later CPUs)
  • PowerPC starts with BA 0x00000100
The fact that 6502 and 68000 begin with an indirect jump through a reset vector instead of executing from a fixed address confuses the heck out of a lot of beginning emulator developers.

Re: Interrupt Service Routine

Posted: Sat Aug 05, 2017 3:10 pm
by dougeff
confuses the heck out of a lot of beginning emulator developers.
Confused the heck out of me, when I first looked at NES ROM and tried to figure out how the program starts...and saw 100+ bytes of data at the start of the ROM. I kept thinking there must be some kind of JMP instruction to the start. Until I read some technical documents.