// LocalVMemInit.bcpl - does VMem setup for MainInit
// Last change October 6, 1982  6:44 PM by Bill van Melle
// Last change July 20, 1982  10:33 PM by Bill van Melle

// everything from here on gets flushed after /I is finished

	get "LispBcpl.decl"
	get "Stats.decl"
	get "VMem.decl"
	get "AltoDefs.d"
	get "AltoFileSys.d"
	get "Streams.d"

external [	// procedures defined here
	LocalInitVmem; CheckIPage

	GiveUp; ShortStack

		// O.S. procedures
	Closes; Endofs; ReadBlock; OpenFile; PositionPage
	CallSwat; OpenFileFromFp; WriteBlock

		// statics
	VmemStream; MinLispForRam; RamVersion; haveUcode; SysinName
	]

manifest [	// same as in RemoteVmemInit.bcpl
	firstMouseX = 260
	firstMouseY = 50
	lastMouseY = 800
	]

let LocalInitVmem (SYSINid, VMEMid) be
 [
 let sst = OpenFile(0, ksTypeReadOnly, 0, 0, SYSINid)
 unless sst do GiveUp("Can't find sysin file ", SysinName)
 VmemStream = OpenFileFromFp(VMEMid)
 unless VmemStream do GiveUp("Can't open Lisp.virtualmem")

 @mouseX, @mouseY = firstMouseX, firstMouseY

//   We can use the rest of the space between the end of the code and the
//   current end of stack for buffers.  This space will eventually go to
//   the assorted allocations, but for now it is empty.

 let Buffers = (@StackEnd+WordsPerPage-1) & not (WordsPerPage-1)
					// first buf page, page-aligned
 let LowStackPage = ShortStack(1000)	// allow 1000 words of stack
 let bsize = LowStackPage - Buffers		// size of buffer region
 if bsize ls WordsPerPage
    then CallSwat("No buffers for SYSIN")
 let OldLowStack = @StackEnd		// save old low stack
 @StackEnd = LowStackPage		// enforce stack end in read

// figure out how big the sysout is so we can move cursor appropriately

 PositionPage (sst, 0)
 ReadBlock (sst, Buffers, WordsPerPage)		// read leader page
 let sysPages = Buffers>>LD.hintLastPageFa.pageNumber
 let mouseInc = 0
 if (sysPages gr 600) & (sysPages ls 10000)		// plausible file size
    then [
	 let nbufs = bsize / WordsPerPage
	 sysPages = (sysPages+nbufs-1) / nbufs	// number buffers full
	 mouseInc =  ((lastMouseY-firstMouseY) lshift 4) / sysPages
	 ]
 let mouseOff = mouseInc
		// thus the mouse crawls down screen as we read.
		// mouseInc is 2↑4 times amount to move per buffer full
		// mouseOff = mouseInc*pgno

//   Restore SavedVMEMstate from the InterfacePage
 PositionPage(sst, FirstVmemBlock)
 PositionPage(VmemStream, FirstVmemBlock)
 ReadBlock(sst, Buffers, WordsPerPage)
//   First page of Buffers now has InterfacePage of sysin - write it into vmem
 CheckIPage(Buffers)
 WriteBlock(VmemStream, Buffers, WordsPerPage)

//   now read the pages off the file and into vmem - the entries in
//   the page maps on the file have the correct vmem address already
 until Endofs(sst) do
      [ let wordsRead = ReadBlock(sst, Buffers, bsize)
	WriteBlock(VmemStream, Buffers, wordsRead)
	@mouseY = firstMouseY + (mouseOff rshift 4)
	mouseOff = mouseOff + mouseInc
      ]
 Closes(sst)
 Closes(VmemStream); VmemStream = 0
 @StackEnd = OldLowStack			// restore previous stack end
 ]

and CheckIPage(buffer) be
[	// checks the critical items in buffer, a copy of the Interface
	// page before it gets written into the vmem
  // Key check - verify file is valid and complete
  if @(buffer+IFPKey) ne IFPValidKey
     then GiveUp(@(buffer+IFPKey) eq (not IFPValidKey) ?
                      "Can't resume: Inconsistent VMem file " ,
                      "Invalid or obselete Lisp VMem ", SysinName)

  // unless haveUcode do return
  let LispV = @(buffer+IFPLVersion)
  unless LispV ge MinLispForRam
      do GiveUp("Sysout too old for this microcode")
  unless LispV ge MinLispForBcpl
      do GiveUp("Sysout too old for this Lisp.Run")
  unless RamVersion ge @(buffer+IFPMinRVersion)
      do GiveUp("Microcode too old for this sysout")
  unless BcplVersion ge @(buffer+IFPMinBVersion)
     then GiveUp("Lisp.Run too old for this sysout")

]