;PAGE	30

;		.TITLE	'INTERRUPT HANDLER'
;LIVES ON DK1:INTHV.SRC
SRTIM2	=	6		;SECOND REPEAT INTERVAL
;
; THIS IS TO MAKE DOS 2 WORK WHICH USED AN ABSOLUTE ADDRESS
;
	.ORG	$E912
	JMP	SETVBL
	.ORG	SETVBV
	JMP	SETVBL
	JMP	SYSVBL
	JMP	XITVBL
	.ORG	INTINV
	JMP	IHINIT
;
	.ORG	VCTABL+INTABS-VDSLST
;
	.WORD	SYRTI		;VDSLST
	.WORD	SYIRQB		;VPRCED
	.WORD	SYIRQB		;VINTER
	.WORD	SYIRQB		;VBREAK
;
	.RES	8
	.WORD	SYIRQB		;VTIMR1
	.WORD	SYIRQB		;VTIMR2
	.WORD	SYIRQB		;VTIMR4
	.WORD	SYIRQ		;VIMIRQ
	.WORD	0,0,0,0,0	;CDTMV1-4
	.WORD	SYSVBL		;VVBLKI
	.WORD	XITVBL		;VVBLKD
;
	.ORG	$900C
;
	LDA	#PIRQH		;SET UP RAM VECTORS FOR LINBUG VERSION
	STA	$FFF9
	LDA	#PIRQL
	STA	$FFF8
	LDA	#PNMIH
	STA	$FFFB
	LDA	#PNMIL
	STA	$FFFA
	RTS
	
;PAGE	31

;	.PAGE
;
; IRQ HANDLER
;
; JUMP THRU IMMEDIATE IRQ VECTOR, WHICH ORDINARILY POINTS TO
; SYSTEM IRQ: DETERMINE & CLEAR CAUSE, JUMP THRU SOFTWARE VECTOR.
;
	.ORG	INTORG
IHINIT: LDA	#$40		;VBL ON BUF DLIST OFF***FOR NOW***
	STA	NMIEN		;ENABLE DISPLAY LIST, VERTICAL BLANK
	LDA	#$38		;LOOK AT DATA DIRECTION REGISTERS IN PIA
	STA	PACTL
	STA	PBCTL
	LDA	#0		;MAKE ALL INPUTS
	STA	PORTA
	STA	PORTB
	LDA	#$3C		;BACK TO PORTS
	STA	PACTL
	STA	PBCTL
	RTS
PIRQ:	JMP	(VIMIRQ)
CMPTAB: .BYTE	$80		;BREAK KEY
	.BYTE	$40		;KEY STROKE
	.BYTE	$04		;TIMER 4
	.BYTE	$02		;TIMER 2
	.BYTE	$01		;TIMER 1
	.BYTE	$08		;SERIAL OUT COMPLETE
	.BYTE	$10		;SERIAL OUT READY
	.BYTE	$20		;SERIAL	IN READY
; THIS IS A TABLE OF OFFSETS INTO PAGE 2.
; THEY POINT TO ~~~
ADRTAB: .BYTE	BRKKY-INTABS
	.BYTE	VKEYBD-INTABS
	.BYTE	VTIMR4-INTABS
	.BYTE	VTIMR2-INTABS
	.BYTE	VTIMR1-INTABS
	.BYTE	VSEROC-INTABS
	.BYTE	VSEROR-INTABS
	.BYTE	VSERIN-INTABS
SYIRQ:	PHA			;SAVE ACCUMULATOR
	LDA	IRQST		; CHECK FOR SERIAL IN
	AND	#$20
	BNE	SYIRQ2
	LDA	#$DF		; MASK ALL OTHERS
	STA	IRQEN
	LDA	POKMSK
	STA	IRQEN
	JMP	(VSERIN)
SYIRQ2: TXA			;PUT X INTO ACC
	PHA			;SAVE X ONTO STACK
	LDX	#$6		;START WITH SIX OFFSET
LOOPM:	LDA	CMPTAB,X	;LOAD MASK
	CPX	#5		;CHECK TO SEE IF COMPLETE IS SET

;PAGE	32

	BNE	LOOPM2
	AND	POKMSK		;IS THIS INTERUPT ENABLED?
	BEQ	LL
LOOPM2: BIT	IRQST		; IS IT THE INTERRUPT?
	BEQ	JMPP
LL:	DEX			;NO DEC X AND TRY NEXT MASK
	BPL	LOOPM		;IF NOT NEG GOTO LOOPM
	JMP	SYIRQ8		;DONE BUT NO INTERRUPT
JMPP:	EOR	#$FF		;COMPLEMENT MASK
	STA	IRQEN		;ENABLE ALL OTHERS
	LDA	POKMSK		; GET POKE MASK
	STA	IRQEN		; ENABLE THOSE IN POKE MASK
	LDA	ADRTAB,X
	TAX
	LDA	INTABS,X	; GET ADDRESS LOW PART
	STA	JVECK		; PUT IN VECTOR
	LDA	INTABS+1,X	; GET ADDRESS HIGH PART
	STA	JVECK+1		; PUT IN VECTOR HIGH PART
	PLA			; PULL X REGISTER FROM STACK
	TAX			; PUT IT INTO X
	JMP	(JVECK)		; JUMP TO THE PROPER ROUTINE
BRKKY2: LDA	#0		; BREAK KEY ROUTINE
	STA	BRKKEY		; SET BREAK KEY FLAG
	STA	SSFLAG		; START/STOP FLAG
	STA	CRSINH		; CURSOR INHIBIT
	STA	ATRACT		; TURN OFF ATRACT MODE
	PLA
	RTI			;EXIT FROM INT
SYIRQ8: PLA
	TAX
	BIT	PACTL		;PROCEED ***I GUESS***
	BPL	SYIRQ9
	LDA	PORTA		; CLEAR INT STATUS BIT
	JMP	(VPRCED)
SYIRQ9: BIT	PBCTL		;INTERRUPT ***I GUESS***
	BPL	SYIRQA
	LDA	PORTB		;CLEAR INT STATUS
	JMP	(VINTER)
SYIRQA: PLA
	STA	JVECK
	PLA
	PHA
	AND	#$10		;B BIT OF P REGISTER
	BEQ	SYRTI2
	LDA	JVECK
	PHA
	JMP	(VBREAK)
SYRTI2: LDA	JVECK
	PHA
SYIRQB: PLA
SYRTI:	RTI			;UNIDENTIFIED INTERRUPT, JUST RETURN.
 	
;PAGE	33

;	.PAGE
;
; NMI HANDLER
;
; DETERMINE CAUSE AND JUMP THRU VECTOR
;
PNMI:	BIT	NMIST
	BPL	PNMI1		;SEE IF DISPLAY LIST
	JMP	(VDSLST)
PNMI1:	PHA
	LDA	NMIST
	AND	#$20		;SEE IF RESET
	BEQ	*+5
	JMP	WARMSV		;GO THRU WARM START JUMP
	TXA			;SAVE REGISTERS
	PHA
	TYA
	PHA
	STA	NMIRES		;RESET INTERRUPT STATUS
	JMP	(VVBLKI)	;JUMP THRU VECTOR
	
;PAGE	34

;	.PAGE
;
; SYSTEM VBLANK ROUTINE
;
; INC FRAME COUNTER. PROCESS COUNTDOWN TIMERS. EXIT IF I WAS SET, CLEAR
; SET DLISTL, DLISTH, DMACTL FROM RAM CELLS. DO SOFTWARE REPEAT.
;
SYSVBL: INC	RTCLOK+2	;INC FRAME COUNTER
	BNE	SYSVB1
	INC	ATRACT		;INCREMENT ATRACT (CAUSES ATRACT WHEN MINUS)
	INC	RTCLOK+1
	BNE	SYSVB1
	INC	RTCLOK
