Separate control of the tape reader and punch into its own program
This commit is contained in:
parent
7316f8ad79
commit
b3d043d43c
114
emulator.pas
114
emulator.pas
|
@ -4,6 +4,16 @@ program Emulator;
|
||||||
|
|
||||||
uses SysUtils, Crt;
|
uses SysUtils, Crt;
|
||||||
|
|
||||||
|
{$ifdef tape}
|
||||||
|
type
|
||||||
|
//Tape file path and reset state
|
||||||
|
Tape = record
|
||||||
|
Path: shortstring;
|
||||||
|
Reset: boolean;
|
||||||
|
Pos: integer;
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
const
|
const
|
||||||
IO = $ffff;
|
IO = $ffff;
|
||||||
|
|
||||||
|
@ -14,10 +24,10 @@ var
|
||||||
Addr, IP, RP: word; //Address argument and instruction and return pointers
|
Addr, IP, RP: word; //Address argument and instruction and return pointers
|
||||||
R: array [0 .. 3] of byte; //General-purpose registers
|
R: array [0 .. 3] of byte; //General-purpose registers
|
||||||
Mem: array [0 .. $ffef] of byte; //Memory
|
Mem: array [0 .. $ffef] of byte; //Memory
|
||||||
Prog{$ifdef printer}, Prn{$endif}{$ifdef tape}, TapeIn, TapeOut{$endif}: file of byte; //Program file, line printer, and punched tape reader and punch
|
Prog{$ifdef printer}, Prn{$endif}{$ifdef tape}, TapeIn, TapeOut{$endif}: file of byte; //Program file, line printer, and tape reader and punch tapes
|
||||||
{$ifdef tape}
|
{$ifdef tape}
|
||||||
TapeInFile: string; //Punched tape reader source file
|
Reader, Punch: Tape; //States of the tape reader and punch
|
||||||
TapeInPos: integer; //Punched tape reader position pointer
|
State: file of Tape; //File storing the states of the tape reader and punch
|
||||||
{$endif}
|
{$endif}
|
||||||
Ch, Scan: ansichar; //Character for input and output and scancode for non-ASCII keys
|
Ch, Scan: ansichar; //Character for input and output and scancode for non-ASCII keys
|
||||||
|
|
||||||
|
@ -27,9 +37,15 @@ begin
|
||||||
Hlt := false;
|
Hlt := false;
|
||||||
IP := 0;
|
IP := 0;
|
||||||
RP := $fff0;
|
RP := $fff0;
|
||||||
|
|
||||||
|
//Initialise the tape reader and punch
|
||||||
{$ifdef tape}
|
{$ifdef tape}
|
||||||
TapeInFile := ' ';
|
Reader.Path := '';
|
||||||
TapeInPos := 0;
|
Reader.Reset := true;
|
||||||
|
Reader.Pos := 0;
|
||||||
|
Punch.Path := '';
|
||||||
|
Punch.Reset := true;
|
||||||
|
Punch.Pos := 0;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
//Read a program file and check for errors
|
//Read a program file and check for errors
|
||||||
|
@ -144,17 +160,6 @@ begin
|
||||||
Ch := ansichar ($7f);
|
Ch := ansichar ($7f);
|
||||||
ASCII := true;
|
ASCII := true;
|
||||||
end
|
end
|
||||||
{$ifdef tape}
|
|
||||||
//The insert key sets a tape to be read
|
|
||||||
else if Scan = ansichar ($52) then begin
|
|
||||||
writeln ();
|
|
||||||
write ('Tape to be read: ');
|
|
||||||
readln (TapeInFile);
|
|
||||||
if TapeInFile = '' then TapeInFile := ' ';
|
|
||||||
TapeInPos := 0;
|
|
||||||
ASCII := false;
|
|
||||||
end
|
|
||||||
{$endif}
|
|
||||||
//Unused function keys insert a null
|
//Unused function keys insert a null
|
||||||
else ASCII := true;
|
else ASCII := true;
|
||||||
end
|
end
|
||||||
|
@ -188,16 +193,39 @@ begin
|
||||||
//Tape reader
|
//Tape reader
|
||||||
{$ifdef tape}
|
{$ifdef tape}
|
||||||
else if Addr = $fffd then begin
|
else if Addr = $fffd then begin
|
||||||
assign (TapeIn, TapeInFile);
|
assign (State, ExpandFileName ('~/.tapes.thingamajig'));
|
||||||
|
//Check the reader state
|
||||||
|
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
|
||||||
|
try
|
||||||
|
reset (State);
|
||||||
|
read (State, Reader);
|
||||||
|
read (State, Punch);
|
||||||
|
close (State);
|
||||||
|
except
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
//Read
|
||||||
|
assign (TapeIn, Reader.Path);
|
||||||
try
|
try
|
||||||
reset (TapeIn);
|
reset (TapeIn);
|
||||||
seek (TapeIn, TapeInPos);
|
seek (TapeIn, Reader.Pos);
|
||||||
read (TapeIn, R [X]);
|
read (TapeIn, R [X]);
|
||||||
TapeInPos := TapeInPos + 1;
|
|
||||||
close (TapeIn);
|
close (TapeIn);
|
||||||
|
Reader.Pos := Reader.Pos + 1;
|
||||||
except
|
except
|
||||||
R [X] := 0;
|
R [X] := 0;
|
||||||
end;
|
end;
|
||||||
|
//Save the reader state
|
||||||
|
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
|
||||||
|
try
|
||||||
|
rewrite (State);
|
||||||
|
write (State, Reader);
|
||||||
|
write (State, Punch);
|
||||||
|
close (State);
|
||||||
|
except
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end
|
end
|
||||||
{$endif}
|
{$endif}
|
||||||
//Regular load
|
//Regular load
|
||||||
|
@ -225,26 +253,52 @@ begin
|
||||||
//Tape punch
|
//Tape punch
|
||||||
{$ifdef tape}
|
{$ifdef tape}
|
||||||
else if Addr = $fffd then begin
|
else if Addr = $fffd then begin
|
||||||
assign (TapeOut, 'tapeout');
|
assign (State, ExpandFileName ('~/.tapes.thingamajig'));
|
||||||
if FileExists ('tapeout') = false then begin
|
//Check the punch state
|
||||||
|
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
|
||||||
try
|
try
|
||||||
rewrite (TapeOut);
|
reset (State);
|
||||||
write (TapeOut, R [X]);
|
read (State, Reader);
|
||||||
close (TapeOut);
|
read (State, Punch);
|
||||||
|
close (State);
|
||||||
except
|
except
|
||||||
end;
|
end;
|
||||||
end
|
end;
|
||||||
else begin
|
//Punch
|
||||||
|
if Punch.Path <> '' then begin
|
||||||
|
assign (TapeOut, Punch.Path);
|
||||||
|
if Punch.Reset then begin
|
||||||
|
try
|
||||||
|
rewrite (TapeOut);
|
||||||
|
write (TapeOut, R [X]);
|
||||||
|
close (TapeOut);
|
||||||
|
Punch.Reset := false;
|
||||||
|
except
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
try
|
||||||
|
reset (TapeOut);
|
||||||
|
seek (TapeOut, FileSize (TapeOut));
|
||||||
|
write (TapeOut, R [X]);
|
||||||
|
close (TapeOut);
|
||||||
|
except
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
//Save the punch state
|
||||||
|
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
|
||||||
try
|
try
|
||||||
reset (TapeOut);
|
rewrite (State);
|
||||||
seek (TapeOut, FileSize (TapeOut));
|
write (State, Reader);
|
||||||
write (TapeOut, R [X]);
|
write (State, Punch);
|
||||||
close (TapeOut);
|
close (State);
|
||||||
except
|
except
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
//Regular store
|
//Regular store
|
||||||
else Mem [Addr] := R [X];
|
else Mem [Addr] := R [X];
|
||||||
end
|
end
|
||||||
|
|
24
readme.md
24
readme.md
|
@ -8,10 +8,11 @@ https://ahti.space/git/crazyettin/Thingamajig.
|
||||||
Included Software
|
Included Software
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The repository includes an emulator implementation of Thingamajig as
|
The repository includes an emulator implementation of Thingamajig, a
|
||||||
well as an assembler and a disassembler, all written in FreePascal. It
|
control program for the emulated punched tape reader and punch, and an
|
||||||
also includes couple of simple example programs for Thingamajig written
|
assembler and a disassembler, all written in FreePascal. It also
|
||||||
in Assembly.
|
includes couple of simple example programs for Thingamajig written in
|
||||||
|
Assembly.
|
||||||
|
|
||||||
Registers and Memory
|
Registers and Memory
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -91,14 +92,13 @@ this.
|
||||||
|
|
||||||
Arbitrary devices can be mapped to the other reserved addresses.
|
Arbitrary devices can be mapped to the other reserved addresses.
|
||||||
|
|
||||||
The emulator can be compiled with support for a line printer and an
|
In Linux the emulator can be compiled with support for a line printer
|
||||||
emulated punched tape reader and punch with the arguments -dprinter and
|
and an emulated punched tape reader and punch with the arguments
|
||||||
-dtape respectively. The printer outputs into /dev/usb/lp0 and the tape
|
-dprinter and -dtape respectively. The printer prints into /dev/usb/lp0
|
||||||
punch to tapeout. To (re)set the tape to be read press the insert key at
|
and the tape files read from and punched to are (re)set using the
|
||||||
any input and enter a file name; the input will resume after this. The
|
settape program. The printer is mapped to address FFFE in the emulator
|
||||||
printer is mapped to address FFFE in the emulator and the tape reader
|
and the tape reader and punch to FFFD. If you wish to use a different
|
||||||
and punch to FFFD. If you wish to use a different setup you have to
|
setup you have to modify the code yourself.
|
||||||
modify the code yourself.
|
|
||||||
|
|
||||||
Initial Program Loader
|
Initial Program Loader
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
program Settape;
|
||||||
|
|
||||||
|
{$MODE OBJFPC}
|
||||||
|
|
||||||
|
uses SysUtils;
|
||||||
|
|
||||||
|
type
|
||||||
|
//Tape file path and reset state
|
||||||
|
Tape = record
|
||||||
|
Path: shortstring;
|
||||||
|
Reset: boolean;
|
||||||
|
Pos: integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
//Check whether to set the reader, the punch, or both
|
||||||
|
if ParamCount <> 1 then begin
|
||||||
|
writeln ('Usage: settape reader/punch/both');
|
||||||
|
halt;
|
||||||
|
end;
|
||||||
|
if ParamStr (1) = 'reader' then begin
|
||||||
|
DoRead := true;
|
||||||
|
DoPunch := false;
|
||||||
|
end
|
||||||
|
else if ParamStr (1) = 'punch' then begin
|
||||||
|
DoRead := false;
|
||||||
|
DoPunch := true;
|
||||||
|
end
|
||||||
|
else if ParamStr (1) = 'both' then begin
|
||||||
|
DoRead := true;
|
||||||
|
DoPunch := true;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
writeln ('Usage: settape reader/punch/both');
|
||||||
|
halt;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Assign the state file
|
||||||
|
assign (State, ExpandFileName ('~/.tapes.thingamajig'));
|
||||||
|
|
||||||
|
//Read existing state if any
|
||||||
|
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
|
||||||
|
try
|
||||||
|
reset (State);
|
||||||
|
read (State, Reader);
|
||||||
|
read (State, Punch);
|
||||||
|
close (State);
|
||||||
|
except
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
//Or else assign a default state
|
||||||
|
else begin
|
||||||
|
Reader.Path := '';
|
||||||
|
Reader.Reset := true;
|
||||||
|
Reader.Pos := 0;
|
||||||
|
Punch.Path := '';
|
||||||
|
Punch.Reset := true;
|
||||||
|
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);
|
||||||
|
Reader.Reset := true;
|
||||||
|
Reader.Pos := 0;
|
||||||
|
end;
|
||||||
|
if DoPunch then begin
|
||||||
|
write ('Punch: ');
|
||||||
|
readln (Punch.Path);
|
||||||
|
Punch.Path := ExpandFileName (Punch.Path);
|
||||||
|
Punch.Reset := true;
|
||||||
|
Punch.Pos := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Write the state
|
||||||
|
try
|
||||||
|
rewrite (State);
|
||||||
|
write (State, Reader);
|
||||||
|
write (State, Punch);
|
||||||
|
close (State);
|
||||||
|
except
|
||||||
|
writeln ('Error: could not set the tape(s)');
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
Loading…
Reference in New Issue