Add option for emulated modem

This commit is contained in:
CrazyEttin 2022-09-27 11:21:14 +03:00
parent 23b32d7835
commit da67a19ac6
3 changed files with 242 additions and 18 deletions

View File

@ -2,17 +2,35 @@ program Emulator;
{$MODE OBJFPC} {$MODE OBJFPC}
uses SysUtils, Crt; {$ifdef full}
{$define RAM64}
{$define printer}
{$define tape}
{$define floppy}
{$define modem}
{$endif}
uses SysUtils, Crt{$ifdef modem}, Sockets{$endif};
{$ifdef tape}
type type
{$ifdef tape}
//Tape file path and reset state //Tape file path and reset state
Tape = record Tape = record
Path: shortstring; Path: shortstring;
Reset: boolean; Reset: boolean;
Pos: integer; Pos: integer;
end; end;
{$endif} {$endif}
{$ifdef modem}
//Modem connection state
Connection = record
Call: boolean;
Addr: longword;
Port: word;
Answer: boolean;
Hang: boolean;
end;
{$endif}
const const
//The last address of RAM //The last address of RAM
@ -31,7 +49,7 @@ const
{$endif} {$endif}
var var
Hlt, Echo{$ifdef floppy}, DiscRead, DiscWrite, DiscTrackSet, DiscSectSet{$endif}: boolean; //Halt and echo flags and disc system flags Hlt, Echo{$ifdef floppy}, DiscRead, DiscWrite, DiscTrackSet, DiscSectSet{$endif}{$ifdef modem}, Calling{$endif}: boolean; //Halt and echo flags, disc system flags, and modem connection flag
Op, Regs: 0 .. $f; //Opcode Op, Regs: 0 .. $f; //Opcode
X, Y: 0 .. 3; //Register arguments X, Y: 0 .. 3; //Register arguments
Addr, IP, RP: word; //Immediate or address argument and instruction and return pointers Addr, IP, RP: word; //Immediate or address argument and instruction and return pointers
@ -56,6 +74,12 @@ var
{$ifdef floppy} {$ifdef floppy}
DiscDrive: 0 .. 1; //Current disc drive number DiscDrive: 0 .. 1; //Current disc drive number
{$endif} {$endif}
{$ifdef modem}
ModemConn: Connection; //State of the modem
ModemState: file of Connection; //File storing the state of the modem
ServerSocket: longint; //Server socket
ServerAddr: TInetSockAddr; //Server address
{$endif}
//Terminal output //Terminal output
procedure Output; procedure Output;
@ -90,6 +114,57 @@ begin
end; end;
{$endif} {$endif}
{$ifdef modem}
//Connect
procedure CallServer;
begin
assign (ModemState, ExpandFileName ('~/.thingamajig/connection'));
//Check the modem state
if FileExists (ExpandFileName ('~/.thingamajig/connection')) then begin
try
reset (ModemState);
read (ModemState, ModemConn);
close (ModemState);
except
end;
end;
//Hang
if ModemConn.Hang then if Calling then begin
CloseSocket (ServerSocket);
ModemConn.Hang := false;
Calling := false;
end
else if ModemConn.Call then if Calling then begin
CloseSocket (ServerSocket);
Calling := false;
end;
//Call
if ModemConn.Call then if Calling = false then begin
//Create a socket
ServerSocket := fpSocket (AF_INET, SOCK_STREAM, 0);
if ServerSocket <> -1 then begin
//Connect
ServerAddr.sin_family := AF_INET;
ServerAddr.sin_port := htons (ModemConn.Port);
ServerAddr.sin_addr.s_addr := htonl (ModemConn.Addr);
if fpconnect (ServerSocket, @ServerAddr, Sizeof (ServerAddr)) <> -1 then begin
ModemConn.Call := false;
Calling := true;
end;
end;
end;
//Save the modem state
if FileExists (ExpandFileName ('~/.thingamajig/connection')) then begin
try
rewrite (ModemState);
write (ModemState, ModemConn);
close (ModemState);
except
end;
end;
end;
{$endif}
//Load a byte from memory //Load a byte from memory
function LoadByte (W: word): byte; function LoadByte (W: word): byte;
var var
@ -178,6 +253,19 @@ begin
else B := 0; else B := 0;
end end
{$endif} {$endif}
{$ifdef modem}
//Modem
else if W = $fffa then begin
{$ifndef fast}
wait (26);
{$endif}
//Connect
CallServer;
//Recieve
if Calling then fpRecv (ServerSocket, @B, 1, 0)
else B := 0;
end
{$endif}
//Unused addresses //Unused addresses
else if W > LastRAM then B := 0 else if W > LastRAM then B := 0
//Regular load //Regular load
@ -515,6 +603,18 @@ begin
end; end;
end end
{$endif} {$endif}
{$ifdef modem}
//Modem
else if W = $fffa then begin
{$ifndef fast}
wait (26);
{$endif}
//Connect
CallServer;
//Send
if Calling then fpSend (ServerSocket, @B, 1, 0);
end
{$endif}
//Regular store //Regular store
else if W <= LastRAM then Mem [W] := B; else if W <= LastRAM then Mem [W] := B;
end; end;
@ -565,6 +665,11 @@ begin
Disc1Sect := 0; Disc1Sect := 0;
{$endif} {$endif}
{$ifdef modem}
//Initialise the modem
Calling := false;
{$endif}
//Check the arguments //Check the arguments
if ParamCount = 0 then begin if ParamCount = 0 then begin
writeln ('Usage: emulator (-v) program (2> verbose_output)'); writeln ('Usage: emulator (-v) program (2> verbose_output)');
@ -726,6 +831,11 @@ begin
end; end;
{$ifdef modem}
//Disconnect the modem
if Calling then CloseSocket (ServerSocket);
{$endif}
{$ifndef fast} {$ifndef fast}
wait (1); wait (1);
{$endif} {$endif}