SYSVB1: LDA	#$FE		;{ATRACT] SET DARK MASK TO NORMAL
	LDX	#0		;SET COLRSH TO NORNAL
	LDY	ATRACT		;TEST ATRACT FOR NEGATIVE
	BPL	VBATRA		;WHILE POSITIVE, DONT GO INTO ATRACT
	STA	ATRACT		;IN ATRACT, SO STAY BY STA $FE
	LDX	RTCLOK+1	;COLOR SHIFT FOLLOWS RTCLOK+1
	LDA	#$F6		;SET DARK MASK TO DARK
VBATRA: STA	DRKMSK
	STX	COLRSH
	LDX	#0		;POINT TO TIMER1
	JSR	DCTIMR		;GO DECREMENT TIMER1
	BNE	SYSVB2		;BRANCH IF STILL COUNTING
	JSR	JTIMR1		;GO JUMP TO ROUTINE
SYSVB2: LDA	CRITIC
	BNE	XXIT		;GO IF CRITICAL SET
	TSX			;SEE IF I WAS SET
	LDA	$104,X		;GET STACKED P
	AND	#$04		;I BIT
	BEQ	SYSVB3		;BRANCH IF OK
XXIT:	JMP	XITVBL		;I WAS SET, EXIT
SYSVB3: LDA	PENV
	STA	LPENV
	LDA	PENH
	STA	LPENH
	LDA	SDLSTH
	STA	DLISTH
	LDA	SDLSTL
	STA	DLISTL
	LDA	SDMCTL
	STA	DMACTL
	LDA	GPRIOR		;GLOBAL PRIOR
	STA	PRIOR
	LDX	#$08		;TURN OFF KEYBOARD SPEAKER
	STX	CONSOL
SCOLLP: CLI			;DISABLE INTERUPTS
	LDA	PCOLR0,X		;LOAD COLOR REGISTERS FROM RAM
	EOR	COLRSH		;DO COLOR SHIFT
	AND	DRKMSK		;AND DARK ATRACT
	STA	COLPM0,X
	DEX
	BPL	SCOLLP
 	
;PAGE	35

	LDA	CHBAS
	STA	CHBASE
	LDA	CHACT
	STA	CHACTL
	LDX	#2		;POINT TO TIMER 2
	JSR	DCTIMR
	BNE	SYSVB4		;IF DIDNT GO ZERO
	JSR	JTIMR2		;GO JUMP TO TIMER2 ROUTINE
SYSVB4: LDX	#2			;RESTORE X
SYSVBB: INX
	INX
	LDA	CDTMV1,X
	ORA	CDTMV1+1,X
	BEQ	SYSVBA
	JSR	DCTIMR		;DECREMENT AND SET FLAG IF NONZERO
	STA	CDTMF3-4,X
SYSVBA: CPX	#8		;SEE IF ALL DONE 3
	BNE	SYSVBB		;LOOP
; CHECK DEBOUNCE COUNTER
	LDA	SKSTAT
	AND	#$04		;KEY DOWN BIT
	BEQ	SYVB6A		;IF KEY DOWN
; KEY UP SO COUNT IT
	LDA	KEYDEL		;KEY DELAY COUNTER
	BEQ	SYVB6A		;IF COUNTED DOWN ALREADY
	DEC	KEYDEL		;COUNT IT
; CHECK SOFTWARE REPEAT TIMER
SYVB6A: LDA	SRTIMR
	BEQ	SYSVB7		;DOESN'T COUNT
	LDA	SKSTAT
	AND	#$04		;CHECK KEY DOWN BIT
	BNE	SYSVB6		;BRANCH IF NO LONGER DOWN
	DEC	SRTIMR		;COUNT FRAME IF KEY DOWN
	BNE	SYSVB7		;BRANCH IF NOT RUN OUT
; TIMER RAN OUT - RESET AND SIMULATE KEYBOARD IRQ
	LDA	#SRTIM2		;TIMER VALUE
	STA	SRTIMR		;SET TIMER
	LDA	KBCODE		;GET THE KEY
	STA	CH		;PUT INTO CH
; READ GAME CONTROLLERS
SYSVB7: LDY	#1
	LDX	#3
