// Press.bcpl

// modified by PolleZ and Swinehart, August 27, 1984 3:27 PM,
// FPREQ.sn field enlarged in FontPass.df, PressInternals.df.
// - changed version to 5.1.

// modified by Ramshaw, November 29, 1983 10:23 AM,
// Added RavenPowerOnFlag
// - changed version to 5.0.


// modified by GWilliams, July 1, 1983 4:31 PM,
// Merged in microcode changes made to accomodate Raven-style printing.
// - changed version to 4.8.

// modified by GWilliams, 14 March 1983 4:51 pm PST (Monday),
// Added Geronimo flag -- scan converts then exits.
// - changed version to 4.7.


// modified by Ramshaw, February 9, 1983 3:29 PM,
// added checks to computation of "delta" parameters used
// in reducing or magnifying dots arrays, to guarantee that
// the input reader won’t run off the end (in PreDots).
// - changed version to 4.6 so as not to confuse with a bootlegged 4.5.

// modified by GWilliams, August 30, 1982 3:49 PM,
// fixed a bug in Press.bcpl introduced in 4.2. The BandWidth
// wasn’t getting into all the PageG’s given a color input file
// - changed version to 4.4

// modified by GWilliams, April 19, 1982 6:37 PM,
// changed SlotDebug to use the BandWidth value from the Press.bits PageG; this makes Reticle debugging easier
// - changed version to 4.3

// modified by GWilliams, April 15, 1982 2:33 PM,
// added BandWidth to PageG definition (and load its value in Press)
// - changed version to 4.2

// modified by Ramshaw, March 19, 1982 4:12 PM,
// - fixed ScanColorPassValue in ScanConvert so that hues in the
// range [240..255] don’t drive it crazy
// - deleted spurious error message that I stuck in PreBand last time
// - changed version to 4.1

// modified by Ramshaw, March 15, 1982 2:08 PM,
// - change band-segment merge code in PreBand to be stable,
// to eliminate "odd number of intersections" bugs.
// - changed version to 4.0

// modified by Ramshaw and GWilliams, March 3, 1982 4:09 PM,
// - cure land-mine in storage management of Press.Bcpl; the
// old version moved Pages and pFonts up to the permanent region
// without checking that this might involve a MoveBlock with
// overlapping source and destination.
// - changed version to 3.9

// modified by Ramshaw and GWilliams, January 30, 1982 9:33 PM,
// - fixed bug in band-segment merging code of PreBand, and
// cleaned it up in the process
// - upped nBandSegmentsMax from 100 to 150
// - changed version to 3.8

// modified by Ramshaw and GWilliams, January 15, 1982 12:29 PM,
// - improved PreFontMake.bcpl to be more polite about memory
// - added F (for FontPickyMatch) switch. Press/F first searches
// the dictionary to find the best matches for all font requests.
// Then, it loops through the requests and reports via Swat each
// and every one that couldn’t be "perfectly" satisfied.
// - I finally figured out the problem with the Transparent hack
// discussed below. From now on, any number of color changes are
// OK in Transparent mode.
// - changed version to 3.7

// modified by Ramshaw and GWilliams, January 15, 1982 12:29 PM,
// - fixed PreFontMake.bcpl to work from scratch file if core is short
// - also upped syncInfinity to 64K-2 by using Ugt in
//
ScanConvert.ScanSyncProc
// - I tried adding another hack in which, if Transparent mode is set,
// the sync codes would just wrap around after 64K, since the overlap
// order doesn’t matter anyway. But this screwed up something else
// that I haven’t had time to track down yet.
// - changed version to 3.5

// modified by Ramshaw and GWilliams, December 4, 1981 2:29 PM,
// - replaced dangling 9999 in ScanChars with syncInfinity
// - changed version to 3.4

// modified by Ramshaw and GWilliams, April 21, 1981 10:07 AM,
// - PressParams.df: raised nBandSegmentsMax from 60 to 100
// - changed version to 3.3

