// Gateway.bcpl -- Alto I voice gateway
// Last modified June 7, 1983  10:08 AM by Taft

get "Pup0.decl"
get "Pup1.decl"
get "SysDefs.d"
get "AltoDefs.d"

external
[
// outgoing procedures
Gateway; GatewayFinish

// incoming procedures
InitGateway; HaltGateway
CallContextList; Enqueue; SetAllocation
AddToZone; Allocate; Free; ResetTimeServ
Junta; OsFinish; Dismiss; StartIO

// outgoing statics
versionText

// incoming statics
pbiFreeQ; lenPBI; ndbQ; socketQ; dPSIB; numNets
sysZone; ctxQ; EventVector; lvAbortFlag
]

static versionText

manifest
[
XMax = 606-16
YMax = 808-16
]

//----------------------------------------------------------------------------
let Gateway() be Junta(levDirectory, AfterJunta)
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
and AfterJunta() be
//----------------------------------------------------------------------------
[
versionText = "Alto BCPL Gateway of June 7, 1983"
InitGateway()
AddToZone(sysZone, InitGateway, sysZone-InitGateway)

// turn all remaining storage into pbis except for a small chunk
let pbiCount = 0
let freeSlop = Allocate(sysZone, 5000)
   [
   let pbi = Allocate(sysZone, lenPBI, true)
   if pbi eq 0 break
   Enqueue(pbiFreeQ, pbi)
   pbiCount = pbiCount+1
   ] repeat
Free(sysZone, freeSlop)

// fix allocations to reflect real number of pbis
pbiCount = pbiCount-numNets
let fakeSoc = dPSIB - offset PupSoc.psib/16
SetAllocation(fakeSoc, pbiCount, pbiCount-1, pbiCount-1)
let soc = socketQ!0
while soc ne 0 do
   [  //update allocations in all sockets
   SetAllocation(soc, pbiCount, pbiCount-1, pbiCount-1)
   soc = soc!0
   ]
let ndb = ndbQ!0
while ndb ne 0 do
   [  //update gateway allocations in ndbs
   ndb>>NDB.numGPBI = pbiCount rshift 1
   ndb = ndb!0
   ]

ResetTimeServ()

// AfterJunta (cont'd)

// main loop:
@lvAbortFlag = @lvAbortFlag +1
   [
   // track the mouse
   if @mouseX ls 0 then @mouseX = 0
   if @mouseX gr XMax then @mouseX = XMax
   @cursorX = @mouseX
   if @mouseY ls 0 then @mouseY = 0
   if @mouseY gr YMax then @mouseY = YMax
   @cursorY = @mouseY

   // check the keyboard
   if (kbdAd!3 & 177577b) ne 177577b then
      [
      // check for shift-swat
      if kbdAd!2 eq 177677b & (kbdAd!3 & 177577b) eq 177573b then
         [ HaltGateway(); OsFinish(fcAbort) ]

      // some other key -- flash the screen to say we are alive
      (@displayListHead)>>DCB.background = 0  //white
      Dismiss(1)
      (@displayListHead)>>DCB.background = 1  //black
      ]

   // run the contexts
   CallContextList(ctxQ!0)
   ] repeat
]

//----------------------------------------------------------------------------
and GatewayFinish(code) be
//----------------------------------------------------------------------------
[
Dismiss(500)
if code eq 1000 then  //restart
   [
   // assume user.cm invokes Gateway.run on eventBooted
   let ev = EventVector
   while ev!0 ne 0 do ev = ev + ev>>EVM.length
   if ev-EventVector+1 ls EventVector!1 then
      [
      ev>>EVM.type = eventBooted
      ev>>EVM.length = 1
      ev!1 = 0
      ]
   ]

(table [ 63400b; 1401b ])(177776b)  //Set boot locus vector
StartIO(100000b)  //silent boot
finish
]