.titl SpruceBandMl

; BandEnter(band,len)
; Must be called to make a new band entry official.
; New band information has been placed in the table beginning at BandFree.
; BandAvail is set to allow it to overflow by one maximum-sized entry.
; See SpruceBand for algorithm description -- this code links to microcode.

; RowRotate(inBuf, outBuf, wordsPerRow) rotates Alto resolution bit map rows
; SetupShowFonts(specs)
; SetupShowChars(specs, numChars, streamFsp) feeds parameters to show microcode
; code = ShowChars(lvC, lvBand)
;OrbitCharSize(width,height) returns number of words for char:
;		((width*height+15)/16+2+1)&(-2)

.bext BandEnter
.bext BandFree, BandAvail, BandTable, onlyOnCopy, BandFlush, CopyTable
.bext CurS, CurB, fspn, fspo, nVisibleBands, bc
.ent RowRotate, SetupShowChars, ShowChars, SetupShowFonts, OrbitCharSize
.ent FlushChars

.srel
OrbitCharSize:	.orbitCharSize
BandEnter: .BandEnter
RowRotate: .RowRotate
ShowChars: .ShowChars
SetupShowChars: .SetupShowChars
SetupShowFonts: .SetupShowFonts
FlushChars: .FlushChars
.nrel

savedPC=1
temp=2
extraArguments=3

;; ************** r... indices here match those in microcode (ShowCharsMc), and the sequences
;; ************** of register references depend on the order of static placement in SprintStatics.bj!

LOADR=71000		; R←@AC0, AC0←AC0+1
STORER =70000	; @AC0←R, AC0←AC0+1
JMPRAM = 61010

rVis = 660		; R66, nVisibleBands
rBTable = 700		; R70, BandTable
rCTable = 520		; R52, CopyTable
rUses = 640		; R64, ICCUses
rOffset = 630		; R63, ICCOffset
rBc = 620		; R62, bcM1
rEc = 610		; R61, ec
rWidth = 670		; R67, WidthPointer

rSpn = 160		; R16, fspn
rSpo = 150		; R15, fspo
rCop = 650		; R65, OnlyOnCopy

rS0 = 600		; R60, CurS0
rS1 = 570		; R57, CurS1
rB0 = 560		; R56, CurB0
rB1 = 550		; R55, CurB1

rFree = 540		; R54, BandFree
	rPData=540	; R54, in FlushChars
rAvail = 530		; R53, BandAvail

rCt = 460		; R46, ct
rC = 470		; R52, c
	rNumData=470	; R52, in FlushChars
rBand = 510		; R51, band
	rOutAddr=510	; R51, in FlushChars

rByteIdx = 450		; R45, byte index for stream access
rBase = 440		; R44, address of current data word or so
rData = 430		; R43, current data word

rP = 410		; R41, loaded externally in FlushChars
    rLen=420		; R42, entryLen, in BandEnter
	rLeftCt = 420	; R42, in FlushChars

; ***** indices into the fsp portion of a stream structure -- see FSP ******
CharPtr = 0
WordPtr = 1
Count = 2
Dirty = 3

; BandEnter(band, len)
; BandTable, CopyTable already loaded into appropriate regs.
.BandEnter:
	sta 0 1 2
	sta 1 2 2
	inc 2 0
	LOADR+rBand
	LOADR+rLen
	lda 0, .only
	LOADR+rCop
	lda 0, .bTable
	LOADR+rBTable
	LOADR+rCTable
	lda 0 .BandFree
	LOADR+rFree
	LOADR+rAvail
	lda 1 RamBandEnter
	JMPRAM;		do the BandEnter
	mov 0 1
	lda 0 .BandFree
	STORER+rFree
	STORER+rAvail
	snz 1 1
	jmp 1 3
	inc 3, 3
	sta 3, save3
	jsrii .bFlush	;BandFlush()
	0
	jmp @save3


.SetupShowFonts: 			; values that remain permanent while font is loaded
					; (except while doing dots)
	lda 0,.vis
	LOADR+rVis
	lda 0, .bTable
	LOADR+rBTable
	LOADR+rCTable
	LOADR+rUses
	LOADR+rOffset
	lda 1 @.bc
	dsz @.bc
	mov# 0, 0
	LOADR+rBc
	sta 1 @.bc
	LOADR+rEc
	LOADR+rWidth
	jmp  1,3