// modified by Ramshaw and GWilliams, April 6, 1981 12:18 PM,
//
- changed version to 3.2
// - scanchar: don’t use extended memory unless the chips are really there
// - PressInstall: ask whether Versatec should be landscape or portrait
// - pressparams.df: raise nDotsRegionsB from 30 to 120


// modified by Ramshaw and Hunt, March 30, 1981 4:24 PM,
//
- changed version to 3.0
// - changed TC200 interface address by adding the manifest hgOutPort=#177101
// it is used in PressUserFinishProc to turn off the Printer in case you are
// leaving from a swat abort (Hunt)
// - fixed several serious bugs in Rotor microcode (Ramshaw)
// - added "LocalFidelity" command-line switch: setting it makes PreScan
// round mica boxes to pixels in such a way that any two boxes with the
// same mica width will have the same pixel width as well, regardless of position
// on the Press page. Leaving LocalFidelity not set means that PreScan will
// round each edge of the mica box independently to a pixel boundary; this
// has the pleasant effect of guaranteeing single coverage and no holes (Ramshaw)

// modified by Ramshaw, March 20, 1981 2:17 PM,
//
- change version to 2.16
// - PressParams.df add syncInfinity
// - ScanConvert use syncInifinty for end of band marker rather than 9999
// - PreBand Check for overflow against synchInfinity
// - PressInit substitute rshift for divide in case over 32K

