Fixed IRQ demo
This commit is contained in:
parent
8293982246
commit
8087aafc32
4 changed files with 87 additions and 23 deletions
5
examples/irq_demo/cm.sh
Executable file
5
examples/irq_demo/cm.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
# Define filename as variable
|
||||
PROGNAME="irq_demo"
|
||||
# Compile and assemble directly
|
||||
c65gm ${PROGNAME}.c65
|
||||
55
examples/irq_demo/irq_demo.c65
Normal file
55
examples/irq_demo/irq_demo.c65
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//-----------------------------------------------------------
|
||||
// Simple IRQ Handler Demo
|
||||
//
|
||||
// Installs a custom IRQ handler through the kernal vector at
|
||||
// $0314. The kernal has already saved the registers for us
|
||||
// before it calls the vector, so our handler does NOT push or
|
||||
// pull A/X/Y. When we are done we jump into the kernal so it
|
||||
// can finish the IRQ and RTI properly:
|
||||
//
|
||||
// jmp $ea31 - let the kernal do its full IRQ work
|
||||
// (scan keyboard, blink cursor, update jiffy
|
||||
// clock, ...) and then RTI
|
||||
// jmp $ea81 - skip the kernal work, just restore the
|
||||
// registers the kernal saved and RTI
|
||||
//
|
||||
// This handler chains to $ea31 so the machine stays usable.
|
||||
//-----------------------------------------------------------
|
||||
|
||||
#INCLUDE <c64start.c65>
|
||||
#INCLUDE <c64defs.c65>
|
||||
|
||||
GOTO start
|
||||
|
||||
WORD CONST IRQ_VECTOR = $0314
|
||||
WORD handler = @myIRQ // Address of our IRQ handler
|
||||
|
||||
FUNC installIRQ
|
||||
ASM
|
||||
sei // Disable interrupts while we patch
|
||||
ENDASM
|
||||
|
||||
POKEW IRQ_VECTOR, handler // Point the vector at our handler
|
||||
|
||||
ASM
|
||||
cli // Re-enable interrupts
|
||||
ENDASM
|
||||
FEND
|
||||
|
||||
|
||||
LABEL start
|
||||
installIRQ()
|
||||
SUBEND //exit back to basic
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// The IRQ handler.
|
||||
//
|
||||
// No register saving needed - the kernal did it. Do the work,
|
||||
// then hand control back to the kernal at $ea31 which restores
|
||||
// the registers and returns from the interrupt.
|
||||
//-----------------------------------------------------------
|
||||
LABEL myIRQ
|
||||
ASM
|
||||
inc $0400 // Bump the top-left screen character
|
||||
jmp $ea31 // Let the kernal finish the IRQ
|
||||
ENDASM
|
||||
1
examples/irq_demo/start_in_vice.sh
Executable file
1
examples/irq_demo/start_in_vice.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
x64 -autostartprgmode 1 irq_demo.prg
|
||||
49
language.md
49
language.md
|
|
@ -925,46 +925,49 @@ FEND
|
|||
|
||||
### Interrupt Handlers
|
||||
|
||||
The C64 kernal calls the IRQ vector at `$0314` on every interrupt. Because
|
||||
the kernal saves the CPU registers *before* calling the vector, your handler
|
||||
does **not** need to push/pull A/X/Y itself. When finished, chain into the
|
||||
kernal so it restores the registers and returns from the interrupt:
|
||||
|
||||
- `jmp $ea31` — let the kernal do its full IRQ work (scan keyboard, blink
|
||||
cursor, update the jiffy clock, ...) and then `RTI`
|
||||
- `jmp $ea81` — skip that work; just restore the saved registers and `RTI`
|
||||
|
||||
Once the vector is installed it keeps firing in the background, so the main
|
||||
program can simply return to BASIC with `SUBEND` — the handler stays live.
|
||||
|
||||
```c65
|
||||
WORD CONST IRQ_VECTOR = $0314
|
||||
WORD oldIRQ
|
||||
WORD handler = @myIRQ // Address of our IRQ handler
|
||||
|
||||
FUNC installIRQ
|
||||
ASM
|
||||
sei // Disable interrupts
|
||||
sei // Disable interrupts while we patch
|
||||
ENDASM
|
||||
|
||||
oldIRQ = PEEKW IRQ_VECTOR
|
||||
POKEW IRQ_VECTOR, myIRQ
|
||||
POKEW IRQ_VECTOR, handler // Point the vector at our handler
|
||||
|
||||
ASM
|
||||
cli // Enable interrupts
|
||||
cli // Re-enable interrupts
|
||||
ENDASM
|
||||
FEND
|
||||
|
||||
LABEL start
|
||||
installIRQ()
|
||||
SUBEND // Return to BASIC; the IRQ stays installed
|
||||
|
||||
// No register saving needed — the kernal already did it.
|
||||
LABEL myIRQ
|
||||
// IRQ handler code
|
||||
ASM
|
||||
// Save registers
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
|
||||
// Do IRQ work
|
||||
inc $d020
|
||||
|
||||
// Restore and return
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
rti
|
||||
inc $0400 // Do the IRQ work
|
||||
jmp $ea31 // Let the kernal finish the IRQ
|
||||
ENDASM
|
||||
```
|
||||
|
||||
See `examples/irq_demo/` for a complete, buildable version.
|
||||
|
||||
|
||||
### Lookup Tables
|
||||
|
||||
Generate tables at compile time:
|
||||
|
|
|
|||
Loading…
Reference in a new issue