Compare commits

...

4 Commits

Author SHA1 Message Date
Bobbi Webber-Manners
9e6f64151e
Add comment about 2MG files 2022-09-07 23:25:26 -04:00
Bobbi Webber-Manners
1a5cacda9d
Fixup to formatting of README-veserver.md 2022-09-07 23:20:36 -04:00
Bobbi Webber-Manners
599d653692
Update VEServer docs 2022-09-07 23:19:51 -04:00
Bobbi Webber-Manners
ec1dc1874c veserver.py: Allow different files to be served to each client. 2022-09-07 22:41:15 -04:00
3 changed files with 85 additions and 15 deletions

View File

@ -14,6 +14,11 @@ place of the ADTPro server for this purpose. VEServer is a much smaller and
simpler program, so it is easier to modify and better suited to being run as simpler program, so it is easier to modify and better suited to being run as
a system service. a system service.
VEServer can also support RS232 serial connections, in which case ADTPro's
`VSDRIVE.SYSTEM` should be used on the Apple II rather than `VEDRIVE.SYSTEM`.
The default mode of operation is to use ethernet. See the Command Line
Options section below for information on how to switch to serial mode.
## Principle of Operation ## Principle of Operation
VEServer uses IPv6 and listens on UDP port 6502 for incoming datagrams from VEServer uses IPv6 and listens on UDP port 6502 for incoming datagrams from
@ -24,7 +29,8 @@ VEServer uses IPv6 and listens on UDP port 6502 for incoming datagrams from
Two simulated drives are supported, backed up by disk files in `.po` "ProDOS Two simulated drives are supported, backed up by disk files in `.po` "ProDOS
Order". These may be 143K or 800K floppy disk images or any volume up to the Order". These may be 143K or 800K floppy disk images or any volume up to the
ProDOS limit of 32MB. ProDOS limit of 32MB. `.2mg` container files are also supported, provided
the volume within the `.2mg` file is in ProDOS order.
VEServer can provide system date and time in a similar manner to an Apple II VEServer can provide system date and time in a similar manner to an Apple II
clock such as Thunderclock or No Slot Clock. Because the legacy ProDOS date clock such as Thunderclock or No Slot Clock. Because the legacy ProDOS date
@ -34,12 +40,19 @@ ProDOS 2.5 please specify the `--prodos25` flag to use the new format.
## Command Line Options ## Command Line Options
There are only a few options: VEServer accepts the following command line options; each option has a short
form and a verbose form:
- `-h`, `--help` - Display brief usage information. - `-h`, `--help` - Display brief usage information.
- `-p`, `--prodos25` - Use new ProDOS 2.5 date/time format (see above.) - `-p`, `--prodos25` - Use new ProDOS 2.5 date/time format (see above.)
- `-1 FNAME`, `--disk1=FNAME` - Specify filename for disk 1 image. - `-1 FNAME`, `--disk1=FNAME` - Specify filename for disk 1 image.
- `-2 FNAME`, `--disk2=FNAME` - Specify filename for disk 1 image. - `-2 FNAME`, `--disk2=FNAME` - Specify filename for disk 1 image.
- `-s`, `--serial` - Use RS232 serial rather than Ethernet.
- `-b nnnnn`, `--baud=nnnnn` - Specify baud rate when using serial connection.
If the `--disk1=FNAME` or `--disk2=FNAME` options are not specified, VEServer
will fall back to using the default values hard coded at the top of the
Python script.
## Running in a Shell ## Running in a Shell
@ -75,3 +88,28 @@ following command:
Rather than using colour to indicate reads and writes the letter 'R' or 'W' is Rather than using colour to indicate reads and writes the letter 'R' or 'W' is
shown before the block number in the log. shown before the block number in the log.
## Working with Multiple Apple II Clients (Advanced)
If you use `VEDRIVE.SYSTEM` on more than one Apple II machine, it is sometimes
convenient to be able to use different disk images on each machine. VEServer
offers a way to do this.
Suppose the disk1 filename is set to `virtual-1.po` and the disk2 filename is
set to `virtual-2.po` (either using the `--disk1=FNAME` / `--disk2=FNAME`
command line parameters, or using the hard-coded default.) Further, suppose
the IP address of the Apple II client is 192.168.0.100. In this case, when
accessing drive 1, VEServer will first look for the file:
- `virtual-1-192.168.0.100.po`
If this is found that file will be served. If not found, VEServer will fall
back to:
- `virtual-1.po`
Similarly for drive 2, `virtual-2-192.168.0.100.po` will be used if it exists,
or `virtual-2.po` otherwise.
This mechanism allows you to serve different disk images for each client,
allowing read/write access with no risk of data corruption due to simultaneous
access.

Binary file not shown.

View File

