// D1SimRes.bcpl -- resident control program for "SimGo" and "SimTest".
//	9 May 1983

get "d1.d"
manifest [ get "d1regmem.d" ]
manifest [ get "d1dmux.d" ]

external [
// OS
	DoubleAdd

// MINIT0
	@MBlock; TimeStream

// MASM
	Wss; @WssCSS; ResetsCSS

// MDATA
	@LoopCount

// MIOC
	DWns

// MOVERLAY
	FlushOverlays

// MRGN
	RemoveFromEveryTimeList

// MMENU
	PrintActionTime

// MCMD
	WnsCSSD; QuitCmdOverlay; PassiveOnly

// MGO
	@QuitF

// D1I0
	@OldDMuxTab; @DMuxTab; HWStatus

// D1ACTIONS
	@LongOne

// D1ASM
	@DoStrobe; ReadDMux; LoadDMD

// D1RES
	ReadAllRegs

// D1GO
	MStopped; OneStep; GetHMask

// D1POKE
	PassivePending

// D1SIMT
	LoadandDoInst

// D1SIMDEC
	DSimulate

// D1SIMINI
	SimAborted

// Defined here
	SimGo; SimTestAbort; SimGoAbort; SimLp
]

//SimGo is put on EveryTimeList by StartSim.  It is resident so that the
//simulation overlay can be flushed before calling PrintErrors overlay.
let SimGo(GoV) be
[	if (DMuxTab!dESTAT & GetHMask()) ne 0 do	//Real halt
	[ SimFinish(); MStopped(true)
	]
	if SimAborted do				//Control-C
	[ SimFinish(); WssCSS(", Aborted"); MStopped()
	]
	MBlock(OldDMuxTab,DMuxTab,DMUXlen)
	DoStrobe(Clock); OneStep(Control+SetRun+SetSS)
	ReadDMux()
	let NDE = DSimulate(2)
	if NDE ne 0 do					//Simulation failure
	[ SimFinish()
	  WssCSS(", "); SimEPrin(NDE); MStopped(true)
	]
	SimLoopPrint()
]


and SimGoAbort(nil,nil,nil) be SimAborted = true


//FlushOverlays to make space for the go overlay that might come in when
//MStopped is called.
and SimFinish() be
[	LoadDMD(RunEnable+(HWStatus>>HWStatus.RunControl))
	if PassivePending then PassiveOnly = true
	FlushOverlays()
]


and SimLoopPrint() be
[	DoubleAdd(LoopCount,LongOne)
	if (LoopCount!1 & #37) eq 0 do
	[ PrintActionTime(); Wss(TimeStream,", ")
	  DWns(TimeStream,LoopCount)
	]
]


and SimEPrin(NErrs) be
[	WnsCSSD(NErrs); WssCSS(" DMux errs")
]


and SimTestAbort(NErrs,nil,nil) be
[	SimFinish()
	RemoveFromEveryTimeList(QuitF); ResetsCSS()
	test NErrs eq 0
	ifso WssCSS("Mouse halt")
	ifnot SimEPrin(NErrs)
	ReadAllRegs(1)
	QuitCmdOverlay()
]


and SimLp(nil) be
[	MBlock(OldDMuxTab,DMuxTab,DMUXlen)
	LoadandDoInst()
	let E = DSimulate(2)
	if E ne 0 then SimTestAbort(E)
	SimLoopPrint()
]