// ConvertUtils.bcpl -- utilities for scan conversion

//  errors 900

get "PDInternals.d"
get "PDConvert.d"
get "AltoDefs.d"

// outgoing procedures
external
	[
	GetBBT
	PutBBT

	LoadRead
	LoadReadBlock
	LoadWriteBlock
	LoadWrite

	XMInit
	XMFinish
	XMRead
	XMWrite
	XMReadBlock
	XMWriteBlock

	UMax
	UMin
	]

// incoming procedures
external
	[
//PDPRINT
	FSGetX
	FSPutZ
	PDError
//PDML
	BitBLT
	Zero
	MoveBlock
	]

// incoming statics
external
	[
	UseXM
	LoadBase
	]

// internal statics
static
	[
	xmr
	xmw
	]

//Prepare BitBLT tables

let GetBBT() = valof
[
	let t=FSGetX(lBBT+2)
	let u=(t+1)&(-2)
	Zero(u, lBBT)
	u!lBBT=(t ne u)		//remember whether to decrement
	resultis u
]

and PutBBT(lvt) be
[
	let t=@lvt
	if t!lBBT then t=t-1
	FSPutZ(lv t)
	@lvt=0
]


//	LoadRead(loadAddr) -- reads a single word
//	LoadWrite(loadAddr, val) -- writes a single word
// LoadReadBlock(loadAddr, addr) -- reads count words
//	LoadWriteBlock(loadAddr, addr, count) -- writes count words

and LoadRead(p) = valof
[
	resultis (UseXM? XMRead(p+LoadBase),p!LoadBase)
]

and LoadWrite(p, val) be
[
	test UseXM then XMWrite(p+LoadBase, val)
		or p!LoadBase=val
]

and LoadReadBlock(p, addr, count) be
[
	test UseXM then
		XMReadBlock(p+LoadBase, addr, count)
	or	MoveBlock(addr, p+LoadBase, count)
]

and LoadWriteBlock(p, addr, count) be
[
	test UseXM then
		XMWriteBlock(p+LoadBase, addr, count)
	or	MoveBlock(p+LoadBase, addr, count)
]
//XM routines

and XMInit() = valof
[
	let BBInit(t) be
	[
		t>>BBT.sType=sBM
		t>>BBT.op=fReplace
		t>>BBT.dbmr=#77777
		t>>BBT.dh=1
		t>>BBT.sbmr=#77777
	]
	xmr=GetBBT()
	xmw=GetBBT()
	xmr>>BBT.sBank=1
	xmw>>BBT.dBank=1
	BBInit(xmr)
	BBInit(xmw)

//Now see if XM useable
	let version=(table [ #61014; #1401 ] )()
	UseXM=(UseXM ne 0 )&(version<<VERS.eng eq 3)
	let j=nil
	if UseXM then
		[
		bankRegs!0=1		//Emulator XMAR uses bank 1
		j=XMRead(1000)
		XMWrite(1000, 0)
		if XMRead(1000) ne 0 then UseXM=false
		]
	if UseXM then
		[
		XMWrite(1000, -1)
		if XMRead(1000) ne -1 then UseXM=false
		XMWrite(1000, j)
		]
	resultis UseXM
]

and XMFinish() be
[
	PutBBT(lv xmr)
	PutBBT(lv xmw)
]

and XMReadBlock(xmaddr, buf, count) = valof
[
	unless UseXM then PDError(900)
	xmr>>BBT.sbca=xmaddr
	if count ugr (#77777 rshift 4) then PDError(901)
	xmr>>BBT.dw=count lshift 4
	xmr>>BBT.dbca=buf
	BitBLT(xmr)
]

and XMWriteBlock(xmaddr, buf, count) = valof
[
	unless UseXM then PDError(900)
	xmw>>BBT.dbca=xmaddr
	if count ugr (#77777 rshift 4) then PDError(901)
	xmw>>BBT.dw=count lshift 4
	xmw>>BBT.sbca=buf
	BitBLT(xmw)
]

and XMRead(xmaddr) = valof
[
	let res=nil
	XMReadBlock(xmaddr, lv res, 1)
	resultis res
]

and XMWrite(xmaddr, val) be
[
	XMWriteBlock(xmaddr, lv val, 1)
]
// UMax, UMin

and UMax(a,b) = ((a ugr b)? a,b)

and UMin(a,b) = ((a ugr b)? b,a)

//and LongCardToDouble(p) be
//[
//	let h=p>>LongCard.high
//	let l=p>>LongCard.low
//	p!0=h
//	p!1=l
//]