// RSilBanks.bcpl 
 

get "AltoDefs.d"
get "Sil.defs"

external		// incoming procedures
	[
	// OS
	BitBlt
	]

external		// incoming statics
	[
	// OS
	AltoVersion
	lvSwatContextProc
	]


external		// outgoing 
	[
	nBanks
	]

static		// statics defined here
	[
	nBanks = 0
	]

manifest
	[
	BankRegs=#177740
	emulator=0
	dwt=#11
	lnrasterwidth=9
	rasterwidth=1 lshift lnrasterwidth
	]

structure BANK [ blank bit 12; norm bit 2; alt bit 2 ]

let SetXM(bank) = valof
	[
	// default is quit if this is a non-XM Alto
	// if upper memory has not already been initialized, then try to do so
	if nBanks eq 0 then InitBanks()
	if nBanks ls bank then 
			 [ CallSwat("This is not an XM Alto.","Type any char to exit."); finish ]
	resultis true
	]



and InitBanks()=valof
	[
	// Returns zero if this is a non-XM Alto, or 1 through 4 depending on the
	// number of (contiguous) memory banks present.  As a side-effect, corrects
	// parity in all banks (>0) that are present.
	if AltoVersion<<VERS.eng ne 3 resultis 1  // An XM Alto is an "Alto 3"
	nBanks=4
	@activeInterrupts=@activeInterrupts & #177776  // Disable parity interrupt
	let XM = @BankRegs
	if XM ne #177761 then @BankRegs = #177761	// CallSwat("XM Init Problem") 
	let save=BankRegs!emulator
	for bank=1 to 3 do
	   [
	   BankRegs!emulator=bank
	   xmstore(0, #125252); let r1=xmload(0)
	   xmstore(0, #52525); let r2=xmload(0)
	   if r1 ne #125252 % r2 ne #52525 then
	      [ nBanks=bank; break ]
	   xmzero(0,#177000,bank)	// DoubleBlt(0, 0, #177000, bank lshift 2)
	   ]
	BankRegs!emulator=save
	@wakeupsWaiting=@wakeupsWaiting & #177776  // Flush pending parity interrupt
	@activeInterrupts=@activeInterrupts % 1  // Reenable parity interrupt
	resultis nBanks
	]


and xmzero(addr,count,bank) be
	[
	// zero count words starting at addr
	let save=BankRegs!emulator
	bank=bank<<BANK.alt
	let function=#14		// replace with gray block
	function<<BBT.dBank=bank ne 0
	BankRegs!emulator=bank

	// define width and height of blocks
	let height=count rshift lnrasterwidth
	let remainder=count & (rasterwidth-1)

	// set up bitblt table
	let BBTable=vec lBBT
	BBTable=(BBTable+1)&(-2)
	Zero(BBTable,lBBT)
	BBTable>>BBT.function=function
	BBTable>>BBT.dbca=addr
	BBTable>>BBT.dbmr=rasterwidth
	BBTable>>BBT.gray↑0=0
	BBTable>>BBT.gray↑1=0
	BBTable>>BBT.gray↑2=0
	BBTable>>BBT.gray↑3=0

	// if more than rasterwidth words then do a block
	if height then
		[
		BBTable>>BBT.dw=rasterwidth*16
		BBTable>>BBT.dh=height
		BitBlt(BBTable)
		]

	// if any left over then do one line
	if remainder then
		[
		BBTable>>BBT.dty=height
		BBTable>>BBT.dw=remainder*16
		BBTable>>BBT.dh=1
		BitBlt(BBTable)
		]

	// restore the bank registers
	BankRegs!emulator=save
	]


and xmload(addr) be
	[
	xmload=table
		[
		#105000	// mov 0 1
		#61025	// #61025			; xmlda -- ac0 ← @ac1
		#1401	// jmp 1 3
		]
	xmload(addr)
	]

and xmstore(addr,value) be
	[
	xmstore=table
		[
		#41002	// sta 0 2 2
		#121000	// mov 1 0
		#25002	// lda 1 2 2
		#61026	// #61026			; xmsta -- @ac1 ← ac0
		#1401	// jmp 1 3
		]
	xmstore(addr,value)
	]