// PrintOrbit.bcpl

// last modified by Butterfield, July 8, 1980 3:03 PM
// - POrbit, live with ScanConvert’s and Orbit.mu’s imprecision - 7/8/80

// errors 1000
//

get "PressInternals.df"
get "PressParams.df"
get "Orbit.D"
manifest lKCB=10+4 //4 is fudge, 10 is right; should be:
get "bfs.d"

// outgoing procedures
external
[
POrbit;POrbitInit
DoFunc
Max
]

// outgoing statics
external
[
signalBand
]
static
[
signalBand
]

// incoming procedures
external
[
//PrintOrbitHdwFns
AddQEntry;AdCommand;IFunc;ROSCheck
FeedASheet;InitializeHardware;ROSCommand;ROSStatus;ReadAdapterStatus
JogReady
PressError

//CURSOR
CursorChar
CursorDigit
CursorToggle

//OS
Zero
MoveBlock
StartIO
CallSwat
DisableInterrupts
EnableInterrupts

//PRESSML
Ugt
DoubleCop
//PRESS
DblShift

//WINDOWS,FILE
FileReadPage
FileVDA
WindowInit
WindowSetPosition
WindowReadBlock

//PrintDisk31
ReadBuffer31
PrintBuffer31
InitBuffers31
//PrintTrident
ReadBufferTrident
PrintBufferTrident
InitBuffersTrident
]

// incoming statics
external
[
BitsFile
sysDisk

BandFile
printerDevice
printerForward
Debug
breakPage
pFonts
ICCtot

//PRINTORBITINIT
nVisibleBands
nLeadingBands
nTrailingBands
FA
maxPrintPassRecs
BitScale
MotorScale
BitClock
MotorSpeed
LineSyncDelay
PageSyncDelay
VideoGate
Tadapter

nPrinterColors
]

//outgoing statics
external [ FontTable;nextBogusChar;nDCBs]
static [ FontTable;nextBogusChar;nDCBs=3]

// internal statics
static
[
Func
nPagesPrinted
timeOut=15*27
debugTrail
simLateDisk//for debugging simulation of late disk
//if true, then every other ReadBands will
//set proceedcode=4 (no sheet in pipe)
//sequoia fix ~~ At present, Sequoia "not ready" bit never presents itself
//
Some rint sequences require an engine runout, followed
//
by a restart -- this delay waits for shutdown before continuing
readyTimeOut
//set 0 at start, non-zero for outler loop continuation
sReadyTimeOut=2*27+20
//can tune this from SWAT until right
]

// File-wide structure and manifest declarations.

manifest [
RTC=#430
loSize=1200//Enough for 300 left-over characters or lines
debugTrailSize=20*3

// Failure Code ranges -- see ROSCheck
maxNotReady = 9 // not ready, but probably will be soon
maxManual = 19 // Manual intervention required
maxJam = 99// Error during operation
minDocumentError = 300 // Document inherently hard to print
]

manifest // factors for creating table entries
[
Invert= #100000
Code= 256
Word= 16
Bit= 1
]

manifest
[
//P commands
PResetRemoteQueue=#63010
PStartRemoteQueue=#63006
PStart3ColorVideo=#63346
PStart3ColorScan=#63246
PStart4ColorVideo=#63306
PStart4ColorScan=#63206
PAppendQueueEntry=#63020
PSetVideo=#63204
PNoPaperAction=#63003
PFeedPaper=#63203
PReleasePaper=#63103
PSinglePass=#63303
PNoColor=#63001
PSetColor6=#63201//usually black
PSetColor7=#63101//usually cyan
PSetColor9=#63041//usually magenta
PSetColor11=#63021//usually yellow
//P printSeq states
Pwarmup=1
Pstandby=2
Pprinting=3
Pendofrun=4
Plowpaper=5
Pbadfeed=6
Pbadstrip=7
Pclearing=8
PmalfClear=9
]


// -----------------------------------------------------------
// Print
Initialization
// -----------------------------------------------------------

// Returns -1 if printing is successfully completed, else
// nPagesPrinted, so can pick up where we left off.

