//MINIT0.BCPL First init
// This file is loaded with the program. After execution, its
// storage is added to free storage. When "Midas/I" is typed, a
// new Midas.State file is created after about 5 seconds of
// initialization. When "Midas/R" is typed, Midas
// resumes from its previous AltIO call. Otherwise, Midas restores its
// state from the existing Midas.State file.
get "streams.d"
get "altofilesys.d"
get "mdecl.d" // Need def of MaxBlockPages
external [
// OS
CallSwat; SetBlock; MoveBlock; Zero; diskKd; sysZone
fpSysDir; Allocate; Free; WriteDiskDescriptor; OpenFile
Closes; Gets; Puts; Wss; ReadBlock; WriteBlock; Endofs; Resets
PositionPage; FileLength; keys
// KEYBOARD
CreateKeyboardStream
// MIDAS
ElapsedTime; FirstStatic; LastStatic
TimeJunta; TimeLookup; TimeOutLdFP; TimeOvScan
TimeQFiles; TimeFont
// MDISP
FontP; Evec; PseudoFontVec; LineCtrlBlockPtrsVector
// MRGN
ControlV; ScreenTV; BlankS
// MINIT2
VecInit; GetHStorage; GetZStorage; MakeTVS
// State package
GetStorage; StorageInit; BeginSave; SaveStatics; Storage; EndStorage
// MTV
TVSpareTVs; TVSpareTVec
// MSYM
TVtoString; @StringVec
// MCMD
NPrograms; ProgramAct; NQuickFiles; FileBlock
// Overlay package
OverlayScan
// MDI
LookupEntries
// Machine dependent
InitHardware1; ScreenHeight; ScreenWidth
//Defined here
MidasFP; MidasRFP; BlockStoreFP; FixUpFP; ErrsFP; mdsInitFP
StateStream; ZoneErr; Init0
]
static [
MidasFP; MidasRFP; BlockStoreFP; FixUpFP; ErrsFP; mdsInitFP
StateStream
StackSize = #4400; SysZoneSize = #5000
ZoneErr = 0 //0 disables checking
]
manifest [ NFNames = 8 // Number of names being looked up
NumOverlays = 8 // Max number of overlays (was 7 on
// 10 February 77)
OvTSize = 5*NumOverlays+25
MaxQuickFiles = 60 // Maximum no. files in table
]
let Init0(CFA,Switch) = valof
[ StorageInit(FirstStatic,LastStatic,SysZoneSize,StackSize)
keys = CreateKeyboardStream()
ElapsedTime(lv TimeJunta)
InitHardware1()
//Build a table of file names to be looked up in the System directory
let SysDirStream = OpenFile(0,ksTypeReadOnly,wordItem,0,fpSysDir)
let ProgramsFP,FontFP = nil,nil
let NV,SV = vec NFNames,vec NFNames
let PrVec = GetStorage(lDV*NFNames)
//Names should be upper case so that they will compare eq later
SetupFPN(lv MidasFP,NV,SV,0,PrVec,"MIDAS.STATE",-1)
SetupFPN(lv BlockStoreFP,NV,SV,1,PrVec,"MIDAS.SYMTAB",MaxBlockPages)
SetupFPN(lv FixUpFP,NV,SV,2,PrVec,"MIDAS.FIXUPS",-1)
SetupFPN(lv ErrsFP,NV,SV,3,PrVec,"MIDAS.ERRORS",-1)
SetupFPN(lv MidasRFP,NV,SV,4,PrVec,"MIDAS.RESUME",-1)
SetupFPN(lv ProgramsFP,NV,SV,5,PrVec,"MIDAS.PROGRAMS",0)
SetupFPN(lv FontFP,NV,SV,6,PrVec,"GACHA10.AL",0)
SetupFPN(lv mdsInitFP,NV,SV,7,PrVec,"MIDAS.MIDAS",0)
// Use storage at the low end of the block used by GetStorage
let Undefined = LookupEntries(SysDirStream,NV,PrVec,NFNames,
true,Storage,EndStorage-Storage)
if Undefined ne 0 do
[ for I = 0 to NFNames-1 do
[ if PrVec!(lDV*I) eq 0 then
CreateFile(NV!I,SV!I,PrVec+(lDV*I))
]
]
ElapsedTime(lv TimeLookup)
//First part of MDISP init
Evec = GetStorage(EvecSize+1)
PseudoFontVec = GetStorage(PFVecSize+1)
LineCtrlBlockPtrsVector = GetStorage(ScreenHeight)-1
//First part of init for MRGN
let SSize = (ScreenWidth rshift 1)+1
BlankS = GetStorage(SSize); SetBlock(BlankS,20040B,SSize)
BlankS>>lh = ScreenWidth
ControlV = GetHStorage(ScreenHeight)
ScreenTV = GetHStorage(ScreenHeight)
for I = 1 to ScreenHeight do
[ ControlV!I = GetZStorage((ScreenWidth+1) rshift 1)
]
BeginSave() //Initialize for SaveState/RestoreState
if Switch eq 0 do //No switch = RestoreState
[ Closes(SysDirStream)
StateStream = OpenFile(NV!0,ksTypeReadOnly,wordItem,0,MidasFP)
resultis false
]
switchon Switch & not 40B into
[
case $R: Closes(SysDirStream)
StateStream = OpenFile(NV!4,ksTypeReadOnly,wordItem,0,MidasRFP)
resultis false
default: CallSwat("Bad switch")
case $I: endcase
]
OverlayScan(lv CFA>>CFA.fp,GetStorage(OvTSize),OvTSize,
lv CFA>>CFA.fa)
ElapsedTime(lv TimeOvScan)
//Init for MTV and MSYM needed by BuildPrograms
MakeTVS(lv TVSpareTVs,lv TVSpareTVec)
StringVec = GetStorage(129)
BuildPrograms(SysDirStream,ProgramsFP); Closes(SysDirStream)
ElapsedTime(lv TimeQFiles)
let FontStream = OpenFile(0,ksTypeReadOnly,wordItem,0,FontFP)
let SizeFont = (FileLength(FontStream)+1) rshift 1
PositionPage(FontStream,1); FontP = GetStorage(SizeFont)+2
ReadBlock(FontStream,FontP-2,SizeFont); Closes(FontStream)
ElapsedTime(lv TimeFont)
SaveStatics(lv StringVec)
StateStream = OpenFile(NV!0,ksTypeWriteOnly,wordItem,
verLatestCreate,MidasFP)
resultis true
]
and SetupFPN(lvFP,NV,SV,X,PrVec,Name,Size) be
[ NV!X = Name; SV!X = Size
rv lvFP = PrVec+(offset DV.fp/16)+lDV*X
]
and CreateFile(Name,npgs,FileDV) be
[ if npgs eq 0 then CallSwat("File doesn't exist: ",Name)
Zero(FileDV,lDV)
if npgs eq -1 then return //-1 = Optional file
let FileFP = FileDV+(offset DV.fp/16)
let BTsize = diskKd>>KD.diskBTsize
let BitTable = lv (diskKd>>KD.diskBitTable)
let bt = Allocate(sysZone,BTsize+1)
MoveBlock(bt,BitTable,BTsize) //Copy the bit table
bt!BTsize = -1
let best = 0
let maxp, max, cur = nil, 0, 0
for i = 0 to BTsize do
test bt!i eq 0
ifso cur = cur+1
ifnot
[ if cur > max then maxp, max = i-cur, cur
cur = 0
]
if max*16 ge npgs then best = maxp
let X = BitTable!(best-1)
if best ne 0 do
[ SetBlock(BitTable,-1,best-1) //Allocate pages below best
BitTable!(best-1) = X % (-X) //Use bits from previous word
diskKd>>KD.bitTableChanged = true //So it won't be read
]
let scratch = vec #400 //Now write the file
let newst = OpenFile(Name,ksTypeWriteOnly,wordItem,verNew,FileFP)
if newst ne 0 then
[ for i = 1 to npgs do WriteBlock(newst,scratch,#400)
Closes(newst)
]
if best ne 0 do
[ MoveBlock(BitTable,bt,best-1) //Restore bit table
BitTable!(best-1) = X % ((BitTable!(best-1)) & not (X % -X))
diskKd>>KD.bitTableChanged = true
WriteDiskDescriptor()
]
Free(sysZone,bt)
if newst eq 0 then CallSwat("CreateFile failed",Name)
]
//BuildPrograms reads "Midas.Programs" and treats the names there
//as follows:
// a name containing no "." is made into a "Run-Program" menu
// item if name.midas exists, and both name.midas and name.mb
// are entered into the QuickOpenFile table;
// if the name contains a ".", it is only entered into the QuickOpenFile
// table.
//In either case no entry is made in the QuickOpenFile table unless the
//file exists.
and BuildPrograms(SysDirStream,ProgramsFP) be
[ let S = OpenFile(0,ksTypeReadOnly,charItem,0,ProgramsFP)
if S eq 0 then CallSwat("Bug in LookupEntries")
let NV = vec MaxQuickFiles
//The algorithm below puts pointers to ".Midas" files at the low end
//of NV and to ".mb" and other files at the high end
let midasPtr,mbPtr = 0,MaxQuickFiles
while not Endofs(S) do
[ Resets(TVSpareTVs); let DotFlag = false
until Endofs(S) do
[ let C = Gets(S)
switchon C into
[
case $,: case $ : case 15B: case 12B: break //Separators
case $.: DotFlag = true
default: if (C < 40B) % (C > 176B) then
CallSwat("Illegal chars in Midas.Programs")
Puts(TVSpareTVs,C); loop
]
]
if TVSpareTVec!0 eq 0 then loop //Just separators
if not DotFlag do
[ let NameEnd = TVSpareTVec!0; Wss(TVSpareTVs,".MIDAS")
NV!midasPtr = MoveString(TVtoString(TVSpareTVec))
midasPtr = midasPtr+1; TVSpareTVec!0 = NameEnd
Wss(TVSpareTVs,".MB")
]
mbPtr = mbPtr-1
NV!mbPtr = MoveString(TVtoString(TVSpareTVec))
if mbPtr le midasPtr then
CallSwat("Too many file names in Midas.Programs")
loop
]
//Now pack NV for LookupEntries
let NFNames = midasPtr+MaxQuickFiles-mbPtr
MoveBlock(NV+midasPtr,NV+mbPtr,MaxQuickFiles-mbPtr)
let PrVec = vec MaxQuickFiles*lDV //For DV's
let Undefined = LookupEntries(SysDirStream,NV,PrVec,NFNames,
true,Storage,EndStorage-Storage)
NQuickFiles = NFNames - Undefined
let FBsize = NQuickFiles*lDV; FileBlock = GetZStorage(FBsize)
ProgramAct = GetZStorage(midasPtr) //Table of names converted
//to table of Actions by MCMD
let FBPtr,Progptr = 0,0
for I = 0 to NFNames-1 do
[ let DV = PrVec + (I*lDV)
if DV!0 ne 0 do
[ let Str = NV!I; let StrSize = (Str>>lh rshift 1)+1
DV!0 = Str; MoveBlock(FileBlock+FBPtr,DV,lDV); FBPtr = FBPtr+lDV
if FBPtr > FBsize then CallSwat("Bug in LookupEntries")
if I < midasPtr do
[ let PStr = GetStorage(StrSize-3) //Truncate ".Midas"
MoveBlock(PStr,Str,StrSize-3)
PStr>>lh = Str>>lh - 6
ProgramAct!Progptr = PStr; Progptr = Progptr+1
]
]
]
NPrograms = Progptr
]
and MoveString(String) = valof
[ let Size = (String>>lh rshift 1)+1
let DestStr = GetStorage(Size)
MoveBlock(DestStr,String,Size)
resultis DestStr
]