106
modemctl.pas Normal file
View File

@ -0,0 +1,106 @@
program ModemCtl;
{$MODE OBJFPC}
uses SysUtils, StrUtils, Sockets;
type
//Connection state
Connection = record
Call: boolean;
Addr: longword;
Port: word;
Answer: boolean;
Hang: boolean;
end;
var
ModemConn: Connection; //State of the modem
State: file of Connection; //File storing the state of the modem
Addr: in_addr; //Temporary variable
begin
//Check the arguments
if ParamStr (1) = '-c' then begin
if ParamCount > 2 then begin
writeln ('Usage: modemctl [-c address:port]/-a/-h');
halt (1);
end;
end
else begin
if ParamCount > 1 then begin
writeln ('Usage: modemctl [-c address:port]/-a/-h');
halt (1);
end;
end;
//Assign the state file
assign (State, ExpandFileName ('~/.thingamajig/connection'));
//Read existing state if any
if FileExists (ExpandFileName ('~/.thingamajig/connection')) then begin
try
reset (State);
read (State, ModemConn);
close (State);
except
end;
end
//Or else assign a default state
else begin
ModemConn.Call := false;
ModemConn.Addr := 0;
ModemConn.Port := 0;
ModemConn.Answer := false;
ModemConn.Hang := false;
end;
//Set the connection
if ParamStr (1) = '-c' then begin
ModemConn.Call := true;
try
Addr := StrToHostAddr (ExtractDelimited (1, ParamStr (2), [':']));
ModemConn.Addr := Addr.s_addr;
except
writeln ('Usage: modemctl [-c address:port]/-a/-h');
halt (1);
end;
try
ModemConn.Port := StrToInt (ExtractDelimited (2, ParamStr (2), [':']));
except
writeln ('Usage: modemctl [-c address:port]/-a/-h');
halt (1);
end;
ModemConn.Answer := false;
ModemConn.Hang := false;
end
else if ParamStr (1) = '-a' then begin
ModemConn.Call := false;
ModemConn.Addr := 0;
ModemConn.Port := 0;
ModemConn.Answer := true;
ModemConn.Hang := false;
end
else if ParamStr (1) = '-h' then begin
ModemConn.Call := false;
ModemConn.Addr := 0;
ModemConn.Port := 0;
ModemConn.Answer := false;
ModemConn.Hang := true;
end
else begin
writeln ('Usage: modemctl [-c address:port]/-a/-h');
halt (1);
end;
//Write the state
try
rewrite (State);
write (State, ModemConn);
close (State);
except
writeln ('Error: could not set the connection');
end;
end.