let POrbitInit(pg,nPages,nCopies;numargs na) be
[ IFunc(fControl, 1)
//Reset Orbit
for i=0 to 15 do//Set inkwell
[
IFunc(fXY, i lshift 12)
IFunc(fInk, -1)
]

AdCommand(adBufferReset)
AdCommand(adSetScales+BitScale lshift 9+MotorScale lshift 6)
AdCommand(adBitClock+BitClock)
AdCommand(adMotorSpeed+MotorSpeed)
AdCommand(adLineSyncDelay+LineSyncDelay)
AdCommand(adPageSyncDelay+PageSyncDelay)
if Tadapter then AdCommand(adVideoGate+VideoGate)
if na eq 0 then return

//do P machine queue creation
//establish queue entries: first, a null entry, and then the real entries
InitializeHardware(true)
ROSCommand(PResetRemoteQueue)
ROSCommand(PAppendQueueEntry)//null rev
for i=0 to nCopies do
[let np=nPages
let p=pg
until np eq 0 do
[test (nPrinterColors eq 3)%
((p>>PageG.ColorUsed)&(nPrinterColors gr 1)) then
[AddQEntry(PSetColor9,PFeedPaper)//magenta
AddQEntry(PSetColor11,PNoPaperAction)//yellow
test nPrinterColors eq 3 then
AddQEntry(PSetColor7,PReleasePaper)//cyan
or
[AddQEntry(PSetColor7,PNoPaperAction)//cyan
AddQEntry(PSetColor6,PReleasePaper)//black
]
]
orAddQEntry(PSetColor6,PSinglePass)
p=p+nPrinterColors*(size PageG/16)
np=np-nPrinterColors
] //for all pages
] //for all copies
ROSCommand(PStartRemoteQueue)
]

and POrbit(pg, lowAdr, highAdr, nPagesAlreadyPrinted,lvFailureCode,last) = valof
[
CursorChar($P)
@lvFailureCode = 0
readyTimeOut=0
nPagesPrinted=nPagesAlreadyPrinted

let debugTrailVec=vec debugTrailSize
compileif DebugSw then [ debugTrail=debugTrailVec;debugTrail!0=0]

lowAdr=lowAdr+(lowAdr&1)
let nRecs=(highAdr-lowAdr-4) rshift BandFile>>F.LogPagesize
//
if nRecs ls maxPrintPassRecs then PressError(1000)

let nBands=nLeadingBands+nVisibleBands+nTrailingBands

let LeftOver=vec loSize+1
LeftOver=(LeftOver+1)&(-2)
let LeftOverGuard=LeftOver+(loSize&(-4))-4

let CommTabNoFeed=vec 3
CommTabNoFeed=(CommTabNoFeed+1)&(-2)
CommTabNoFeed!0=-1
let CommTabFeed=vec 10
CommTabFeed=(CommTabFeed+1)&(-2)

let funcTab=vec 20
Func=(funcTab+1)&(-2)

let FAvalue=FA lshift 8
let coldStart=printerDevice eq printerDover
let consecutiveErrors=0
let printerSimple = printerDevice eq printerSequoia
let stopPrint, okPrint = nil, nil
test printerDevice eq printerSequoia
then stopPrint, okPrint = #60000, #60001 // PimlicoAlt assumed
orstopPrint, okPrint = #60005, #60001 // stop print, lamp inhibit

let newRp=nil

//Read in font and relocate the pointers to characters
let font=pFonts+pg>>PageG.fontLoad*(size FontG/16)
ReadFont(font,lowAdr)
FontTable=lowAdr+font>>FontG.fontLength
for i=0 to ICCtot+nVisibleBands do FontTable!i=FontTable!i+lowAdr

//Figure out where buffers are
let nfRecs=(nRecs-font>>FontG.nRecords)/2
newRp=lowAdr+(font>>FontG.nRecords lshift BandFile>>F.LogPagesize)

//Now read in the bands for this page
let nextBuffFreeList=ReadBands(pg,newRp,nfRecs*2)-BandFile>>F.Pagesize
let firstBuff=(nextBuffFreeList+BandFile>>F.Pagesize+1)&-2

let nBuffs=0
let page=pg>>PageG.BitPage
nextBogusChar=ICCtot
let doneFlag=true
let nextBuffFreeIndex=0
let DCBs=vec 2
let v=vec lKCB*16*3+1
DCBs!0=(v+1)&-2
DCBs!1=DCBs!0+lKCB*16
DCBs!2=DCBs!1+lKCB*16

let InitBuffers,ReadBuffer,PrintBuffer=nil,nil,nil
test BitsFile>>F.Device ge DISKT80 then
[ InitBuffers=InitBuffersTrident;ReadBuffer=ReadBufferTrident
PrintBuffer=PrintBufferTrident
]
or
[ InitBuffers=InitBuffers31;ReadBuffer=ReadBuffer31;PrintBuffer=PrintBuffer31
]

let headerBuff=vec 2
let labelBuff=vec 10

unless pg>>PageG.SimplePage do
[ //Set up initial bogus character buffers
// doneFlag=false
// let myBands=pg>>PageG.LastBand-pg>>PageG.FirstBand+1
// let da=nil
// Make an effort to print blank pages. Otherwise, color sync
// on 6500 will be screwed up.
// test myBands gr 0 then da=FileVDA(BitsFile, pg>>PageG.BitPage)
// or [
//
da=-1
//
pg>>PageG.FirstBand=10
//
pg>>PageG.BitMargin=16*10
//
pg>>PageG.BitWc=4
//
nBands=1
//
]

nBuffs=((highAdr rshift 1)-(firstBuff rshift 1))/(4096/2)
doneFlag=InitBuffers(DCBs,firstBuff,nBuffs,headerBuff,labelBuff,lv page)

] //end of "unless simplePage"