STLOOP: LDA	PORTA,Y
	LSR	A
	LSR	A
	LSR	A
	LSR	A
	STA	STICK0,X	;STORE JOYSTICK
	DEX
	LDA	PORTA,Y
	AND	#$F
	STA	STICK0,X	;STORE JOYSTICK
	DEX
	DEY
	
;PAGE	36

	BPL	STLOOP
;
	LDX	#3
STRL:	LDA	TRIG0,X		;MOVE JOYSTICK TRIGGERS
	STA	STRIG0,X
	LDA	POT0,X		;MOVE POT VALUES
	STA	PADDL0,X
	LDA	POT4,X
	STA	PADDL4,X
	DEX
	BPL	STRL
	STA	POTGO		;START POTS FOR NEXT TIME
;
	LDX	#6
	LDY	#3
PTRLP:	LDA	STICK0,Y	;TRANSFER BITS FROM JOYSTICKS
	LSR	A		;TO PADDLE TRIGGERS
	LSR	A
	LSR	A
	STA	PTRIG1,X
	LDA	#0
	ROL	A
	STA	PTRIG0,X
	DEX
	DEX
	DEY
	BPL	PTRLP
;
	JMP	(VVBLKD)	;GO TO DEFERRED VBLANK ROUTINE
SV7H	= SYSVB7/256
SV7L	= (-256)*SV7H+SYSVB7
SYSVB6: LDA	#0
	STA	SRTIMR		;ZERO TIMER
	BEQ	SYSVB7		;UNCOND
JTIMR1: JMP	(CDTMA1)
JTIMR2: JMP	(CDTMA2)
;
; SUBROUTINE TO DECREMENT A COUNTDOWN TIMER
; ENTRY X=OFFSET FROM TIMER 1
; EXIT A,P=ZERO IF WENT ZERO, FF OTHERWISE
;
DCTIMR: LDY	CDTMV1,X	;LO BYTE
	BNE	DCTIM1		;NONZERO, GO DEC IT
	LDY	CDTMV1+1,X	;SEE IF BOTH ZERO
	BEQ	DCTXF		;YES, EXIT NONZERO
	DEC	CDTMV1+1,X	;DEC HI BYTE
DCTIM1: DEC	CDTMV1,X	;DEC LO BYTE
	BNE	DCTXF
	LDY	CDTMV1+1,X
	BNE	DCTXF
	LDA	#0		;WENT ZERO, RETURN ZERO
	RTS
DCTXF:	LDA	#$FF		;RETURN NONZERO
	RTS
	
;PAGE	37
;	.PAGE
;
; SUBROUTINE TO SET VERTICAL BLANK VECTORS AND TIMERS
; ENTRY X=HI,Y=LO BYTE TO SET
;	A= 1-5 TIMERS 1-5
;		6 IMM VBLANK
;		7 DEF VBLANK
;
SETVBL: ASL	A		;MUL BY 2
	STA	INTEMP
	TXA
	LDX	#5
	STA	WSYNC		;WASTE 20 CPU CYCLES
SETLOP: DEX			;TO ALOWD VBLANK TO HAPPEN
	BNE	SETLOP		;IF THIS IS LINE "7C"
	LDX	INTEMP
	STA	CDTMV1-1,X
	TYA
	STA	CDTMV1-2,X
	RTS
;
; EXIT FROM VERTICAL BLANK
;
XITVBL: PLA			;UNSTACK Y
	TAY
	PLA			;UNSTACK X
	TAX
	PLA			;UNSTACK A
	RTI			;AND GO BACK FROM WHENCE.
PIRQH	=	PIRQ/256
PIRQL	=	(-256)*PIRQH+PIRQ
PNMIH	=	PNMI/256
PNMIL	=	(-256)*PNMIH+PNMI
; SPARE BYTE OR MODULE TOO LONG FLAG
CRNTP2	=*
	.ORG	$14
INTSPR: .BYTE	SIOORG-CRNTP2 ;^GINTHV IS TOO LONG
 