View File

@ -9,8 +9,8 @@ Included Software
----------------- -----------------
The repository includes an emulator implementation of Thingamajig with The repository includes an emulator implementation of Thingamajig with
storage device control programs, and an assembler and a disassembler, device control programs, and an assembler and a disassembler, all
all written in FreePascal. It also includes couple of simple example written in FreePascal. It also includes couple of simple example
programs for Thingamajig written in assembly. programs for Thingamajig written in assembly.
Registers and Memory Registers and Memory
@ -91,13 +91,14 @@ implementation has a front panel the IPL is optional. The instruction
and return pointers are initialised as 0 and the first address after RAM and return pointers are initialised as 0 and the first address after RAM
respectively, while other registers and RAM are uninitialised. respectively, while other registers and RAM are uninitialised.
Emulator and Storage Device Control Programs Emulator and Device Control Programs
-------------------------------------------- ------------------------------------
Usage: Usage:
* emulator (-v) program (2> verbose_output) * emulator (-v) program (2> verbose_output)
* tapectl (-r tape) (-p tape) * tapectl (-r tape) (-p tape)
* floppyctl (-0 disc) (-1 disc) * floppyctl (-0 disc) (-1 disc)
* modemctl [-c address:port]/-a/-h
By default the emulator runs at roughly 500 KIPS and has 2 KiB of RAM. By default the emulator runs at roughly 500 KIPS and has 2 KiB of RAM.
The arguments -dRAM4, -dRAM8, -dRAM16, -dRAM32, and -dRAM64 can be used The arguments -dRAM4, -dRAM8, -dRAM16, -dRAM32, and -dRAM64 can be used
@ -118,16 +119,23 @@ characters and non-character keys null.
In Linux the emulator can be compiled with support for a character In Linux the emulator can be compiled with support for a character
printer, an emulated high speed (roughly 500 CPS in and 50 CPS out) printer, an emulated high speed (roughly 500 CPS in and 50 CPS out)
8-bit paper tape reader and punch, and an emulated two-drive 8" floppy 8-bit paper tape reader and punch, an emulated two-drive 8" floppy disc
disc system with the arguments -dprinter, -dtape, and -dfloppy system, and a roughly 300 b/s modem with the arguments -dprinter,
respectively. The printer is mapped to address FFFE, the tape reader and -dtape, -dfloppy, and -dmodem respectively. Full 64 KiB of RAM and all
punch to FFFD, and the disc system to FFFB and FFFC. The printer prints of these options can also be enabled with the argument -dfull. The
into /dev/usb/lp0. The tape files read from and punched to are (re)set printer is mapped to address FFFE, the tape reader and punch to FFFD,
using the program tapectl with the arguments -r and -p respectively and the disc system to FFFB and FFFC, and the modem to FFFA. The printer
the disc files in drives 0 and 1 using the program floppyctl with the prints into /dev/usb/lp0. The tape files read from and punched to are
arguments -0 and -1 respectively. The disc system uses hard sectored (re)set using the program tapectl with the arguments -r and -p
single-sided discs with 77 tracks of 32 sectors of 137 bytes, or 337568 respectively and the disc files in drives 0 and 1 using the program
bytes in total: the disc files must be of this size. floppyctl with the arguments -0 and -1 respectively. The disc system
uses hard sectored single-sided discs with 77 tracks of 32 sectors of
137 bytes, or 337568 bytes in total: the disc files must be of this
size. The modem is controlled by the program modemctl: the option -c is
used to "call" an IP address and port, -a to set the modem ready for
"answering" "calls" to port 1337, and -h to "hang". "Hanging" manually
is not necessary when "calling" a different address or switching between
"calling" and "answering". Note: "Answering" is not functional yet.
The floppy disc system uses two ports: command at FFFB and data at FFFC. The floppy disc system uses two ports: command at FFFB and data at FFFC.
Only the low nibble of the command port is used, consisting of a Only the low nibble of the command port is used, consisting of a