// Initialize the Orbit, Dover, etc.
InitializeHardware(false)
let np = nil
let tim = @RTC
// Check for problems, wait for ready indication
// wait for ready or some serious condition or for long enough
unless Debug do
[
//sequoia Fix ~~ possibly wait for shutdown
while (@RTC-tim) < readyTimeOut do [ ]
if printerDevice eq printerSequoia then readyTimeOut=sReadyTimeOut
[
let running=printerDevice eq printerPuffin
np=ROSCheck(lvFailureCode,nPagesAlreadyPrinted,running,
nPagesPrinted)
if np eq -1 break // ready
if @lvFailureCode>maxNotReady % (@RTC-tim) > timeOut resultis np
] repeat
] //end of "unless Debug" with sequoia fix

// Try to empty Orbit buffers to clear them. This is to minimize
// toner dumping on first (blank) page.
compileif loSize ls 256 then [ foo=nil ]
for i=0 to 31 do DoFunc(fReadBlock, 256, LeftOver)

unless printerDevice eq printerPuffin do
//feed first sheet:
[
DoFunc(fControl, 21b)
ROSCommand(adBufferReset)
// If Dover is already running, this StartPrint may not do the right
// thing, because it may be sent during the "dead" time near
// CS-5.
FeedASheet()
]
Announce(15)// ~~ Delays PimlicoAlt long enough?
unless AwaitPageSync(0) do CallSwat("1")//Wait for sendVideo to go off.

