goodenough@vogon.DEC (Jeff Goodenough, IPG Reading DEC-UK) (03/06/86)
Well, this isn't really any longer than some of the postings to this
newsgroup, so specially for "dave3" and Marco, and any others who might want
it, here is my sample code for handling Raster Interrupts. In any case,
my brain starts to hurt after about the eighth node in a routing. Perhaps
we can persuade you all to convert to VMS and DECnet :-) :-)
NOTE: If some of the code looks a bit non-standard (e.g. BYT) it's because
I wrote my own assembler, and made some tweaks to the "standard" to
make things a bit easier.
Jeff.
=*= =*= =*=
Sample code for raster interrupts
This example assumes that the screen is split in half, the top half in
hires bitmap mode, and the bottom half in normal character mode.
The screen memory is 1Kb from $0400-$07FF (default), the character memory
2Kb from $1000-17FF (Character ROM image - default), and the bitmap
(potentially) 8Kb from $2000-$3FFF. Since only the first half of the
bitmap is actually displayed, the second half ($3000-$3FFF) could be used
to store other information (code or data). Note that the VIC chip is
somewhat peculiar, and only *it* thinks it sees the character ROM at $1000-
$17FF. The ROM isn't actually there, so there's nothing to stop you storing
other code/data in these locations.
Equates
VIC =$D000 ; start of VIC chip
BITMAP =$2000 ; start of bitmap
SCVAL =147 ; split at scan line 147 (top of row 13)
CHROUT =$FFD2 ; kernel routine: output character
IRQ =$EA31 ; kernel interrupt routine
Data
RASVAL BYT 0 ; byte to store current raster value
Initialization code (put this somewhere at the beginning of your program):
SEI ; inhibit interrupts
LDA #<INT ; set up interrupt vector
STA $0314
LDA #>INT
STA $0315
CLI ; re-enable interrupts
Subroutine to turn split screen/bitmap on:
BMON LDA #11 ; example - sets screen/border to Grey 1
STA VIC+$20 ; (if you want to)
STA VIC+$21
SEI ; inhibit interrupts
LDA #0
STA RASVAL ; set raster value to top of screen (0)
STA VIC+$12 ; store in VIC raster compare register
LDA VIC+$11 ; clear bit 8 of raster value (always 0)
AND #$7F
STA VIC+$11
LDA VIC+$1A ; VIC IRQ mask register
ORA #1 ; enable raster interrupt
BMON1 STA VIC+$1A
CLI ; enable interrupts
LDA #147
JMP CHROUT ; clear screen and return
Subroutine to turn split screen/bitmap off:
BMOFF LDA #14 ; example - resets screen/border to Lt Blue
STA VIC+$20 ; (if you want to)
STA VIC+$21
SEI ; inhibit interrupts
LDA #$1B ; turn off bitmap mode
STA VIC+$11
LDA #$08 ; turn off multicolor mode
STA VIC+$16 ; (if you turned it on)
LDA #$14 ; map VIC back to character memory
STA VIC+$18
LDA VIC+$1A ; VIC IRQ mask register
AND #$FE ; disable raster interrupt
JMP BMON1
Interrupt routine:
INT LDA #1
BIT VIC+$1A ; are raster interrupts enabled?
BEQ MINT ; br if not, to main interrupt service
BIT VIC+$19 ; had an interrupt, but is it a raster int?
BEQ MINT ; br if not
STA VIC+$19 ; clear the latched raster interrupt bit
LDA RASVAL ; get the last-stored scan value
BNE RINT1 ; br if not at top of screen
LDA #$3B ; enable bitmap mode
STA VIC+$11
LDA #$18 ; map VIC to bitmap (also right value for
; setting multicolor mode in VIC+$16)
STA VIC+$18
LDX #SCVAL ; get the required scan line value
BNE RINT2 ; (branch assumes SCVAL non-zero!)
;
RINT1 LDX #0 ; at split - get top of screen value
[LDA #$08 ; clear multicolor mode if you set it]
RINT2 STX RASVAL ; save the new scan value
STX VIC+$12 ; store in raster compare register
[STA VIC+$16 ; set or clear multicolor bit]
;
; Following code mimics kernel interrupt exit
;
LDA $DC0D
PLA
TAY
PLA
TAX
PLA
RTI
;
MINT <any other interrupt handling you need to do>
JMP IRQ ; jump to kernel interrupt handling
Jeff.