// modified by Ramshaw, March 11, 1981 2:16 PM,
//
- change version to 2.15 (there were several different bootleg 2.14’s
// floating around for a while)
// - PreScan: changed CoordBox once again; with John Warnock’s blessing,
// made rectangles behave just like the corresponding objects, hence
// abandoning any attempt at local fidelity in favor of a simple model
// and global fidelity.
// - ScanObjects: Removed an off-by-one bug that was causing rectangles
// be one scan line too deep. Also, added a random off-by-one hack
// to shifts all objects one bit higher in the scan direction, to make
// them line up correctly with rectangles.

// modified by Ramshaw, January 18, 1981 5:36 PM,
//
- change version to 2.13
// - FontPass1: changed font match algorithm so that splines are
// used instead of rasters unless the rasters are an excellent match.
// I think that fidelity is more important than performance!

// modified by Ramshaw, January 9, 1981 10:14 PM,
//
- change version to 2.12
// - FontPass1: changed the zero value of ICC to be a pure dummy.
// Real font chars get ICC’s starting from 1, and a dummy raster
// file pointer is output for ICC=0. This means that character
// zero of font zero of font set zero will now print.

// modified by Ramshaw, December 11, 1980 12:39 PM,
//
- change version to 2.11
// - ScanDots: synch halftone screen in B as well as in S dimension
// - PreScan: guarantee that CoordBox is at least one bit in B and S,
//
to avoid problems in lots of other code.

// modified by Butterfield, October 22, 1980 3:48 PM
// - change version to 2.10 - 10/22
// - Press, put the password in Press.bits - 10/22
// - Press, use nPressRecs from PressInit - 10/22
// - ResolutionB, ResolutionS, 1X instead of 10X - 10/13/80

// errors 100

// PRESS MAIN PROCEDURE
//
//Assorted utilities for PRESS.
//
// FSGet(size)
//
Tries to get a block of size "size". Returns pointer or zero.
// FSGetX(size)
//
Like FSGet, but complains if core unavailable.
// FSPut(ptr)
//
Release block seized by FSGet or FSGetX
//
// DblShift(dp,amount)
//
Shift double precision number by "amount" (>0 is to the right)
//
//

get "PressInternals.df"
get "PressParams.df"
get "PressFile.df"

// outgoing procedures
external
[
Press
PressUserFinishProc
PressError
PressErrorV
PressTrap
Scream

GetTime
FSGet
FSGetX
FSPut

DblShift

SwappedOut
]

// outgoing statics
external
[
//Files, disks
BitsFile//Files for all to use
ScratchFile
LeftOverFile1
LeftOverFile2
BandFile
MeterFile
GodFile
PressFile
RunFile
//
tridentDisk//Another "disk" structure!
//
tridentDrive//Number of drive used for Press files
tridentUsed//Flag to say that some file resides on T80

//User’s wishes
Directive//What to do
UserCopies//Number of copies to make
UserPageStart//First page to print
UserPageEnd//Last page to print

// Output device information
nPrinterColors
printerDevice//Code for which device to use
RavenPowerOnFlag
//Is Slot really a Raven?
printerForward//Pages should be printed 1,2,3,...
portrait//True if printerMode=3; otherwise printerMode=8
ResolutionS// number of bits/inch in S
ResolutionB// number of bits/inch in B
PaperDimensionS//10* inches
PaperDimensionB
nScanLines//Number of scan lines on a page
nBitsPerScan//Number of bits per scan line
nBands//Number of bands per page
nPages//Number of pages to scan convert
printerMaxBitsPerScan//Max it can support

VersatecMsSl//Number of milliseconds/scan-line
VersatecFF//Extra form-feeds (256*before+after)

XOffset//User’s specifications of how to perturb pages
YOffset
ScaleOffset

ScreenModulus
ScreenMagnitude
ScreenAngle

FileName//Name of Press file
DPzero//Double precision zero
BESizes//Sizes of band bucket entries
EL//A Window on the Press file.
DoMeter//Gather statistics
DoFileMeter//True if gather stats on each file transfer
DoFaultMeter//Record character faults
Debug//Debugging flag
SoftScan//true if software scan conversion for everything
Verbose//If true, squeal on every error
UseMicroCode//Flag to use microcode facilities
PressSavedUFP
Geronimo//If true, scan convert then get out (don’t print)
PressVersion//Version number =a.b = a*256+b
DoEtherReport//True if log errors on MAXC
Report//Pointer to REP structure for Ether reporting
blockBitsFile//True if one band equiv one block
//Free storage stuff
PressZone//Zone to use for all free storage
PermanentBottom//Bottom of "permanent" free storage
OverlayTable//ovt!i = page of ith overlay
OverlayBottom//Place to put first word of overlay
OverlayTop//Place where last word of overlay is
OverlayReloc//Pointer to relocation table for overlay
]
static
[
BitsFile
ScratchFile
LeftOverFile1
LeftOverFile2
BandFile
MeterFile
GodFile
PressFile
RunFile
//
tridentDisk
//
tridentDrive
tridentUsed

Directive
UserCopies
UserPageStart
UserPageEnd

nPrinterColors
RavenPowerOnFlag

printerDevice
printerForward
portrait
ResolutionS
ResolutionB
PaperDimensionS
PaperDimensionB
nScanLines
nBitsPerScan
nBands
nPages
printerMaxBitsPerScan

VersatecMsSl
VersatecBytes
VersatecFF

XOffset
YOffset
ScaleOffset

ScreenModulus
ScreenMagnitude
ScreenAngle

FileName
DPzero
BESizes
EL
DoMeter
DoFileMeter
DoFaultMeter
Debug
SoftScan
Verbose
UseMicroCode
PressSavedUFP
PressVersion = 5 * 256 + 1;
DoEtherReport
Report
blockBitsFile

PressZone
PermanentBottom
OverlayTable
OverlayBottom
OverlayTop
OverlayReloc
]

// incoming procedures
external
[
//Main procedures for the various passes.
PressInit

FontsPass

PreScanInit
ShowPage
PreScanClose

ScanConvertInit
ScanConvert
ScanConvertClose

PrintInit
Print
PrintClose

//PARTS
SetPartBounds
GetPositioninPart
SetPositioninPart
SetBytePositioninPart
CheckAvailinPart
SkipinPart

//WINDOW,FILES
WindowInit
WindowClose
WindowGetPosition
WindowSetPosition
WindowReadBlock
WindowWriteBlock
WindowReadByte
WindowRead
WindowWrite
WindowFlush
FileStuff
FileWritePage

//METER
MeterBlock
MeterClose

//EVENTREPORT
EventReport

//OS
MoveBlock
lvUserFinishProc
StartIO
SysErr

//PRESSML
DoubleAdd; DoubleSub; DoubleCop; MulDiv
Ugt

//ALLOC
InitializeZone
AddToZone
Allocate
Free

//SLOTTEST
SlotTest
SlotPatterns

//LOADRAM
LoadRam
SetBLV
//PRESSFLOAT
FPSetup
//TFS
TFSSilentBoot//around all the time (tfsa)
]

// incoming statics
external
[
UserName
ScanRam
PrintRam
SlotRam
pFonts//from preFontMake: list of font load stuff (3 wds per load)
nFontLoads
ICCtot
nPressRecs
]

// internal statics
static
[
DocDir//Copy of document directory
FSTrap//To flag storage coming and going.
]

// File-wide structure and manifest declarations.
manifest
[
hgOutPort=#177101
]


// Procedures

let Press(layout, userParams, cfa) be
[
DPzero= table [ 0;0 ]

//First, call initialization routine. It will call Press(0) when it is finished.
if layout ne 0 then PressInit(userParams, cfa)

//Here, the zone in use is still the "permanent" zone. So allocate what
// you need.

compileif ReportSw then [ GetTime(lv Report>>REP.totalTime) ]
let Pages=nil
nPages=0
//"Pages" that will be scan-converted
let firstCopy=1
let lastCopy=1
let PartStart=vec 1
//Position of part directory
let FontPart=vec size PE/16
//To hold font part goodies
let Part=vec size PE/16

DocDir=FSGetX(PressRecordSize)
//Get DocDir first to avoid frag.

FSInit()
//Set to temporary zone.

if (Directive) ne 0 then
[
Overlay(0)
if (Directive) ne 0 then SlotPatterns()
if (Directive) ne 0 then SlotTest()
finish
]

//DOCUMENT DIRECTORY

if PressFile ne 0 then
[PR
let PressLength=vec 1
// FileStuff(PressFile, PressLength); // can’t use since can be on Trident
PressLength!0 = 0; PressLength!1 = nPressRecs;
DblShift(PressLength, -LogPressRecordSize);
DoubleSub(PressLength,table [ 0;PressRecordSize ])
if PressLength!0 ls 0 then PressError(100)

EL=WindowInit(PressFile)
WindowSetPosition(EL,PressLength)
//Get to doc dir.
WindowReadBlock(EL,DocDir,PressRecordSize)

DblShift(PressLength,LogPressRecordSize)
if PressLength!0 then PressError(101)
// let nPressRecs=PressLength!1+1

unless DocDir>>DDV.Passwd eq PressPasswd then PressError(102)
unless DocDir>>DDV.nRecs eq nPressRecs then PressError(103)
unless DocDir>>DDV.nParts*(size PE/16) le
DocDir>>DDV.pdRecs*PressRecordSize then PressError(104)

firstCopy=DocDir>>DDV.fCopy
lastCopy=DocDir>>DDV.lCopy

compileif ReportSw then
[
[
let TransferName(toP,fromP1,fromP2,toLen) be
[
let l=@fromP1 rshift 8
test l ne 0 & l ls 40
ifso MoveBlock(toP, fromP1, toLen)
ifnot [ MoveBlock(toP+1, fromP2, toLen-1)
@toP=(@fromP2𫓸)+(2*256+$-)
toP!1=(@fromP2Ź)+($- *256)
]
]
TransferName(lv Report>>REP.User, lv DocDir>>DDV.CreatStr, UserName, size REP.User/16)
TransferName(lv Report>>REP.File, lv DocDir>>DDV.FileStr, FileName, size REP.File/16)
]
]

//Find the font part and count "pages" in the document.
SetPartBounds(EL,DocDir>>DDV.pdStart,DocDir>>DDV.pdRecs)
SetPositioninPart(EL,DPzero)
//Start reading parts here
WindowGetPosition(EL,PartStart)
//For later reference

let fontfound=false
for i=1 to DocDir>>DDV.nParts do
[
WindowReadBlock(EL,Part,size PE/16)
if Part>>PE.Type eq PETypeFont then
//Font part
[
MoveBlock(FontPart,Part,size PE/16)
fontfound=true
]
if Part>>PE.Type eq PETypePage then
//Page part (ignore other parts)
nPages=nPages+1
]
unless fontfound then PressError(105)

let up=UserPageEnd-UserPageStart+1
if up ls nPages then nPages=up

WindowClose(EL)

]PR

if UserCopies then lastCopy=firstCopy+UserCopies-1

//Here:
//
nPages= number of pages to print.
//
FontPart contains font part PE structure
//
PartStart= address in Press file of part directory
//
DocDir=> checked document directory.

compileif ReportSw then
[
Report>>REP.nPages=nPages
Report>>REP.nCopies=lastCopy-firstCopy+1
]

//FONT PASS

if (Directive𘚠) ne 0 then
[
//Do fonts pass
Overlay(1)
//Bring in the code
PassF:
EL=WindowInit(PressFile)
let FScratchW=WindowInit(ScratchFile,3)
let FGodW=WindowInit(GodFile,1)
SetPartBounds(EL,FontPart>>PE.pStart,FontPart>>PE.pRecs)
SetPositioninPart(EL,DPzero)
FontsPass(EL,FScratchW,FGodW,FontPart>>PE.pRecs)
WindowClose(FGodW)
WindowClose(FScratchW)
WindowClose(EL)
]

//Here: Scratch file is update with first 6 words containing pointers:
//
0,1Used length of Scratch File
//
2,3Pointer to FontSetDirectory (FSD)
//
4,5Pointer to ICC table

//PRESCAN PASS

test (Directive鱀) ne 0 then
[
Overlay(2)
PassS:
Pages=FSGetX(nPages*(size PageG/16)*nPrinterColors)//Avoid frag
EL=WindowInit(PressFile)
PreScanInit()
let p=Pages
let np=0

for i=1 to DocDir>>DDV.nParts do
[let s=vec 1
s!0=0; s!1=(i-1)*(size PE/16)
DoubleAdd(s,PartStart)
WindowSetPosition(EL,s)
WindowReadBlock(EL,Part,size PE/16)
if Part>>PE.Type eq PETypePage then
[np=np+1
if np ge UserPageStart & np le UserPageEnd then
[p>>PageG.PageNumber=np
ShowPage(p,Part)
//
p>>PageG.BandWidth = BANDWidth
p=p+ (size PageG/16)*nPrinterColors
]
]
]

WindowClose(EL)
//No longer need press file.
PreScanClose()

//Now re-order page structure if printer prints backwards
unless printerForward then
[
for j=0 to nPages/2-1 do
[let ap=Pages+(j* (size PageG/16)*nPrinterColors)
let bp=Pages+((nPages-1-j)* (size PageG/16)*nPrinterColors)
for i=0 to ((size PageG/16)*nPrinterColors)-1 do
[ let t=ap!i; ap!i=bp!i; bp!i=t
]
]
]
//set the bandwidth in all the pageG’s
for pa=Pages to (Pages+ (((nPages*nPrinterColors)-1)*(size PageG/16))) by (size PageG/16) do
pa>>PageG.BandWidth = BANDWidth

WritePageStructure(nPages,Pages,nFontLoads,pFonts)
//Write on BitsFile
]
or //no prescan pass
[
let b=WindowInit(BitsFile)
nPages=WindowRead(b)
compileif ReportSw then [ Report>>REP.nPages=nPages]
WindowClose(b)
Pages=ReadPageStructure(nPages,lv pFonts)
//Read it in from BitsFile
nFontLoads=pFonts!-1
]

//Now place Pages structure up out of harm’s way during all the bouncing
// back and forth between Scan Conversion and Printing overlays. Do
// not worry about re-initializing free storage, as it will be done by
// one of the Overlay calls.
let lPageVec=nPages*(size PageG/16)*nPrinterColors
let lFontLoadVec=nFontLoads*3
//size FI/16 is 3
test Ugt(Pages,pFonts)
ifso
[
Pages=MoveBackwards(Pages,lPageVec)
pFonts=MoveBackwards(pFonts,lFontLoadVec)
]
ifnot
[
pFonts=MoveBackwards(pFonts,lFontLoadVec)
Pages=MoveBackwards(Pages,lPageVec)
]

//Calculate the "index" of first and last printable pages:
let firstPageX=nPages*nPrinterColors
let lastPageX=-1
let p=Pages
for i=0 to nPages*nPrinterColors-1 do
[
let pn=p>>PageG.PageNumber
if pn ge UserPageStart & pn le UserPageEnd &
p>>PageG.FirstBand le p>>PageG.LastBand then
[
if i ls firstPageX then firstPageX=i
if i gr lastPageX then lastPageX=i
]
p=p+ (size PageG/16)
]

//SCAN CONVERSION & PRINTING PASSES
// These are dovetailed to handle the "show ... only on copy n"
// PRESS command and the finite capacity of the disk for buffering
// scan-converted pages. The basic idea is to scan-convert everything for
// the first copy, and to print it. Then scan-convert only if needed
// what has changed for subsequent copies, and print them.

let PrintInited=false
//True if printer set up
let veryFirstPrinting=true
let ScanInited=false
//True if scan-converter set up
let doScan=(Directive丠)

let convertPageX=firstPageX
//Page index to convert next

// ***** L O O P F I L L I N G D I S K *****
while convertPageX le lastPageX do
[DiskLoop
//Loop filling up disk buffers

if doScan then
for i=0 to nPages*nPrinterColors-1 do
(Pages+i*(size PageG/16))>>PageG.BitPage=-1
let first=true
//Signal to allocate disk space
let BitPagePos = (4 + nPages * (size PageG / 16) * nPrinterColors + 2 +
nFontLoads * 3 + 1023) / 1024; // cf. WritePageStructure
let nextConvertPageX=lastPageX+1

// ***** L O O P O N C O P I E S *****
for Copy=firstCopy to lastCopy do
[CopyLoop
//Loop making all proper copies
let mustStop=false

let doPageX=convertPageX
let lastBitPagePos=nil
let lastnRecords=nil
// ***** L O O P O N P A G E S (Scan Conversion) *****
while doPageX ls nextConvertPageX do
[PageLoop//Loop scan converting pages
let p=Pages+doPageX*(size PageG/16)
let BandsUsed=(p>>PageG.LastBand-p>>PageG.FirstBand+1)

//for color printers with black input, only scan convert once
if first&doScan&(not p>>PageG.ColorUsed)&
((nPrinterColors ls 4)%(printerDevice eq printerPuffin))&
(p>>PageG.ColorPass ne 0) then
[ p>>PageG.BitPage=lastBitPagePos
p>>PageG.nRecords=lastnRecords
doPageX=doPageX+1
loop
]

//do scan conversion if: needed, or color differences
//for 4-color slot printers, even black has color differences
if (not p>>PageG.SimplePage)%(p>>PageG.ColorUsed)%
((nPrinterColors eq 4)&(printerDevice ne printerPuffin)) do
if (first % p>>PageG.CopyCrucial)&(BandsUsed gr 0)&doScan then
[Convert
unless ScanInited then
[
if PrintInited then PrintClose(false)
PrintInited=false
Overlay(3, lv ScanRam)
PassC:
ScanConvertInit()
ScanInited=true
]
if first then p>>PageG.BitPage=BitPagePos
let nFilePages=ScanConvert(p, Copy)
if nFilePages ls 0 then//Done filling available disk buffers
[
if doPageX eq convertPageX then PressError(106)
break
]
lastBitPagePos=BitPagePos
lastnRecords=p>>PageG.nRecords
BitPagePos=BitPagePos+nFilePages
if p>>PageG.CopyCrucial then mustStop=true
]Convert

doPageX=doPageX+1
]PageLoop

if first then
[ //Write current scan-conversion state on disk
if ScanInited then WritePageStructure(nPages, Pages, nFontLoads, pFonts)
first=false
nextConvertPageX=doPageX
]

//Here: pages with index convertPageX up to nextConvertPageX-1 have been
// scan-converted and are ready to print. mustStop is set if subsequent
// copies require special scan-conversion.

if Geronimo then finish
//got the bits, now get out!

// ***** L O O P O N P A G E S (Printing) *****
if (Directive✐) ne 0 then
for printPageX=convertPageX to nextConvertPageX-1 do
[PageLoop
let p=Pages+printPageX*(size PageG/16)
// Printing routine will decide whether to print blank pages (those
// with FirstBand le LastBand).
if (p>>PageG.FirstBand gr p>>PageG.LastBand) %
(p>>PageG.BitPage ne -1)%p>>PageG.SimplePage then
[ unless PrintInited then
[
if ScanInited then ScanConvertClose()
ScanInited=false
test printerDevice ge printerDurango
then Overlay(4, lv SlotRam)
or Overlay(4, lv PrintRam)
PassP:
PrintInit(veryFirstPrinting,//and add stuff for Puffin control
Pages+convertPageX*(size PageG/16),nextConvertPageX-convertPageX,
lastCopy-firstCopy)
PrintInited=true
veryFirstPrinting=false
]
let stop=(mustStop ne 0 % Copy eq lastCopy)&
(printPageX eq nextConvertPageX-1)
Print(p, stop, OverlayTop+1, PermanentBottom-1)
]
]PageLoop

]CopyLoop

convertPageX=nextConvertPageX
]DiskLoop

if PrintInited then PrintClose(true)


//And finish statistics:
compileif ReportSw then [ Report>>REP.Success=true ]
compileif ReportSw & MeterSw then [ MeterBlock(METERRep, Report, size REP/16) ]
compileif MeterSw then [ MeterClose() ]

finish
//!!!
]

// WritePageStructure(nPages, Pages, nFontLoads, pFonts) -- writes pages data on disk
// ReadPageStructure(nPages,pFontslv) -- reads it back.
// Format of Press.Bits:
//
# page descriptions
//
# words for each page description
//
PrinterMode
//
PressPasswd
//
..followed by PageG structures for each page
//
ICCtot
//
# font loads
//
..followed by FI structures for each font load

and WritePageStructure(nPages, Pages, nFontLoads, pFonts) be
[
let PrinterMode=(portrait? 3,8)
let lPageVec=nPages*(size PageG/16)*nPrinterColors
let b=WindowInit(BitsFile)
WindowWrite(b, nPages)
WindowWrite(b, size PageG/16)
WindowWrite(b, PrinterMode)
WindowWrite(b, PressPasswd);
WindowWriteBlock(b, Pages, lPageVec)
WindowWrite(b,ICCtot)
WindowWrite(b,nFontLoads)
WindowWriteBlock(b,pFonts,nFontLoads*3)
WindowClose(b)
]

and ReadPageStructure(nPages, pFontslv) = valof
[
let PrinterMode=(portrait? 3,8)
let lPageVec=nPages*(size PageG/16)*nPrinterColors
let Pages=FSGetX(lPageVec)
let b=WindowInit(BitsFile)
unless WindowRead(b) eq nPages then PressError(121)
unless WindowRead(b) eq size PageG/16 then PressError(121)
unless WindowRead(b) eq PrinterMode then PressError(121)
unless WindowRead(b) eq PressPasswd then PressError(121);
WindowReadBlock(b, Pages, lPageVec)
ICCtot=WindowRead(b)
let nFontLoads=WindowRead(b)
let pFonts=FSGetX(nFontLoads*3+1)
pFonts!0=nFontLoads
WindowReadBlock(b,pFonts+1,nFontLoads*3)
@pFontslv=pFonts+1
WindowClose(b)
resultis Pages
]


//Miscellaneous

and MoveBackwards(dataToMove, len) = valof
[
//move len words from dataToMove to the permanent zone. BE CAREFUL!
// you must guarantee that there is no valuable data higher than
// dataToMove and below the permanent zone. Also, can’t call MoveBlock,
// since we must move the words from back to front.
PermanentBottom=PermanentBottom-len
for i=len-1 by -1 to 0 do
PermanentBottom!i=dataToMove!i
resultis PermanentBottom
]

and PressError(code, p1, p2, p3, p4) be
[
compileif ReportSw then [ Report>>REP.lastError=code ]
(table [ #77403; #1401 ])("Press.Errors", lv code)
]

and PressErrorV(code, p1, p2, p3, p4) be
[
if Verbose then PressError(code, p1, p2, p3, p4)
]

and PressTrap() be PressError(107)

and Scream(String) be PressError(108)

and GetTime(ptr, ref; numargs n) = valof
[
let time=@#430
if n eq 1 then [ @ptr=time-@ptr ]
if n eq 2 then [ @ptr=@ptr+(time-ref) ]
resultis time
]

//Free storage functions

and FSInit(permBot; numargs n) be
[
//Maximum size of an individual block is 32K. But we can give two blocks
// to FS package. They will never be merged.
if n eq 0 then permBot=PermanentBottom
let len=permBot-OverlayTop-1
let flen=len
if Ugt(flen, #77776) then flen=#77776
PressZone=InitializeZone(OverlayTop+1, flen, SysErr, (Debug? SysErr,0))
if len-flen gr 30 then
[
let b=OverlayTop+1+flen+10
AddToZone(PressZone, b, len-flen-10)
]
]

and FSGet(Size) = valof
[
let ptr=Allocate(PressZone, Size, -1)
if ptr ne 0 & ptr eq FSTrap then PressError(111)
resultis ptr
]

and FSGetX(Size) = valof
[
let p=FSGet(Size)
if p eq 0 then PressError(110)
resultis p
]

and FSPut(ptr) be
[
if ptr eq FSTrap then PressError(111)
Free(PressZone, ptr)
]

and DblShift(dblwordlv,amount) = valof
[
test amount ls 0 then
//Left shift
[
amount=-amount
let temp=(dblwordlv!1) rshift (16-amount)
@dblwordlv=(@dblwordlv lshift amount)+temp
dblwordlv!1=(dblwordlv!1) lshift amount
]
or
[
let temp=@dblwordlv lshift (16-amount)
@dblwordlv=@dblwordlv rshift amount
dblwordlv!1=((dblwordlv!1) rshift amount)+temp
]
resultis dblwordlv!1
//low order 16 bits
]

and PressUserFinishProc() be
[
compileif ReportSw then
[
if Report then
[
GetTime(lv Report>>REP.totalTime)
//Send it out over the ether to 3#200#31
if DoEtherReport then EventReport(Report, size REP/16, table [ #1600; #0; #31 ] )
]
]
if printerDevice eq printerHg then @hgOutPort = 0
StartIO(#100000)
// Silent boot because BLV set at init time.
@lvUserFinishProc=PressSavedUFP
]

and Overlay(i, lvInitRam; numargs n) be
[
let p=OverlayReloc
for i=1 to OverlayReloc!0 do
[
@(p!1)=SwappedOut
p=p+2
]

let pn=OverlayTable!i
PressZone=InitializeZone(PermanentBottom-2000,2000)
let R=WindowInit(RunFile)
let pos=vec 1
pos!0=0; pos!1=pn-1
DblShift(pos, -8)
WindowSetPosition(R, pos)

let dope=vec 16
WindowReadBlock(R, dope, 16)
let len=dope!4-16
WindowReadBlock(R, OverlayBottom, len)
OverlayReloc=OverlayBottom+dope!3-16
let nRel=OverlayReloc!0 *2
for p=1 to nRel by 2 do
[
@(OverlayReloc!p)=OverlayReloc!(p+1)+OverlayBottom
]

OverlayTop=OverlayBottom+len

//If there is an initialization routine, call it. Then move reloc table down over
// it so we can find them when doing the next overlay.
if n ne 1 then
[
let bot=@lvInitRam
if tridentUsed then TFSSilentBoot()
LoadRam(bot, true)
SetBLV(#177776)//Prepare for silent boot on finish.
if tridentUsed then StartIO(#40)
MoveBlock(LoadRam, OverlayReloc, nRel+1)
OverlayReloc=LoadRam
OverlayTop=OverlayReloc+nRel+1
]

FSInit()
if FPSetup ne SwappedOut then//microcode initialization needed
[ let workArea=FSGetX(4*33+1)
workArea!0=33
FPSetup(workArea)
]
]

and SwappedOut() be PressError(120)