[RunningLoop
// Calculate a ROS command table for the device:
let CommTab=nil
switchon printerDevice into
[
case printerDover:
CommTab=CommTabFeed
CommTab!0=signalBand+2
CommTab!1=adExternalCommand1//No feed yet
CommTab!2=signalBand+1
CommTab!3=adExternalCommand1
CommTab!4=10000b+signalBand
CommTab!5=32*256//Status bits 0-3 of word 8
CommTab!6=-1
endcase
case printerDurango:
CommTab=CommTabNoFeed
FeedASheet()
endcase
case printerSequoia: case printerPimlicoAlt:
CommTab=CommTabFeed
CommTab!0=signalBand
CommTab!1=last?stopPrint,okPrint//Stop unless proven otherwise (below)
CommTab!2=-1
endcase
case printerPuffin: CommTab=CommTabNoFeed;endcase
case printerPimlico:
[
CommTab = CommTabNoFeed
let nC = nil
if last do ROSCommand(#63030) // Stop Print (at end of copy)
endcase
]
]

//cold start for test
if printerDevice eq printerDover then
[ AwaitPageSync(1)
FeedASheet()
AwaitPageSync(0)
]

// Start Orbit working on the present page.
DoFunc(fControl, #21)//Reset, clear behind
ROSCommand(adBufferReset)

LeftOver!0=0//Initialize LeftOver table
LeftOverGuard!1=-1
tim=@RTC
// Start the microcode!!!!
DoFunc(fSlot, CommTab, 20000,pg>>PageG.LastBand+1, FAvalue, LeftOver,
FontTable+#100000, newRp-1, nil, nil, 1)

// Proceed code:
// 0: Charge on ahead, full speed
// 1: Pause because cannot fit bands or font for next page,
// or because printing is done.
// 2: Reprint this page, due to misfeed (Dover only).
// 4: No sheet in pipe (Dover only)

// Assume the page we are printing will be OK:
//
unless coldStart then
//
[
//
nPagesPrinted=nPagesPrinted+1
//
CursorDigit(nPagesPrinted)
//
]
// Find next page to work on:
//
let proceedCode=1
//
let nextbuf=curbuf xor buf1 xor buf2
//
let nextPage=PrintNext(pDoc,lv copy)
//
if nextPage & (nextPage>>PageG.fontLoad eq page>>PageG.fontLoad) &
//
(nextPage>>PageG.nRecords le nfRecs) then proceedCode = 0
//
PollEther() // ~~ later, if print request then proceedCode = 1

// Read in the bands for the next page:
//
if proceedCode eq 0 then
let proceedCode=nil
//TEST
//if false then
//TEST ONLY
//
[
//
if printerSimple then CommTab!1=okPrint // don’t stop
////TEST
ReadBands(nextPage, nextbuf, coldStart? nfRecs*2, nfRecs)
//
if printerDevice eq printerDover then
//
[
//
if simLateDisk then
//
[
//
simLateDisk=simLateDisk xor 1
//
if (simLateDisk&1) eq 0 then Func!3=-1
//
]
//
DisableInterrupts()
//
test Func!3 gr signalBand+3 then
//
CommTab!1=adExternalCommand1+1
//
orproceedCode=4
//
EnableInterrupts()
//
]
//
]
// Now see if we actually printed this page properly. First,
// wait for Orbit to announce it is finished.
let imageTimeout = (printerDevice eq printerDover? 4, 10)*27
let readCount=0
let printCount=0
while @#720 ne 0 do
[ if (@RTC-tim) gr imageTimeout then
[
Blast()// clear hardware, #720
test printerDevice eq printerPimlicoAlt & JogReady() ne 0 then
proceedCode = 2 // counted out, equiv. to misfeed.
// Machine dead or Orbit got behind and it wasn’t detected
// Will generally be overriden by more specific analysis
or @lvFailureCode = 19 // Manual intervention required
break
]
// (Notes: ScanConvert processes bands FirstBand to LastBand. When
// writing out band b it checks to see if the nWordsToWrite will fit.
// If they will not, it writes the Bit page and sets the
// nextBuffFreeList entry for that page to b+1, which is two too many.
// Orbit.mu only decrements Func!3 upon starting the next band, and
// the emulator is run only when a band is on it’s way out.
// currentBand below, then, is the band just processed.
// Writing over a page used to wait until
currentBand ge
// nextBuffFreeList!nextBuffFreeIndex
. Subtracting 2 lets the disk
// get (further) ahead.)
let currentBand=pg>>PageG.LastBand+1-Func!3
unless doneFlag do
[ if (currentBand ge nextBuffFreeList!nextBuffFreeIndex - 2) then
[ //diskIO
let adr=firstBuff+4096*(readCount rem nBuffs)
ReadBuffer(page,adr,DCBs!(readCount rem nDCBs))
readCount=readCount+1
if (readCount-printCount) ge nDCBs then
[ until PrintBuffer(DCBs!(printCount rem nDCBs),
lv doneFlag) do [ ]
printCount=printCount+1
]
page=page+4096/1024
nextBuffFreeIndex=nextBuffFreeIndex+1
]
if readCount gr printCount then
if PrintBuffer(DCBs!(printCount rem nDCBs),
lv doneFlag) then printCount=printCount+1
]
]

// Check Orbit status
@#521=0
let debugValue=readCount-printCount
StatusLabel:
let nonF = 0
let stat=Func!9//Orbit printing status.
// ********** Debugging stuff
//if stat<<STATUS.invalidBandEntry then CallSwat("Illegal non-char band dispatch!!!!!")
// ***********
test stat<<STATUS.prematurePageAbort then [ Announce(16); nonF = 301 ]
or if stat<<STATUS.behind then [ Announce(16); nonF = 300 ]
if stat<<STATUS.timeout then [ Announce(17); @lvFailureCode = 18 ]
if LeftOverGuard!1 ne -1 then [ Announce(18); nonF = 310 ]
if nonF then @lvFailureCode = nonF
// Now try for more specific engine status check
np=ROSCheck(lvFailureCode, nPagesAlreadyPrinted, true, nPagesPrinted)
// Release any "buttons" that are being held "depressed"
if printerDevice eq printerPimlicoAlt then
ROSCommand(#60001)
// Check COUNT-H signal, paper did not arrive -- else re-print page (Dover only).
if coldStart eq 0 & printerDevice eq printerDover &
((CommTab!5)&1) eq 0 then proceedCode=proceedCode%
(Func!3 le signalBand+3? 2, proceedCode eq 1? 0, 4)

// Now wait for page sync to go off
unless AwaitPageSync(0) then @lvFailureCode = 18

resultis true
//TESTTESTTESTTEST

//Now decide what to do:
if proceedCode then Announce(proceedCode)
let malfunction = @lvFailureCode
if malfunction ge minDocumentError then malfunction = 0 // will not stop

// First, if pipe is empty, fill it. Will not be invoked if pausing. (Dover only)
//TEST
if (proceedCode&4) ne 0 then
//if false do //TEST ONLY
//
[
//
AwaitPageSync(1)
//
FeedASheet()
//
AwaitPageSync(0)
//
proceedCode=proceedCode-4
//
]

// Now react to the analysis: if at this point nothing is wrong and sheets are
// feeding, steam ahead. Otherwise, return to the slow loop if data is not available
// or if paper misfed. Return if there was a serious malfunction, or if things look
// odd several times consecutively (paper failed to feed is the only case, for now)
//TEST
unless malfunction do
//if false do //TEST ONLY
//
[
//
if proceedCode eq 0 % proceedCode eq 2 & nonF ne 0 then
//
[
//
coldStart=false
////
curbuf=nextbuf
//
consecutiveErrors=0
//
loop
//
]
//
if proceedCode eq 1 then [ coldStart = false; break ] //Out of RunningLoop
//
consecutiveErrors=consecutiveErrors+1 // misfeeds only, right now
//
if consecutiveErrors ge 4 then
//
[
//
malfunction, @lvFailureCode = 17, 17
//
np = nPagesPrinted
//
]
//
]

if malfunction then
[
InitializeHardware(true)
// if malfunction detected outside of ROSCheck, set np
let backup = printerDevice eq printerDover? 2, 1 // probably wrong
if np eq -1 then np = nPagesPrinted-backup
// account for previous increment
np = Max(np-1, nPagesAlreadyPrinted)
resultis np
]
// If we get here, it is necessary to reprint this page. Paper is
// probably flowing. Probably a paper misfeed
// Exception: non-fatal malfunction (mf=0, but nonF isn’t) -- give it up and go on
unless nonF do nPagesPrinted=nPagesPrinted-1
if (proceedCode&1) ne 0 then break//Use pause code
loop//Reprint the page, or go on
]RunningLoop repeat

InitializeHardware(true)
resultis -1
]
// -----------------------------------------------------------------
// PrintNext(pDoc, lvCopyNo), ReadBands(page, buf, nRecs), ReadFont(font, buf)
// ------------------------------------------------------------------

// Return pointer to next page to print (given nPagesPrinted)
// Set @lvCopyNo to current copy number, beginning with 1
// nPagesPrinted is the total number of pieces of paper shoved out.
// Routine is complicated by:
//
BreakPage: (always last in array)
//
PrinterForward: printer could be going either way.

//TESTand PrintNext(pDoc, lvCopyNo, n; numargs na) = valof
//TEST[
//TEST
if na<3 then n = nPagesPrinted
//TEST
let nPages=pDoc>>DocG.nPages
//TEST
let nBreaks = breakPage eq 0? 0, printerDevice eq printerPimlicoAlt? 3, 1
//TEST
nPages=nPages-nBreaks
//TEST
let nCopies=pDoc>>DocG.nCopies
//TEST
let copy = (printerForward? n-nBreaks+nPages, n)/nPages
//TEST
@lvCopyNo = printerForward? copy, nCopies-copy
//TEST
let totPages=nCopies*nPages+nBreaks
//TEST
if n ge totPages then resultis 0//All finished
//TEST
// Transform to forward sequence:
//TEST
unless printerForward then n=totPages-n-1
//TEST
n=n-nBreaks
//TEST
let p=n rem nPages
//TEST
if breakPage ne 0 & n ls 0 then p=nPages+nBreaks+n//Print break page
//TEST
resultis p*(size PageG/16)+pDoc>>DocG.Pages
//TEST]

//Horrible stuff added to avoid understanding band merge pass (shame)
and ReadBands(page, buf, nRecs) = (page eq 0)?0,valof
[ let readRecs=page>>PageG.nRecords
if nRecs ls readRecs then PressError(1001)
let firstBand=page>>PageG.FirstBand
let lastBand=page>>PageG.LastBand
Zero(buf,firstBand*2)
buf=buf+firstBand*2
let pos=vec 1
DoubleCop(pos,lv page>>PageG.BandPos)
let wordOffset=(pos!1)&(BandFile>>F.Pagesize-1)
let firstPage=DblShift(pos,BandFile>>F.LogPagesize)
FileReadPage(BandFile,firstPage,buf)
MoveBlock(buf,buf+wordOffset,BandFile>>F.Pagesize-wordOffset)
firstPage=firstPage+1
buf=buf+BandFile>>F.Pagesize-wordOffset
until readRecs le 48 do
[ FileReadPage(BandFile,firstPage,buf,48)
firstPage=firstPage+48
buf=buf+48*BandFile>>F.Pagesize
readRecs=readRecs-48
]
FileReadPage(BandFile,firstPage,buf,readRecs)
resultis buf+readRecs*BandFile>>F.Pagesize
]

and ReadFont(font, buf) be
[ let count=font>>FontG.nRecords
let page=font>>FontG.bandPos
until count le 48 do
[ FileReadPage(BandFile,page,buf,48)
page=page+48
buf=buf+48*BandFile>>F.Pagesize
count=count-48
]
FileReadPage(BandFile,page,buf,count)
]
and Max(a,b)=(a gr b)?a,b

and Announce(n) be
[
CursorChar((n ge 16? $K,$P))
for i=0 to 3 do
[
if (n&10b) ne 0 then CursorToggle(i)
n=n lshift 1
]
]
and Blast() be InitializeHardware(false)

and SetRMR(x) = ( table [ #61010; #1401 ] )(x, #20)


and DebugEnter(a, b) be
[
compileif DebugSw then
[
let m=debugTrail!0
let dm=debugTrail+m
dm!1=a; dm!2=b; dm!3=@RTC//Time
m=m+3; if m ge debugTrailSize-4 then m=0
debugTrail!0=m
]]

// -----------------------------------------
// Engine controls of various sorts.
// -----------------------------------------

//Wait for page sync to equal given value.
// Returns true if there was nothing unexpected
and AwaitPageSync(ps) = valof
[
if Debug then resultis true
let tim=@RTC
[
if (@RTC-tim) gr 5*27 then resultis false
DoFunc(fControl, 0)//Read ROS special status (1st four bits of status word 0)
let f=Func!9
if f<<STATUS.ROSStatusBit0 eq ps then resultis true
] repeat
]

and DoFunc(function, arg1, arg2, arg3, arg4, arg5, nil,nil,nil,nil,nil) = valof
[
compileif DebugSw then [ DebugEnter(function, arg1) ]
if Debug then resultis 0
MoveBlock(Func, lv function, 11)
if function eq fStatus then Func!0=fDBCWIDIn
//
if refreshIdle then @Func=(@Func)%#100000
// Give pointer to microcode stuff.
@#720=Func
// Wake up microcode
StartIO(#4)
// Wait for microcode to complete
if function ne fSlot then while @#720 ne 0 do loop
if function eq fStatus then resultis Func!9
resultis Func!8
]

// DCS, July 27, 1977 11:49 PM, use IndexedPageIO instead of FileReadPage
// September 20, 1977 12:03 AM, tentative PimlicoAlt control code
// September 22, 1977 2:12 PM, firm PimlicoAlt control code
// September 23, 1977 8:30 PM, much improved engine control routine
// September 24, 1977 2:25 PM, fix some bugs
// September 26, 1977 7:54 AM, accommodate "only on copy"
// October 1, 1977 12:21 AM, three color break page
// October 12, 1977 12:05 PM, allow large pages
// October 17, 1977 5:13 PM, missing Dover test, Pimlico breaks -- Version 4.(0,0)
// October 17, 1977 11:56 PM, try to jog start print on coincidence -- v4.(0,2)
// October 25, 1977 8:35 PM, fix ROSStatus for Sequoia
// October 28, 1977 1:32 PM, Pimlico!
// October 31, 1977 12:37 AM, all 66xxx s/b 63xxx
// October 31, 1977 10:53 AM, Pimlico, stop print was one rev late.
//