@ -11,8 +11,8 @@
########################################################################### ###########################################################################
pd25 = False # Default to old-style date/time --prodos25 to use new format pd25 = False # Default to old-style date/time --prodos25 to use new format
file1 = "/home/pi/virtual-1.po" # Disk image drive 1 --disk1 to override file1 = "/home/bobbi/virtual-1.po" # Disk image drive 1 --disk1 to override
file2 = "/home/pi/virtual-2.po" # Disk image drive 2 --disk2 to override file2 = "/home/bobbi/virtual-2.po" # Disk image drive 2 --disk2 to override
serial_port = None # Serial port to use instead of ethernet serial_port = None # Serial port to use instead of ethernet
baud_rate = 115200 # Baud rate for serial mode baud_rate = 115200 # Baud rate for serial mode
@ -107,10 +107,36 @@ def printinfo(drv, blknum, isWrite, isError, cs):
prevop = isWrite prevop = isWrite
prevcs = cs prevcs = cs
#
# Augment filename by adding IP
# If filename is basename.ext and IP is 192.168.2.3
# will return basename-192.168.2.3.ext
#
def augment_filename(filename, ip):
idx = filename.rfind(".")
basename = filename[0 : idx]
ext = filename[idx:]
return basename + "-" + ip + ext
#
# See if augmented filename exists, if so return that name
# otherwise return the unaugmented name
#
def select_filename(filename, ip):
if serial_port:
return filename
filename_with_ip = augment_filename(filename, ip)
try:
with open(filename_with_ip, "rb"):
pass
except:
return filename
return filename_with_ip
# #
# Read block with date/time update # Read block with date/time update
# #
def read3(dataport, addr, d): def read3(dataport, addr, ip, d):
global packet global packet
d = dataport.recvmore(d, 3) d = dataport.recvmore(d, 3)
@ -124,6 +150,8 @@ def read3(dataport, addr, d):
drv = 2 drv = 2
skip = skip2 skip = skip2
file = select_filename(file, ip)
blknum = d[2] + 256 * d[3] blknum = d[2] + 256 * d[3]
err = False err = False
@ -164,12 +192,12 @@ def read3(dataport, addr, d):
printinfo(drv, blknum, False, err, cs) printinfo(drv, blknum, False, err, cs)
b = dataport.sendto(bytearray(l), addr) b = dataport.sendto(bytearray(l), addr)
#print('Sent {} bytes to {}'.format(b, addr)) #print('Sent {} bytes to {}'.format(b, ip))
# #
# Write block # Write block
# #
def write(dataport, addr, d): def write(dataport, addr, ip, d):
global packet global packet
d = dataport.recvmore(d, BLKSZ + 4) d = dataport.recvmore(d, BLKSZ + 4)
@ -183,6 +211,8 @@ def write(dataport, addr, d):
drv = 2 drv = 2
skip = skip2 skip = skip2
file = select_filename(file, ip)
cs = 0 cs = 0
for i in range (0, BLKSZ): for i in range (0, BLKSZ):
cs ^= d[i+5] cs ^= d[i+5]
@ -192,7 +222,7 @@ def write(dataport, addr, d):
err = False err = False
if cs == d[517]: if cs == d[517]:
try: try:
with open(file, 'r+b') as f: with open(file, 'rb') as f:
b = blknum * BLKSZ + skip b = blknum * BLKSZ + skip
f.seek(b) f.seek(b)
for i in range (0, BLKSZ): for i in range (0, BLKSZ):
@ -220,7 +250,7 @@ def write(dataport, addr, d):
printinfo(drv, blknum, True, err, cs) printinfo(drv, blknum, True, err, cs)
b = dataport.sendto(bytearray(l), addr) b = dataport.sendto(bytearray(l), addr)
#print('Sent {} bytes to {}'.format(b, addr)) #print('Sent {} bytes to {}'.format(b, ip))
# #
# See if file is a 2MG and, if so, that it contains .PO image # See if file is a 2MG and, if so, that it contains .PO image
@ -332,7 +362,7 @@ for a, v in args:
elif a in ('-b', '--baud'): elif a in ('-b', '--baud'):
baud_rate = int(v) baud_rate = int(v)
print("VEServer v1.1") print("VEServer v1.2")
if pd25: if pd25:
print("ProDOS 2.5+ Clock Driver") print("ProDOS 2.5+ Clock Driver")
else: else:
@ -347,11 +377,13 @@ with DataPort(serial_port, baud_rate) as dataport:
while True: while True:
try: try:
data, address = dataport.recvfrom(2) data, address = dataport.recvfrom(2)
# print('Received {} bytes from {}'.format(len(data), address)) ip = address[0]
ip = ip[ip.rfind(":")+1:]
#print('Received {} bytes from {}'.format(len(data), ip))
if (data[0] == 0xc5): if (data[0] == 0xc5):
if (data[1] == 0x03) or (data[1] == 0x05): if (data[1] == 0x03) or (data[1] == 0x05):
read3(dataport, address, data) read3(dataport, address, ip, data)
elif (data[1] == 0x02) or (data[1] == 0x04): elif (data[1] == 0x02) or (data[1] == 0x04):
write(dataport, address, data) write(dataport, address, ip, data)
except DataPort.Timeout: except DataPort.Timeout:
pass pass