Apple II

Vertical BLanking (VBL)

We would like to be able to detect Vertical BLanking (VBL) on all models of Apple II.

"Applications can accomplish smooth animation on the Apple IIGS and Apple IIe by changing the data on the screen during the time the system is tracing the unusable area of the display. This time is called "vertical blanking" or "VBL" in this Note. You can determine the state of the VBL signal by reading location $C019."

Apple IIGS Technical Note #40, VBL Signal

The following is a 6502 assembly language routine for detecting VBL on all models of Apple II. This method assumes that interrupt handing is turned off because we need deterministic cycle counting.

VBL machine-language routine:
1100:
:A0 0 98 99 0 10 C8 D0 FA CE 0 10 84 FA A9 20
:85 FB B1 FA AA BD 0 10 C9 FF F0 3 FE 0 10 C8
:D0 F0 E6 FB A5 FB C9 40 D0 E8 A9 FF 85 FD BE 0
:10 E4 FD B0 4 86 FD 84 FC C8 D0 F2 A2 0 A9 20
:85 FB A5 FC D1 FA D0 15 49 FF 91 FA A9 8D 9D 99
:11 E8 98 9D 99 11 E8 A5 FB 9D 99 11 E8 C8 D0 E2
:E6 FB A5 FB C9 40 D0 DA A9 AD D0 4 9D 99 11 E8
:E0 60 D0 F8 8A 9D 99 11 2C 52 C0 2C 54 C0 2C 57
:C0 2C 50 C0 AE D0 27 A5 FC 8D D0 27 CD 50 C0 D0
:FB 8E D0 27 A2 23 CA D0 FD       

	ORG $1100

VALUE	EQU $FC
MINIMUM EQU $FD
PTRLO	EQU $FA
PTRHI	EQU $FB
TABLE	EQU $1000
VIDMEM	EQU $27D0

; CLEAR TABLE
	LDY #$00
	TYA
CLEAR
	STA TABLE,Y
	INY
	BNE CLEAR
; COUNT BYTES
	DEC TABLE ; REMOVE 0
	STY PTRLO
	LDA #$20
	STA PTRHI
COUNT
	LDA (PTRLO),Y
	TAX
	LDA TABLE,X
	CMP #$FF
	BEQ SKIP
	INC TABLE,X
SKIP
	INY
	BNE COUNT
	INC PTRHI
	LDA PTRHI
	CMP #$40
	BNE COUNT
; MINIMUM
	LDA #$FF
	STA MINIMUM
FIND
	LDX TABLE,Y
	CPX MINIMUM
	BCS NEXT
	STX MINIMUM
	STY VALUE
NEXT
	INY
	BNE FIND
; STORE WITH BACKUP
	LDX #$00
	LDA #$20
	STA PTRHI
LOOP
	LDA VALUE
	CMP (PTRLO),Y
	BNE NOSTORE
	EOR #$FF
	STA (PTRLO),Y
	LDA #$8D
	STA RESTORE,X
	INX
	TYA
	STA RESTORE,X
	INX
	LDA PTRHI
	STA RESTORE,X
	INX
NOSTORE
	INY
	BNE LOOP
	INC PTRHI
	LDA PTRHI
	CMP #$40
	BNE LOOP
; FILL INSTRUCTIONS
	LDA #$AD
	BNE DONOTHING
NOTHING
	STA RESTORE,X
	INX
DONOTHING
	CPX #$60
	BNE NOTHING
	TXA
	STA RESTORE,X
; DETECT
	BIT $C052    ; FULL SCREEN
	BIT $C054    ; PAGE ONE
	BIT $C057    ; HI-RES
	BIT $C050    ; GRAPHICS
	LDX VIDMEM
	LDA VALUE
	STA VIDMEM
POLLIT
	CMP $C050    ; 4? READ BUS
	BNE POLLIT   ; 2 LOOP IF NOT FOUND
	STX VIDMEM   ; 4
	LDX #$23     ; 2
DELAY
	DEX          ; 2
	BNE DELAY    ; 3
RESTORE          ; 134 = 32 * 4 + 6
;	CODE IS UPDATED HERE

The bus is read, and the POLLIT loop runs until the special byte is found. Every 7 cycles the bus is read. "It takes 17030 cycles for the gun to end up in the same place on the screen." 17030 / 7 = 2432 remainder 6, and 7 * 2432 = 17024 which conveniently offsets the reading by 1 cycle. Using the loop, all screen bytes are checked by reading the bus every 7 cycles from $C050.

Apple II video timing
source: http://rich12345.tripod.com/aiivideo/vbl.html

The floating bus scanning is not as simple as the above diagram suggests. There are many screen addresses that are rescanned. And note that in testing this on an emulator the value $00 appears on the floating bus even when there are no zero bytes stored in screen memory. The exact details of Apple II video scanning is described in Understanding the Apple II by Jim Sather.

There is a lot of housekeeping in determining a good choice of byte to search for. The routine is "non-destructive" in that it temporarily modifies HGR and then restores the HGR screen bytes.

Hopefully this provides a suitable means to accomplish smooth animation on all models of Apple II, assuming of course that accurate cycle counting is done.

Updated on February 1, 2015 by mmphosis — comments (macgui.com)

mentioned on the Retro Computing Roundtable podcast
around the 32 minute mark of Episode 93 (rcrpodcast.com)