diff --git a/emulator.pas b/emulator.pas index 92bad38..c50d49d 100644 --- a/emulator.pas +++ b/emulator.pas @@ -2,7 +2,7 @@ program Emulator; {$MODE OBJFPC} -uses Crt; +uses SysUtils, Crt; const IO = $ffff; @@ -14,7 +14,10 @@ var Addr, IP, RP: word; //Address argument and instruction and return pointers R: array [0 .. 3] of byte; //General-purpose registers Mem: array [0 .. $ffef] of byte; //Memory - Prog{$ifdef printer}, Prn{$endif}: file of byte; //Program file and printer + Prog{$ifdef printer}, Prn{$endif}{$ifdef tape}, TapeIn, TapeOut{$endif}: file of byte; //Program file, line printer, and punched tape reader and keypunch + {$ifdef tape} + TapePos: integer; //Punched tape reader position pointer + {$endif} Ch: ansichar; //Character for input and output begin @@ -23,6 +26,9 @@ begin Hlt := false; IP := 0; RP := $fff0; + {$ifdef tape} + TapePos := 0; + {$endif} //Read a program file and check for errors if ParamCount <> 1 then begin @@ -121,23 +127,42 @@ begin else if Op = 9 then R [X] := R [X] xor R [Y] //Load else if Op = $a then begin - //Input + //Dumb terminal input if Addr = IO then begin Ch := ReadKey; - write (Ch); + write (Ch); //Local echo R [X] := byte (Ch); end + //Punched tape reader + {$ifdef tape} + else if Addr = $fffd then begin + assign (TapeIn, 'tapein'); + try + reset (TapeIn); + seek (TapeIn, TapePos); + if eof (TapeIn) = false then begin + read (TapeIn, R [X]); + TapePos := TapePos + 1; + end + else R [X] := 0; + close (TapeIn); + except + R [X] := 0; + TapePos := 0; + end; + end + {$endif} //Regular load else R [X] := Mem [Addr]; end //Store else if Op = $b then begin - //Output + //Dumb terminal output if Addr = IO then begin Ch := ansichar (R [X]); write (Ch); end - //Printer + //Line printer {$ifdef printer} else if Addr = $fffe then begin assign (Prn, '/dev/usb/lp0'); @@ -149,6 +174,29 @@ begin end; end {$endif} + //Punched tape keypunch + {$ifdef tape} + else if Addr = $fffd then begin + assign (TapeOut, 'tapeout'); + if FileExists ('tapeout') = false then begin + try + rewrite (TapeOut); + write (TapeOut, R [X]); + close (TapeOut); + except + end; + end + else begin + try + reset (TapeOut); + seek (TapeOut, FileSize (TapeOut)); + write (TapeOut, R [X]); + close (TapeOut); + except + end; + end; + end + {$endif} //Regular store else Mem [Addr] := R [X]; end diff --git a/readme.md b/readme.md index 7bbe18a..202ddb8 100644 --- a/readme.md +++ b/readme.md @@ -91,10 +91,14 @@ this. Arbitrary devices can be mapped to the other reserved addresses. -The emulator can be compiled in Linux with support for a line printer at -/dev/usb/lp0 with the argument -dprinter. The printer is mapped to -address FFFE in the emulator. If you wish to use a different setup you -have to modify the code yourself. +The emulator can be compiled with support for a line printer at +/dev/usb/lp0 with the argument -dprinter, and for an emulated punched +tape reader and keypunch at tapein and tapeout respectively with -dtape. +The printer is mapped to address FFFE in the emulator and the tape +reader and keypunch to FFFD. To reset the tape reader to the beginning +of a tape, for example to change the tape, read once with no file at +tapein. If you wish to use a different setup you have to modify the code +yourself. Initial Program Loader ----------------------