-- DiskDebugImpl.mesa
-- Jim Gasbarro  19-Feb-85 14:01:51

DIRECTORY
  ColorVersatecDriver,
  ColorVersatecUtils,
  DicentraDiskDriver,
  Heap USING [systemZone],
  OthelloDefs,
  ProcessorFace,
  String,
  Watchdog USING [Deactivate];
 
DiskDebugImpl: PROGRAM 
  IMPORTS ColorVersatecDriver, ColorVersatecUtils, DicentraDiskDriver, Heap, OthelloDefs, ProcessorFace, String, Watchdog 
  = BEGIN
  
OPEN   ColorVersatecDriver,
  ColorVersatecUtils,
  DicentraDiskDriver,
  OthelloDefs;

GoToDebugger: SIGNAL = CODE;

StripeBand: PROC [stripeOffset: CARDINAL, hyperOffset: LONG CARDINAL] =
  BEGIN
  buffer: ARRAY [0..wordsPerScan) OF CARDINAL;
  p: POINTER ← @buffer;
  FOR i: CARDINAL IN [0..wordsPerScan) DO
    IF i MOD 4 = stripeOffset THEN buffer[i] ← 0F0FFH ELSE buffer[i] ← 0;
    ENDLOOP;
  FOR i: LONG CARDINAL IN [0..scansPerBand) DO
    HyperStore[sourcePtr: p, destOffset: hyperOffset + (i * LENGTH[buffer]), wordCount: LENGTH[buffer]];
    ENDLOOP;
  END;
  
SetupBand: PROC [value: CARDINAL, hyperOffset: LONG CARDINAL] =
  BEGIN
  buffer: ARRAY [0..wordsPerScan) OF CARDINAL;
  p: POINTER ← @buffer;
  FOR i: CARDINAL IN [0..wordsPerScan) DO
    buffer[i] ← value;
    ENDLOOP;
  FOR i: LONG CARDINAL IN [0..scansPerBand) DO
    HyperStore[sourcePtr: p, destOffset: hyperOffset + (i * LENGTH[buffer]), wordCount: LENGTH[buffer]];
    ENDLOOP;
  END;

CheckBand: PROC [stripeOffset: CARDINAL, hyperOffset: LONG CARDINAL] =
  BEGIN
  buffer: ARRAY [0..wordsPerScan) OF CARDINAL;
  p: POINTER ← @buffer;
  FOR i: LONG CARDINAL IN [0..scansPerBand) DO
    HyperRead[destPtr: p, sourceOffset: hyperOffset + (i * LENGTH[buffer]), wordCount: LENGTH[buffer]];
    FOR j: CARDINAL IN [0..wordsPerScan) DO
        IF j MOD 4 = stripeOffset THEN 
          BEGIN IF buffer[j] # 0F0FFH THEN 
          BEGIN
          WriteString["scan: "];
          WriteLongNumber[i];
          WriteString[" word: "];
          WriteLongNumber[j];
          WriteString[" expected: 170377 got: "];
          WriteOctal[buffer[j]];
          NewLine[];
          END
        END
        ELSE IF buffer[j] # 0 THEN 
          BEGIN
          WriteString["scan: "];
          WriteLongNumber[i];
          WriteString[" word: "];
          WriteLongNumber[j];
          WriteString[" expected: 0 got: "];
          WriteOctal[buffer[j]];
          NewLine[];
          END
      ENDLOOP;
    ENDLOOP;
  END;
  
ReadBand: PROC [cylinder: Cylinder] =
  BEGIN
  FOR i: LONG CARDINAL IN [0..sectorsPerBand) DO
  [] ← Read[head: CARDINAL[i / sectorsPerTrack], sector: CARDINAL[i MOD sectorsPerTrack], cylinder: cylinder, sectorCount: 1, cmdOffset: 32, dataOffset: 64 + (i * wordsPerSector)];
  ENDLOOP;
  END;
  
WriteBand: PROC [cylinder: Cylinder] =
  BEGIN
  FOR i: LONG CARDINAL IN [0..sectorsPerBand) DO
  [] ← Write[head: CARDINAL[i / sectorsPerTrack], sector: CARDINAL[i MOD sectorsPerTrack], cylinder: cylinder, sectorCount: 1, cmdOffset: 32, dataOffset: 64 + (i * wordsPerSector)];
  ENDLOOP;
  END;
  