.SetupShowChars:	;0 is nChars, 1 => FSP portion of stream
	sta 3, 2, 2	; not the normal roles -- indices used explicitly to exhibit relationships
	sta 0, 1,2	; used below (see lines marked with ** and subsequent similar ones)
	sta 1, 3, 2	; ~~ MUST document this stuff.
	lda 0, .only
	LOADR+rCop
	sub 0,0
	sta 0, @.fspn
	sta 0, @.fspo
	lda 0, .fspn
	LOADR+rSpn
	LOADR+rSpo
	lda 0, @.CurS
	LOADR+rS0
	LOADR+rS1
	lda 0, @.CurB
	LOADR+rB0
	LOADR+rB1
	inc 2 0; ** 0 is lv 1,2 **
	LOADR+rCt
	sub 0 0
	lda 1 @3, 2	;fsp.charPtr
	sn 1 1
	mknil 0 0
	sta 0 1,2	;0 if charPtr of stream was non-zero, -1 otherwise -> byteIdx
	inc 2 0 ; **
	LOADR+rByteIdx; fsp.wordPtr
	lda 3 3, 2	;fsp
	lda 0 1 3	;address of data, more or less
	lda 1 1 2	; previously derived byteIdx determines where initial data word will be
	sub 1, 0
	sta 0 1,2
	LOADR+rData	; AC0 here is address of 1st data word
	inc 2 0; **	; AC0 here is address of address of 1st data word, to be put in base register
	LOADR+rBase
	lda 3 2, 2
	jmp 1 3

.bFree: .BandFree: BandFree
.bAvail: BandAvail
.bTable: BandTable
.cTable: CopyTable
.only: onlyOnCopy
.bFlush: BandFlush
.vis: nVisibleBands
.bc: bc
.CurS: CurS
.CurB: CurB
.fspn: fspn
.fspo: fspo
save0:	0
save1: 0
save2: 0
save3: 0
RamRowRotate: 23
RamFlushChars: 24
RamShowChars: 25
RamBandEnter: 30

.ShowChars:
	sta 3, save3
	sta 2, save2			; ShowChars microcode uses all Acs
	sta 0, save0
again:	lda 0 .BandFree
	LOADR+rFree
	LOADR+rAvail
	lda  1,RamShowChars		; ShowChars starts at RAM 25
	JMPRAM
	lda 2, save2
	mov 0 1			; return code
	lda 0 .BandFree
	STORER+rFree
	STORER+rAvail
	jsr postT
; ****** These order of these instructions must remain compatible with the MU... codes in ShowCharMc
table:	jmp done				; 0 result -- all done
	jmp range
	jmp range				; range or other errors
	jmp full				; buffer full
; ****** 
postT:	add 1 3
	jmp 0 3				;dispatch
full:	jsrii .bFlush
	0
	jmp again
done:	lda 0 .fspn
	STORER+rSpn
	STORER+rSpo
	lda 0 @.CurS
	STORER+rS0
	STORER+rS1
	lda 0 @.CurB
	STORER+rB0
	STORER+rB1
	jmp quit
range:	lda 0 save0			;address of variable to hold most recently considered char.
	STORER+rC
quit:	lda  3,save3
	mov 1 0			;result returned from microcode
	jmp 1,3


; FlushChars

; FlushChars(lv p, fsP)
; p, nextP are contiguous

.FlushChars:
	inc 3,3
	sta 3, savedPC, 2
	sta 0, save0;	lv (p, nextP)
	LOADR+rP
	inc 1 0; 	word 0 is (next out address)-1, word 1 is -(#left+1)
	sta 0, save1;	fsp stream information
	LOADR+rOutAddr; WordPtr
	LOADR+rLeftCt; Count
	lda 1 RamFlushChars	; FlushChars code in RAM
	JMPRAM
	mov 0,1	; return code, save
	lda 0, save0
	STORER+rPData ; current version of p
	STORER+rP	; next version of p, not always derivable from p
	STORER+rNumData; (#words in previous p)-1
	lda 0 save1
	STORER+rOutAddr
	STORER+rLeftCt
	mov 0,3	; fsp.Dirty
	sta 3, 0, 3	; denote current output page dirty
	mov 1,0
	jmp @savedPC, 2


; Other ml routines and mu linkages

.orbitCharSize: sta 3 savedPC,2
	mov 2,3
	mov 0,2
	lda 0,dorb
	mul		; ac0,1 ← height*width+15+3*16
	movr 0,0
	movr 1,1
	movr 0,0
	movr 1,1
	movr 0,0
	movr 1,1
	movr 0,0
	movr 1,1
	mov 1,0
	lda 1,cm2
	and 1,0		; make even number
	mov 3,2
	lda 3 savedPC,2
	jmp 1,3

dorb:	15.+(3*16.)
cm2:	177776

.RowRotate: sta	3,savedPC,2
	sta 2,save2			; never reentered!
	lda 3,extraArguments,2	;wordsPerRow
	mov 1,2			; outBuf AC0 is inBuf
	lda  1,RamRowRotate		; ROWROT starts at RAM 23
toram:	61010				;JmpRam(23)
	lda  2,save2
	lda  3,savedPC,2
	jmp 1,3

; Runtime Initialization (for GetFrame, return)

;; DCS, September 27, 1977  2:57 PM, created
;; October 18, 1978  12:23 PM, moved in a lot of band-related stuff from spruceml
;; October 19, 1978  8:55 AM, modified ShowChars interfaces to use LOADR, STORER
;; October 19, 1978  10:41 PM, lotsa bugs
;; October 23, 1978  7:13 AM, add FlushChars
;; October 24, 1978  9:58 AM, onlyOnCopy cleanups, mods -- BandEnter a lot simpler
;; 

.end