[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: