[A83] Re: interrupt with rom calls
[Prev][Next][Index][Thread]
[A83] Re: interrupt with rom calls
> > From: "Patai Gergely" <patai.ti@freemail.hu>
> >
> > This piece of code made me thinking a bit. I use a special
> > routine for fast side-scrolling that uses both shadow
> > registers and modifies SP as well. How could I set
> > up a safe interrupt in this case?
> >
> > (The question is actually rather theoric, because I
> > tend to disable interrupts for the running time of my
> > programs.)
>
> Van: Tijl Coosemans <tijl@ulyssis.org>
>
> Henk Poley has made some code that you can wrap arround the standard
> interrupt handler and which saves all register, including the shadow
> regs, on the stack. Being able to use SP can be easily added. At the
> start of your interrupt routine you first save SP and let it point to
> some safe location. Then push all the regs there. Afterwards you can just
> pop them and restore SP to what it was when the interrupt routine was
> called.
>
> HP will tell you how things work exactly. Calling the standard interrupt
> controller is a bit tricky :-)
It's quite 'easy':
- push all regs (AF, DE, HL, BC[, IY])
- check if the wrapper exited correctly last time (using a flag)
- fix the stack if not
- set flag to 'incorrect'
[- set IY to point to flags]
- swap to shadow regs
- call the TIOS interrupt handler
- which swaps back to our saved regs, executes it's code
- and at the end swaps to the shadow regs again
- enables interrupts
- tricky part, disable interupts
- if an interrupt occured inbetween, the checking part will correct it
- swap to normal registers
- set flag to 'correct' again
- pop all regs
- return
And I know, there is no way to distinguish between 'shadow' regs and the
'normal' registers. It's just easier to understand if I write it like this.
I don't know what you exactly mean with 'modifies the SP'. SP is the stack
pointer, but you don't tell what you change about it. If it would give
problems if there's data getting witten to the space below the SP, you
won't be able to run an interrupt, as since when an interrupt occures the
current PC will be pushed to the stack.
Well, this is the code Tijl is talking about, the interrupt loader used is
the one I posted before:
; Ti83 interrupt 'wrapper' - by Henk Poley
;--------------------------------------------------------------------------
; The z88dk makes extensively use of the shadow registers (EXX and EX
AF,AF)
; The Ti83 system interrupt doesn't preserve (any of) these regs and
; could thus crash your program. The workaround is to use this interrupt
; all the time, it saves and restores the (shadow-)registers for the
; system interrupt.
; We need the system interrupt when scanning keys (in an easy way), also
; some (other) ROM calls make use of the system interrupt. if the
interrupt
; is then not running, the calculator would crash.
;--------------------------------------------------------------------------
defc _IY_TABLE = $8567 ; Where IY usually points
defc intcount = $878A ; 1 byte needed
INCLUDE "#int83.asm" ; Put interrupt loader here
; HL = $8789
inc hl ; We need to intialize variables
ld (hl),0 ; by ourself.
;
jr jump_over ; Jump over the interrupt code
;-----------------
; Actual interrupt
;-----------------
.IntProcStart
push af ;
ld a,(intcount) ; Check if own interrupt has quited
bit 7,a ; correctly, then bit 7 is zero
jr nz,int_fix ; If not zero, fix stack...
push hl ;
push de ;
push bc ;
push iy ;
ld iy,_IY_TABLE ;
ld hl,intcount ; If a 'direct interrupt' occures
set 7,(hl) ; right after the TIOS-int, then
; we want bit 7 to be set...
.exit_interrupt ;
exx ; Swap to shadow registers.
ex af,af ; So the TIOS swaps back to the
; normal ones... (the ones we saved
; with push/pops)
rst $38 ;
di ; 'BIG' HOLE HERE... (TIOS does ei...)
ex af,af ;
exx ;
;
;.exit_interrupt ;
ld hl,intcount ; Interrupt returned correctly, so
res 7,(hl) ; we reset our error-condition...
;
pop iy ;
pop bc ;
pop de ;
pop hl ;
pop af ;
ei ;
ret ;
.int_fix ;
pop af ; Pop AF back
ex af,af ; Fix shadowregs back
exx ;
pop bc ; Pop the returnpoint of RST $38
; from the stack
jr exit_interrupt ; Continue with interrupt
.IntProcEnd
.jump_over
; Memory usage in statvars:
; -------------------------------------------
; $858F / $85FF - 113 bytes - free
; $8600 / $8700 - 256 bytes - IV table
; $8701 / $8786 - 134 bytes - free
; $8787 / $8789 - 3 bytes - JP IntProcStart
; $878A - 1 byte - intcount <--
; $878B / $87A2 - 24 bytes - free
; -------------------------------------------
Follow-Ups: