// Midas.bcpl -- Main program
// Last edited: 2 June 1981
get "altofilesys.d"
get "streams.d"
get "mdecl.d"
get "mcommon.d"
external [
// OS
Resets; TruncateDiskStream; Closes; Puts; GetCompleteFa; JumpToFa
CreateDiskStream; lvUserFinishProc; DoubleAdd; Timer; MyFrame
GotoLabel
// MASM
Wss; @MBlock; ErrorProtect; DoubleNeg; DoubleDiv
// MDATA
LastTimer; TimeStart
// MSYM
StreamFromTextName
// MTXTBUF
TxtBNewChar; InputTextBuffer
// MIOC
DWns; Wns
// MOVERLAY
KillOverlays
// MDISP
FinishDisplay; SetDisplay
// MRGN
DriverLoop
// MMENU
ExecuteTextCmdStream; EscAction; CFileStream
// MCMD
CmdDoRC; DisplayError; RunProgMenu; StartCmdOverlay
// MCMDOV
TextCmdOutStream
// MGO
StartSetup; HaltWait
// MINIT0
Init0; TimeStream; MStatus
// MINIT1
Init1
// MINIT2
Init2
// ACTIONS
NoopAction
// Machine dependent
FinishHardware
// Defined here
Nmidas; InitRes; StartTimer; ElapsedTime; PrintTime; MidasFinish
MidasSwat
TopFrame; Resume; BegCF; @NestedCFiles; lvFinishProc; Initialized
TimerGoing; SysZoneSize; StackSize; StateFileSize
TimeJunta; TimeLoadRam; TimeJunkInit; TimeLookup1; TimeCreateFiles
TimeOvScan; TimeLookup2; TimeQFiles; TimeMSYM; TimeInit1
TimeLoad; TimeSwapInit2; TimeScreenInit; TimeRCActions
TimeInitHardware; TimeCmdMenu1; TimePaintRegions; TimeInit2Menu
TimeCmdMenu2; TimeLoadOvl; TimeComCM; TimeFinish
CodeOS; StorageSize; BBblockSize; AvailBlockSize; FinalStorage
]
static [
Initialized = false; TimerGoing = false; TopFrame; lvFinishProc
@NestedCFiles = 0
// Initialization statistics for DoradoMidas on 27 October 79
TimeJunta //(0.011) Runtime after Junta
TimeJunkInit //(0.020) Assorted GetStorage calls
TimeLoadRam //(0.178) After InitHardware1 (LoadRam primarily)
TimeLookup1 //(0.637) After building FP's for Midas files
//**Midas/I only**
TimeOvScan // (2.385) After OverlayScan
TimeCreateFiles //(.002,4.613) After creating auxiliary files
TimeLookup2 // (0.565) After 2nd LookupEntries call
TimeQFiles // (1.130) Build FP's from Midas.Programs &
// Midas.UserPrograms
TimeMSYM // (0.198) MSYM init, swap in Load overlay
TimeInit1 // (0.155) Make MPD, MDFS, RGN structures
TimeLoad // (0.992) Open Midas.Midas + Ld in command file
// (.13 slower if LOADER.MB not dumped)
TimeRestoreState //(4.707) Rest of Midas.Midas on Midas/I -or-
//(3.143) Rest of Midas.Midas if temp files exist -or-
//(0.387) RestoreState
TimeSwapInit2 //(0.166) Loading Init2 overlay
TimeScreenInit //(0.008) Init ScreenTV, ControlV, and display
TimeRCActions //(0.003) Create RdCmds and RunProg actions
TimeComCM //(0.181) Reading Com.CM
TimeInitHardware //(1.399) InitHardware()
TimeCmdMenu1 //(0.042) Forming regular command menu
TimePaintRegions //(0.057) Paint non-MPD lines
//**Init2 menu only (select Dorado)**
TimeInit2Menu // (indeterminate)
TimeCmdMenu2 // (0.044) Forming regular command menu
TimeLoadOvl //(0.495) Loading overlays into space avilable
TimeFinish //(18.131) Midas/i and create temporary files -or-
//(11.293) Midas/i, temp files already exist -or-
//( 3.799) Total time when not Midas/i
TimeUpdate //(0.172) Runtime at call to DriverLoop
//Screen update times determined manually
// (0.106) in ClearAndScanConvert
// (0.097) in FormMPDMenu & below
// (0.071) in MarkMenus & below
// (0.069) in DatatoStream & below
// (0.037) in MPDEveryTime
// (0.012) in MGetxx
// Storage statistics
CodeOS // (21130) OS after Junta to levStreams
// (was 25600 when Junta'd to levKeyboard)
//StackSize large enough for SimGo action to be called from a command file.
StackSize = #5000
StorageSize //(54271) Original size excluding stack and init code
//SysZoneSize = #6400 is enough for #5100 words of SimGo overlay and open
//command and output files. Other worst case is two open files during
//Ld, plus open command and output files.
SysZoneSize = #6400
BBblockSize //(26330) Bit buffers
AvailBlockSize //(20010) OverlayZone (part of bit buffers)
//(1065 words/line at ScreenWidth eq 76)
FinalStorage //(12077) Free storage available for additional FP's in
//Midas.Programs and Midas.UserPrograms & Midas additions;
//used meanwhile for overlays made resident and symbols.
StateFileSize //(15236) Words on Midas.RunProg or Midas.Dtach
// TimeFont (0.261) Reading gacha10.al **no longer do this**
// BBWait (in MDATA) is the loop count waiting for bit buffers (~ 562)
]
manifest [ MaxNestedCFiles = 8 ]
let Nmidas(Layout,userParams,CFA) be
[ StartTimer()
Init0(Layout,userParams,CFA) //Never returns
]
//Enter with GotoLabel from Init0A--never returns
and InitRes(nil) be
[ TopFrame = MyFrame()
let CFileStack = vec lCFA*MaxNestedCFiles
//Init1 returns only on Midas/I; otherwise, does RestoreState(..) to
//"Resume". CFileStack is used to return the FP for MIDAS.MIDAS
//and as TempStorage for Init0B(..).
Init1(CFileStack)
//Execute MIDAS.MIDAS comfile which must leave display off and not activate
//hardware interface. MIDAS.MIDAS must write two state files:
//MIDAS.DTACH for starting Midas from the Exec or from a Dtach;
//MIDAS.RUNPROG for reinitializing on RunProg.
ErrorProtect(lv ExecuteTextCmdStream,
CreateDiskStream(CFileStack+(offset DV.fp/16),
ksTypeReadOnly,charItem))
Resume: ElapsedTime(lv TimeRestoreState)
//Display is off here, returns non-0 if com-file on input line.
let CFS = Init2(); KillOverlays()
//If the machine is running at this time, wait for halt, abort, or Dtach.
if MStatus>>MStatus.MachRunning ne 0 do
[ SetDisplay(false) //Display on
StartCmdOverlay(lv StartSetup,HaltWait)
SetDisplay(true) //Display off
]
//On initialization, execute command file from Exec's command line; on
//RunProg, execute command file named on input text line or in menu.
if CFS then ErrorProtect(lv CmdDoRC,lv RunProgMenu)
//CmdDoRC jumps here with GotoLabel, ensuring that the stack won't get too
//deep during nested command files. An open stream exists for only one
//command file at-a-time; its callers are remembered on CFileStack.
BegCF: test InputTextBuffer!0 ne 0 //Start comfile
ifso
[ test CFileStream eq 0
ifso SetDisplay(true) //Display off for first comfile
ifnot //Push previous comfile
[ test NestedCFiles ge MaxNestedCFiles
ifso
[ ErrorProtect(lv DisplayError,"Comfile nesting > 8 levels")
CFS = CFileStream; goto(RetCF)
]
ifnot
[ GetCompleteFa(CFileStream,CFileStack+(NestedCFiles*lCFA))
NestedCFiles = NestedCFiles+1
Closes(CFileStream)
]
]
CFileStream = -1
//StreamFromTextName will ErrorExit(..) with the display on if any error
//occurs, resulting in a call on DisplayError because CFileStream is ne 0
CFS = ErrorProtect(lv StreamFromTextName,InputTextBuffer,
".MIDAS",ksTypeReadOnly,charItem)
]
ifnot CFS = CFileStream //Aborted RunProg or RdCmds
RetCF: CFileStream = 0
if CFS ne 0 then ExecuteTextCmdStream(CFS)
TxtBNewChar(#177)
if NestedCFiles > 0 do //Pop comfile from stack & continue
[ NestedCFiles = NestedCFiles-1
let CFA = CFileStack+(NestedCFiles*lCFA)
CFS = CreateDiskStream(lv CFA>>CFA.fp,ksTypeReadOnly,charItem)
JumpToFa(CFS,lv CFA>>CFA.fa)
goto(RetCF)
]
PrintComputeTime()
SetDisplay(false); ElapsedTime(lv TimeUpdate)
EscAction = NoopAction
DriverLoop(); finish
]
and MidasFinish() be
[ if TextCmdOutStream ne 0 do
[ TruncateDiskStream(TextCmdOutStream); Closes(TextCmdOutStream)
]
FinishDisplay(); FinishHardware()
@lvUserFinishProc = lvFinishProc
]
//Puts Timer in TimeStart and LastTimer vectors
and StartTimer() be
[ Timer(TimeStart)
//Don't use MBlock here because not initialized at first call
LastTimer!0,LastTimer!1 = TimeStart!0,TimeStart!1
TimerGoing = true
]
//TimeV!0←low-order word of Timer-LastTimer, high-order word returned.
//LastTimer←Timer.
and ElapsedTime(TimeV) = valof
[ let X = vec 1; MBlock(X,LastTimer,2); DoubleNeg(X)
Timer(LastTimer); DoubleAdd(X,LastTimer)
TimeV!0 = X!1; resultis X!0
]
//Timer covers about 1200 hours
and PrintComputeTime() be
[ MBlock(LastTimer,TimeStart,2)
let Y = vec 1; Y!0 = ElapsedTime(Y+1)
TimeFinish = Y!1 //Single-precision result in TimeFinish
PrintTime(Y)
TimerGoing = false
]
//Prints the elapsed time in double-precision V on TimeStream
and PrintTime(V) be
[ let TimeParse = vec 3
DoubleAdd(V,table [ 0; 5 ] ) //For rounding to 100ths
TimeParse!3 = DoubleDiv(V,1000)/10 //V←seconds, excess 100ths
TimeParse!2 = DoubleDiv(V,60) //V←minutes, excess sec
TimeParse!1 = DoubleDiv(V,60) //V←hours, excess min
TimeParse!0 = DoubleDiv(V,24) //V←days, excess hrs
Resets(TimeStream); Wss(TimeStream,"Time: ")
let Printing = false
if V!1 ne 0 do
[ Wns(TimeStream,V!1,0,10); Wss(TimeStream," days ")
Printing = true
]
for I = 0 to 3 do
[ if (TimeParse!I ne 0) % (I eq 2) then Printing = true
if Printing do
[ DWns(TimeStream,TimeParse+I,16,0,10,2,$0)
let Char = table [ $:; $:; $.; 0 ] !I
if Char ne 0 then Puts(TimeStream,Char)
]
]
]
and MidasSwat(ErrNo,P1,P2,P3,P4,P5) be
[ (table [ #77403; #1401 ] )("Midas.Errors",lv ErrNo)
]