diff --git a/emulator.pas b/emulator.pas index 1e9774a..c75a8cc 100644 --- a/emulator.pas +++ b/emulator.pas @@ -31,7 +31,7 @@ const {$endif} var - Hlt, Verbose, Echo: boolean; //Halt, verbose, and echo flags + Hlt, Echo: boolean; //Halt and echo flags Op, Regs: 0 .. $f; //Opcode X, Y: 0 .. 3; //Register arguments Addr, IP, RP: word; //Immediate or address argument and instruction and return pointers @@ -43,7 +43,7 @@ var State: file of Tape; //File storing the states of the tape reader and punch {$endif} Ch, Scan: ansichar; //Character for input and output and scancode for non-ASCII keys - IC, LFX: integer; //Instruction counter for CPU speed + Verbose, IC, LFX: integer; //Verbose flag, instruction counter for CPU speed, and line feed position marker Fetched: byte; //Fetched byte //Terminal output @@ -288,14 +288,21 @@ begin halt (1); end; if ParamStr (1) = '-v' then begin - Verbose := true; + Verbose := 1; + if ParamCount <> 2 then begin + writeln ('Usage: emulator (-v) program (2> verbose_output)'); + halt (1); + end; + end + else if ParamStr (2) = '-v' then begin + Verbose := 2; if ParamCount <> 2 then begin writeln ('Usage: emulator (-v) program (2> verbose_output)'); halt (1); end; end else begin - Verbose := false; + Verbose := 0; if ParamCount <> 1 then begin writeln ('Usage: emulator (-v) program (2> verbose_output)'); halt (1); @@ -304,7 +311,7 @@ begin //Read a program file and check for errors {$i-} - if Verbose = true then assign (Prog, ParamStr (2)) + if Verbose = 1 then assign (Prog, ParamStr (2)) else assign (Prog, ParamStr (1)); reset (Prog); if FileSize (Prog) > LastRAM + 1 then begin @@ -329,7 +336,7 @@ begin while Hlt = false do begin //Print the CPU state to StdErr - if Verbose = true then writeln (StdErr, 'IR: ', IntToHex (Op, 1), IntToHex (Regs, 1), IntToHex (Addr, 4), '; IP: ', IntToHex (IP, 4), ', RP: ', IntToHex (RP, 4), '; R0: ', IntToHex (R[0], 2), ', R1: ', IntToHex (R[1], 2), ', R2: ', IntToHex (R[2], 2), ', R3: ', IntToHex (R[3], 2), ansichar ($d)); + if Verbose <> 0 then writeln (StdErr, 'IR: ', IntToHex (Op, 1), IntToHex (Regs, 1), IntToHex (Addr, 4), '; IP: ', IntToHex (IP, 4), ', RP: ', IntToHex (RP, 4), '; R0: ', IntToHex (R[0], 2), ', R1: ', IntToHex (R[1], 2), ', R2: ', IntToHex (R[2], 2), ', R3: ', IntToHex (R[3], 2), ansichar ($d)); //Fetch the instruction and increment the instruction pointer //Fetch the opcode and register arguments diff --git a/readme.md b/readme.md index 82b9db1..f72d7bd 100644 --- a/readme.md +++ b/readme.md @@ -92,15 +92,20 @@ implementation has a front panel the IPL is optional. The instruction and return pointers are initialised as 0 and the first address after RAM respectively, while other registers and RAM are uninitialised. -Emulator --------- +Emulator and Tapectl +-------------------- + +Usage: + * emulator (-v) program (2> verbose_output) + * tapectl (-r reader_file) (-p punch_file) By default the emulator runs at roughly 500 KIPS, has 2 KiB of RAM, and -interacts with memory mapped devices at roughly 1000 B/s. The arguments +interacts with memory mapped devices at roughly 1 kB/s. The arguments -dRAM4, -dRAM8, -dRAM16, -dRAM32, and -dRAM64 can be used to compile the emulator with 4, 8, 16, 32, or 64 KiB (minus the reserved addresses) of RAM respectively instead and the speed limitations can be removed -with the argument -dfast. +with the argument -dfast. When run with the argument -v the current +state of the registers is output to stderr before each instruction. Input and output are handled by an emulated glass teletype terminal with local echo on by default. Of the control characters bell (^G), @@ -116,8 +121,23 @@ printer and an emulated punched tape reader and punch with the arguments -dprinter and -dtape respectively. The printer is mapped to address FFFE and the tape reader and punch to FFFD. The printer prints into /dev/usb/lp0 and the tape files read from and punched to are (re)set -using the program tapectl. +using the program tapectl with the arguments -r and -p respectively. -The IPL loads a program from a file specified when launching the +The IPL loads the program specified as an argument when running the emulator. + +Assembler and Disassembler +-------------------------- + +Usage: + * assembler program (< input) + * disassembler program (> output) + +Both the assembler and the disassembler are run with a program as their +sole argument: they take their input from and print their output to +stdin and stdout respectively. + +An initial gap created with ORG is not included in an assembled program. +All possible interpretations of a disassembled program are included in +its listing, resulting in overlapping information.  \ No newline at end of file diff --git a/tapectl.pas b/tapectl.pas index df0277b..021205b 100644 --- a/tapectl.pas +++ b/tapectl.pas @@ -15,29 +15,33 @@ type var Reader, Punch: Tape; //States of the reader and punch State: file of Tape; //File storing the states of the reader and punch - DoRead, DoPunch: boolean; //Whether to reset the reader or the punch + DoRead, DoPunch: integer; //Whether to (re)set the reader or the punch begin - //Check whether to set the reader, the punch, or both - if ParamCount <> 1 then begin - writeln ('Usage: tapectl reader/punch/both'); + //Check the arguments + if ParamCount > 4 then begin + writeln ('Usage: tapectl (-r reader_file) (-p punch_file)'); + halt (1); + end + else if ParamCount mod 2 <> 0 then begin + writeln ('Usage: tapectl (-r reader_file) (-p punch_file)'); halt (1); end; - if ParamStr (1) = 'reader' then begin - DoRead := true; - DoPunch := false; + if ParamStr (1) = '-r' then begin + DoRead := 2; + DoPunch := 0; + if ParamStr (3) = '-p' then begin + DoPunch := 4; + end; end - else if ParamStr (1) = 'punch' then begin - DoRead := false; - DoPunch := true; - end - else if ParamStr (1) = 'both' then begin - DoRead := true; - DoPunch := true; + else if ParamStr (1) = '-p' then begin + DoRead := 0; + DoPunch := 2; + if ParamStr (3) = '-r' then DoRead := 4; end else begin - writeln ('Usage: tapectl reader/punch/both'); + writeln ('Usage: tapectl (-r reader_file) (-p punch_file)'); halt (1); end; @@ -64,18 +68,14 @@ begin Punch.Pos := 0; end; - //Input the files to be read from or punched to - if DoRead then begin - write ('Reader: '); - readln (Reader.Path); - Reader.Path := ExpandFileName (Reader.Path); + //Get the files to be read from or punched to + if DoRead <> 0 then begin + Reader.Path := ExpandFileName (ParamStr (DoRead)); Reader.Reset := true; Reader.Pos := 0; end; - if DoPunch then begin - write ('Punch: '); - readln (Punch.Path); - Punch.Path := ExpandFileName (Punch.Path); + if DoPunch <> 0 then begin + Punch.Path := ExpandFileName (ParamStr (DoPunch)); Punch.Reset := true; Punch.Pos := 0; end;