BandTest: PROC [] =
  BEGIN
  DiskInitialCheckout[];
  ShowMP[1000];
  StripeBand[stripeOffset: 0, hyperOffset: 64];
  ShowMP[2000];
  WriteLine["Checking band before disk write..."];
  CheckBand[stripeOffset: 0, hyperOffset: 64];
  [] ← Write[head: 0, sector: 0, cylinder: 0, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  ShowMP[3000];
  SetupBand[value: 52525B, hyperOffset: 64];
  [] ← Read[head: 0, sector: 0, cylinder: 0, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  ShowMP[4000];
  WriteLine["Checking band after disk read..."];
  CheckBand[stripeOffset: 0, hyperOffset: 64];
  ShowMP[5000];
  WriteLine["Done."];
  END;

SeekTest: PROC [] =
  BEGIN
  success: BOOLEAN ← TRUE;
  WriteString["Begin Seek Test..."]; 
  FOR i: CARDINAL IN [0..cylindersPerSpindle) DO
    success ← success AND Seek[cylinder: i, cmdOffset: 0];
    success ← success AND Seek[cylinder: cylindersPerSpindle - i - 1, cmdOffset: 0];
    ENDLOOP;
  IF ~success THEN WriteLine["ERROR: Seek Test Failed"]
  ELSE WriteLine["Seek Test Complete"];
  END;

seed: WORD ← 0;
eachWord: WORD ← 1;
eachSector: WORD ← 256;
eachTest: WORD ← 1;

VerifyTest: PROC [] =
  BEGIN
  BufferSetup: PROC [ptr: LONG POINTER TO ARRAY [0..wordsPerSector) OF CARDINAL] =
    BEGIN
    temp: WORD ← seed;
    FOR i: CARDINAL IN [0..LENGTH[buffer]) DO
      ptr[i] ← temp;
      temp ← temp + eachWord;
      ENDLOOP;
    END;
    
  BufferClear: PROC [ptr: LONG POINTER TO ARRAY [0..wordsPerSector) OF CARDINAL] =
    BEGIN
    FOR i: CARDINAL IN [0..LENGTH[buffer]) DO
      ptr[i] ← 0;
      ENDLOOP;
    END;
    
  BufferOK: PROC [ptr: LONG POINTER TO ARRAY [0..wordsPerSector) OF CARDINAL] RETURNS [BOOLEAN] =
    BEGIN
    temp: WORD ← seed;
    FOR i: CARDINAL IN [0..LENGTH[buffer]) DO
      IF ptr[i] # temp THEN RETURN[FALSE];
      temp ← temp + eachWord;
      ENDLOOP;
    RETURN[TRUE];
    END;
  
  PrintBuffer: PROC [ptr: LONG POINTER TO ARRAY [0..wordsPerSector) OF CARDINAL] =
    BEGIN
    FOR i: CARDINAL ← 0, i+16 UNTIL i >= LENGTH[buffer] DO
      FOR j: CARDINAL IN [0..16) DO
        temp: STRING = [20];
        String.AppendNumber[temp, ptr↑[i+j], 16];
        FOR i: CARDINAL IN [temp.length..5) DO WriteChar[' ]; ENDLOOP;
        WriteString[temp];
        ENDLOOP;
      NewLine[];
      ENDLOOP;
    END;
      
  p: POINTER ← @buffer;
  buffer: ARRAY [0..wordsPerSector) OF CARDINAL;
  startCylinder, endCylinder: CARDINAL;
  savedSeed: WORD ← seed;
  
  startCylinder ← LOOPHOLE[ReadNumber ["StartCylinder: ", 0, LAST[Cylinder], 0]];
  endCylinder ← LOOPHOLE[ReadNumber ["EndCylinder: ", 0, LAST[Cylinder], 822]];
  seed ← LOOPHOLE[ReadNumber ["Seed: ", 0, LAST[WORD], seed]];
  eachWord ← LOOPHOLE[ReadNumber ["Word Incr: ", 0, LAST[WORD], eachWord]];
  eachSector ← LOOPHOLE[ReadNumber ["Sector Incr: ", 0, LAST[WORD], eachSector]];
  IF startCylinder > endCylinder THEN 
    BEGIN
    WriteLine["Input Error: StartCylinder greater than EndCylinder."];
    RETURN[];
    END;
  WriteLine["VerifyTest: Begin Write Phase"];  
  FOR i: CARDINAL IN [startCylinder..endCylinder) DO
    FOR j: CARDINAL IN [0..tracksPerCylinder) DO
      BufferSetup[ptr: p]; 
      ColorVersatecUtils.HyperStore[sourcePtr: p, destOffset: 32, wordCount: LENGTH[buffer]];
      ColorVersatecUtils.HyperRead[destPtr: p, sourceOffset: 32, wordCount: LENGTH[buffer]];
      IF ~BufferOK[ptr: p] THEN
        BEGIN
        WriteLine["MEMORY ERROR before writing to disk, sector:"];
        WriteLongNumber[j];
        WriteString[" head: "];
        WriteLongNumber[j];
        WriteString[" cylinder: "];
        WriteLongNumber[i];
        WriteLine["..."];
        PrintBuffer[ptr: p];
        END;
        [] ← Write[sector: j, head: j, cylinder: i, sectorCount: 1, cmdOffset: 0, dataOffset: 32]; 
      IF ~BufferOK[ptr: p] THEN
        BEGIN
        WriteLine["MEMORY ERROR after writing to disk, sector:"];
        WriteLongNumber[j];
        WriteString[" head: "];
        WriteLongNumber[j];
        WriteString[" cylinder: "];
        WriteLongNumber[i];
        WriteLine["..."];
        PrintBuffer[ptr: p];
        END;
      seed ← seed + eachSector;
      ENDLOOP;
    ProcessorFace.SetMP[i];
    ENDLOOP;
     
  WriteLine["VerifyTest: Begin Read Phase"];  
  FOR i: CARDINAL IN [startCylinder..endCylinder) DO
    FOR j: CARDINAL IN [0..tracksPerCylinder) DO
      [] ← Read[sector: j, head: j, cylinder: i, sectorCount: 1, cmdOffset: 0, dataOffset: 32];
      ColorVersatecUtils.HyperRead[destPtr: p, sourceOffset: 32, wordCount: LENGTH[buffer]];
      IF ~BufferOK[ptr: p] THEN
        BEGIN
        WriteString["ERROR: Data Compare Error at sector: "];
        WriteLongNumber[j];
        WriteString[" head: "];
        WriteLongNumber[j];
        WriteString[" cylinder: "];
        WriteLongNumber[i];
        NewLine[];
        PrintBuffer[ptr: p];
        END;
      seed ← seed + eachSector;
      ENDLOOP;
    ProcessorFace.SetMP[i];
    ENDLOOP;
  seed ← seed + eachTest;
  WriteLine["End ReadWriteTest"];
  END;
  
DiskToPlotterTest: PROC [] =
  BEGIN
  
  VersatecInitialCheckout[];
  DiskInitialCheckout[];

  ShowMP[1000];
  StripeBand[stripeOffset: 0, hyperOffset: 64];
  [] ← Write[head: 0, sector: 0, cylinder: 0, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  StripeBand[stripeOffset: 1, hyperOffset: 64];
  [] ← Write[head: 0, sector: 0, cylinder: 200, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  StripeBand[stripeOffset: 2, hyperOffset: 64];
  [] ← Write[head: 0, sector: 0, cylinder: 400, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  StripeBand[stripeOffset: 3, hyperOffset: 64];
  [] ← Write[head: 0, sector: 0, cylinder: 600, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  
  ShowMP[2000];
  [] ← Read[head: 0, sector: 0, cylinder: 0, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  SetColorMode[inches: 10, mode: FirstPassOfColor, color: Black, cmdOffset: 0];
  PlotBuffer[wordCount: wordsPerBand, hyperOffset: 64];
  Rewind[cmdOffset: 0];
  
  ShowMP[3000];
  [] ← Read[head: 0, sector: 0, cylinder: 200, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  SetColorMode[inches: 10, mode: IntermediatePassOfColor, color: Cyan, cmdOffset: 0];
  PlotBuffer[wordCount: wordsPerBand, hyperOffset: 64];
  Rewind[cmdOffset: 0];
  
  ShowMP[4000];
  [] ← Read[head: 0, sector: 0, cylinder: 400, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  SetColorMode[inches: 10, mode: IntermediatePassOfColor, color: Magenta, cmdOffset: 0];
  PlotBuffer[wordCount: wordsPerBand, hyperOffset: 64];
  Rewind[cmdOffset: 0];
  
  ShowMP[5000];
  [] ← Read[head: 0, sector: 0, cylinder: 400, sectorCount: sectorsPerBand, cmdOffset: 32, dataOffset: 64];
  SetColorMode[inches: 10, mode: IntermediatePassOfColor, color: Yellow, cmdOffset: 0];
  PlotBuffer[wordCount: wordsPerBand, hyperOffset: 64];
  SendEOT[];
  END;

FormatDisk: PROC [] =
  BEGIN
  IF GotYes["Are you sure [Y/N]? "] THEN [] ← RawFormat[cmdOffset: 32];
  END;
  

GotYes: PROC [t: STRING] RETURNS[BOOL] =
  BEGIN
  c: CHAR;
  WriteString[t];
  c ← ReadChar[]; 
  WriteChar[c];
  NewLine[];
  IF c = 'y OR c = 'Y THEN RETURN[TRUE] ELSE RETURN[FALSE];
  END;
  
BS: CHARACTER = 10C;
ControlA: CHARACTER = 'A - 100B;
ControlP: CHARACTER = 'P - 100B;
ControlW: CHARACTER = 'W - 100B;
CR: CHARACTER = 15C;
DEL: CHARACTER = 177C;
ESC: CHARACTER = 33C;
SP: CHARACTER = ' ;
NUL: CHARACTER = 0C;
spacesInStringOK: BOOLEAN ← FALSE;
  GetName: PUBLIC PROCEDURE [
    prompt: STRING ← NIL, dest: POINTER TO LONG STRING,
    -- how: EchoNoEcho ← echo, signalQuestion: BOOLEAN ← FALSE ] =
    how: EchoNoEcho ← echo] =
    BEGIN
    first: BOOLEAN ← TRUE;
    EraseChar: PROCEDURE = {
      IF dest.length = 0 THEN RETURN;
      dest.length ← dest.length - 1;
      -- OthelloForgot.EraseTTYChar[IF how = echo THEN dest[dest.length] ELSE '*];
      WriteChar[BS];
      IF dest.length = 0 AND dest.maxlength > 20 THEN {
  z.FREE[dest]; dest↑ ← z.NEW[StringBody[10]]; }};
    CWriteC: PROCEDURE [c: CHARACTER] = {WriteChar[IF how = echo THEN c ELSE '*]};
    CWriteString: PROCEDURE = {
      FOR i: CARDINAL IN [0..dest.length) DO CWriteC[dest[i]] ENDLOOP};

    IF dest↑ = NIL THEN dest↑ ← z.NEW[StringBody[10]];
    WriteString[prompt]; CWriteString[];
    DO
      c: CHARACTER = ReadChar[];
      SELECT TRUE FROM
        c = BS, c = ControlA => EraseChar[];
        (c = SP AND ~spacesInStringOK), c = CR => {NewLine[]; RETURN};
        c = DEL => {WriteLine[" XXX"L]; -- ERROR TryAgain -- EXIT};
        c = ControlW =>
    DO
      EraseChar[];
      IF dest.length=0 THEN EXIT;
      SELECT dest[dest.length-1] FROM
        IN ['a..'z], IN ['A..'Z], IN ['0..'9] => LOOP;
        ENDCASE => EXIT;
      ENDLOOP;
  -- c = '? AND signalQuestion => {
        --  SIGNAL Question; WriteString[prompt]; CWriteString[]; LOOP};
        c >= SP => {
          IF first THEN WHILE dest.length#0 DO EraseChar[] ENDLOOP;
          String.AppendCharAndGrow[dest, c, z]; CWriteC[dest[dest.length-1]]};
        ENDCASE => BlinkDisplay[];
      first ← FALSE;
      ENDLOOP;
    END;
  
z: UNCOUNTED ZONE = Heap.systemZone;
numberString: LONG STRING ← NIL;
ReadNumber: PUBLIC PROCEDURE [
    prompt: STRING, min, max, default: LONG CARDINAL ← LAST[LONG CARDINAL]]
    RETURNS [ans: CARDINAL] = {
    DO
      IF default # LAST[LONG CARDINAL] THEN {
        IF numberString=NIL THEN numberString ← z.NEW[StringBody[15]];
  numberString.length ← 0; String.AppendLongNumber[numberString, default, 10]};
      WriteString[prompt];
      WriteChar['[];
      WriteLongNumber[min];
      WriteString[".."L];
      WriteLongNumber[max];
      WriteString["]: "L];
      GetName[prompt: "", dest: @numberString];
      ans ← 0;
      FOR i: CARDINAL IN [0..numberString.length) DO
        IF numberString[i] NOT IN ['0..'9] THEN EXIT;
        ans ← 10*ans + numberString[i] - '0;
        REPEAT FINISHED => IF ans IN [min..max] THEN {
    z.FREE[@numberString]; RETURN};
        ENDLOOP;
      WriteLine["Bad Number !"L];
      ENDLOOP};

LoopRead: PROC [] =
  BEGIN
  sector: Sector;
  head: Head;
  cylinder: Cylinder;
  count: CARDINAL;
  sector ← LOOPHOLE[ReadNumber ["Sector: ", 0, LAST[Sector], 0]];
  head ← LOOPHOLE[ReadNumber ["Head: ", 0, LAST[Head], 0]];
  cylinder ← LOOPHOLE[ReadNumber ["Cylinder: ", 0, LAST[Cylinder], 0]];
  count ← ReadNumber ["Loop Count: ", 1, LAST[CARDINAL], 1];
  FOR i: CARDINAL IN [0..count) DO
    [] ← Read[head: head, sector: sector, cylinder: cylinder, sectorCount: 1000, cmdOffset: 32, dataOffset: 64];
    ENDLOOP;
  END;
  
ReadSector: PROC [] =
  BEGIN
  sector: Sector;
  head: Head;
  cylinder: Cylinder;
  count: CARDINAL;
  sector ← LOOPHOLE[ReadNumber ["Sector: ", 0, LAST[Sector], 0]];
  head ← LOOPHOLE[ReadNumber ["Head: ", 0, LAST[Head], 0]];
  cylinder ← LOOPHOLE[ReadNumber ["Cylinder: ", 0, LAST[Cylinder], 0]];
  count ← ReadNumber ["Sector Count: ", 1, LAST[CARDINAL], 1];
  [] ← Read[head: head, sector: sector, cylinder: cylinder, sectorCount: count, cmdOffset: 32, dataOffset: 64];
  END;
  
WriteSector: PROC [] =
  BEGIN
  sector: Sector;
  head: Head;
  cylinder: Cylinder;
  count: CARDINAL;
  sector ← LOOPHOLE[ReadNumber ["Sector: ", 0, LAST[Sector], 0]];
  head ← LOOPHOLE[ReadNumber ["Head: ", 0, LAST[Head], 0]];
  cylinder ← LOOPHOLE[ReadNumber ["Cylinder: ", 0, LAST[Cylinder], 0]];
  count ← ReadNumber ["Sector Count: ", 1, LAST[CARDINAL], 1];
  [] ← Write[head: head, sector: sector, cylinder: cylinder, sectorCount: count, cmdOffset: 32, dataOffset: 64];
  END;
  
Help: PROC [] =
  BEGIN
  c: CHAR;
  WriteString["Help (command or ?): "];
  c ← ReadChar[]; 
  SELECT c FROM
  'B, 'b => BEGIN
    WriteLine["BandTest"];
    WriteLine["MP=1000 - drive is online"];
    WriteLine["MP=2000 - generated a pattern in memory 64 sectors long"];
    WriteLine["MP=3000 - test pattern written to first 64 sectors on disk (single transfer)"];
    WriteLine["MP=4000 - cleared memory and read first 64 sectors (single transfer)"];
    WriteLine["MP=5000 - pattern in memory verified"];
    WriteLine["Takes a few seconds to complete"];
    NewLine[];
    END;
  'C, 'c => BEGIN
    WriteLine["ControllerTest"];
    WriteLine["This command runs the power-up self test.  If successful, status is returned."];
    WriteLine["If not, the self-test LED will not extinguish and error status may be returned."];
    NewLine[];
    END;
  'D, 'd => BEGIN
    WriteLine["Debugger"];
    WriteLine["Sends the Dicentra into 915 mode."];
    NewLine[];
    END;
  'F, 'f => BEGIN
    WriteLine["Format"];
    WriteLine["Formats the disk for 19 heads and 823 cylinders."];
    WriteLine["Takes about 20 minutes"];
    NewLine[];
    END;
  'G, 'g => BEGIN
    WriteLine["GetStatus"];
    WriteLine["Returns controller and drive parameters"];
    NewLine[];
    END;
  'L, 'l => BEGIN
    WriteLine["LoopRead"];
    WriteLine["Reads first 1000 sectors a specified number of times"];
    NewLine[];
    END;

  'P, 'p => BEGIN
    WriteLine["Plot"];
    WriteLine["MP=1000 - disk and versatec online"];
    WriteLine["MP=2000 - four color band pattern written to disk"];
    WriteLine["MP=3000 - black pass transmitted"];
    WriteLine["MP=4000 - cyan pass transmitted"];
    WriteLine["MP=5000 - magenta pass transmitted"];
    WriteLine["MP=6000 - yellow (final) pass transmitted"];
    WriteLine["Time limited by versatec"];
    NewLine[];
    END;
  'R, 'r => BEGIN
    WriteLine["ReadSector"];
    WriteLine["Prompts for Sector, Head, Cylinder, and Count then does a disk read"];
    WriteLine["operation with those prameters"];
    NewLine[];
    END;
  'S, 's => BEGIN
    WriteLine["Seek"];
    WriteLine["Seeks from [0..822] to [822..0].  No data is transferred.  It is not unusual"];
    WriteLine["(although not correct) for the disk to fail this test."];
    WriteLine["Takes about two minutes to complete."];
    NewLine[];
    END;
  'V, 'v => BEGIN
    WriteLine["VerifyTest"];
    WriteLine["Writes one sector on each track (sector number equals track number) for a"];
    WriteLine["range cylinders on the disk.  Data written is a counting pattern starting at"];
    WriteLine["sector+track.  After all cylinders are written, the data is read and verified."];
    WriteLine["MP=last complete track read or written"];
    WriteLine["Takes about a second per track per pass."];
    NewLine[];
    END;
  'W, 'w => BEGIN
    WriteLine["WriteSector"];
    WriteLine["Prompts for Sector, Head, Cylinder, and Count then does a disk write"];
    WriteLine["operation with those prameters"];
    NewLine[];
    END;
  ENDCASE => BEGIN
    WriteLine[""];
    WriteLine["options are: BandTest, ControllerTest, Debugger, Format, GetStatus, Plot,"];
    WriteLine["ReadSector, Seek, VerifyTest, and WriteSector"];
    NewLine[];
    END;
  END;
  
NewLine[];
WriteLine["What's up doc?"];
Watchdog.Deactivate[];
DO
c: CHAR;
WriteString["> "];
c ← ReadChar[]; 
WriteChar[c];
NewLine[];
SELECT c FROM
  'B, 'b => BandTest[];
  'C, 'c => SelfTest[];
  'D, 'd => SIGNAL GoToDebugger[];
  'F, 'f => FormatDisk[];
  'G, 'g => ReadDriveStatus[];
  'L, 'l => LoopRead[];
  'P, 'p => DiskToPlotterTest[];
  'R, 'r => ReadSector[];
  'S, 's => SeekTest[];
  'V, 'v => VerifyTest[];
  'W, 'w => WriteSector[];
  '? => BEGIN
    WriteLine["BandTest, ControllerTest, Debugger, Format, GetStatus, LoopRead, Plot, "];
    WriteLine["ReadSector, Seek, VerifyTest, and WriteSector"];
    END;
  'H, 'h => Help[];
  ENDCASE => WriteLine["Learn to type you moron."];
ENDLOOP;
END.