A2CLOUD
rasppleii / a2cloud Goto Github PK
View Code? Open in Web Editor NEWConnect your Apple // to the world via Linux
License: Other
Connect your Apple // to the world via Linux
License: Other
It's possible we want to detect chroot while doing installation via pi-gen or whatever.
Something like this will do that:
isChroot=
[[ "$(ls -di / | cut -d ' ' -f 1)" != "2" ]] && isChroot=1
Is this necessary or desirable?
From @IvanExpert on October 25, 2015 22:21
I might have actually done this already, but it would certianly save a few clunky steps if the A2CLOUD disk came out of the box with a Null Modem connect to the Pi ready to roll from its quick dial menu rather than having to fuss with the Online Parameters.
Copied from original issue: RasppleII/a2server#37
From @IvanExpert on October 25, 2015 22:21
Ewen recently re-released a couple of 8-bit comm programs he write long ago, one for ProDOS and one for DOS 3.3. The DOS 3.3 one is especially interesting since it almost certainly won't require an enhanced //e, which ProTERM and Z-Link do. And some people just like DOS 3.3 better.
Copied from original issue: RasppleII/a2server#36
From @IvanExpert on October 25, 2015 22:19
I looked into this and once got it cooking with SLIrP, but SLIrP is super slow, and I could never get the right script going. The bigger problem is that the lack of conditional logic in Marinetti's scripting makes it impossible to determine whether the serial shell is in any of three states: logged out, logged in, logged in with SLIP (or PPP) running.
I also suspect that even with proper SLIP or PPP server running on the Pi, it would still be just too slow; I'm not even sure that GS/OS can keep up with the theoretically 57,600 available.
Copied from original issue: RasppleII/a2server#35
Hey Ivan, I think I mostly have the adtpro.sh script figured out, but maybe you can provide some of your thinking in a few places. This script and the udev rules are basically why it doesn't work with systemd, but I think I have a handle on how to do that. Mostly. Anyway, let's have a look at the diff:
--- ../../adtpro/build/adtprobase.sh 2015-11-02 07:36:07.000000000 -0800
+++ adtpro.sh.txt 2015-10-30 05:47:22.000000000 -0700
@@ -1,5 +1,6 @@
-#!/bin/sh
-#
+#! /bin/bash
+# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
+
# ADTPro - *nix startup shell script
#
# Note:
That's totally on me. :) I actually didn't check the scripts for bashisms, I just made them all use bash since most of the scripts did. Might wanna revert that for this script if it truly isn't necessary. Anyway…
@@ -12,9 +13,9 @@
#
# Set default ADTPRO_HOME to be the fully qualified
# current working directory.
-export ADTPRO_HOME="`dirname \"$0\"`"
-cd "$ADTPRO_HOME"
-export ADTPRO_HOME=`pwd`
+#export ADTPRO_HOME="`dirname \"$0\"`"
+#cd "$ADTPRO_HOME"
+#export ADTPRO_HOME=`pwd`
# Uncomment and modify one or both of the lines below if you
# want to specify a particular location for Java or ADTPro.
@@ -24,21 +25,74 @@
# export MY_JAVA_HOME=/usr/local/java/bin/
# export ADTPRO_HOME=~/myuser/adtpro
+usageExit () {
+ echo "usage:" 1>&2
+ echo "adtpro.sh [headless] [serial|ethernet|audio|localhost] [serialPortName]" 1>&2
+ exit 1
+}
+
+export ADTPRO_HOME=/usr/local/adtpro
+cd "$ADTPRO_HOME"
+
OS=`uname`
-OS_ARCH=`uname -p`
+OS_ARCH=`uname -m`
+
+[[ $1 == "headless" ]] && { headless=1; shift; } || headless=
+
+if [[ $1 && ( $1 != "serial" && $1 != "ethernet" && $1 != "audio" && $1 != "localhost" ) ]]; then
+ usageExit
+fi
Setting ADTPRO_HOME is obvious. Changing uname -p to uname -m
is less obvious, until you note that uname -p returns unknown on many Linux installations, including the Raspberry Pi. I see you changed how headless is processed here—entirely so you could add the usage message? If so, I'll make the usage message work more the way the rest of the script does and submit that change to David for upstream inclusion.
The real meat follows:
# For Linux, use this:
if [ "$OS" = "Linux" ]; then
+
+ serialPortName=
+ if [[ $1 == "serial" ]]; then
+ if [[ $2 ]]; then
+ serialPortName="$2"
+ [[ ${serialPortName:0:5} == "/dev/" ]] && serialPortName=${serialPortName:5}
+ if [[ ! -c /dev/$serialPortName ]]; then
+ echo "Serial port $serialPortName not found." 1>&2
+ usageExit
+ fi
+ elif [[ -c /dev/ttyUSBlower ]]; then
+ serialPortName=ttyUSBlower
+ elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
+ serialPortName=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-)
+ elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
+ serialPortName=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | head -1 | cut -c 6-)
+ else
+ echo "No eligible USB-to-serial adapter found." 1>&2
+ echo "Possible ports:" 1>&2
+ echo " lower USB port"
+ echo " any port on lower USB hub with no other adapters"
+ echo " lowest port on USB hub on upper or lower USB port with multiple adapters"
+ usageExit
+ fi
+ fi
+
+ if [[ $(grep CommPort= /usr/local/adtpro/disks/ADTPro.properties) ]]; then
+ if [[ $serialPortName ]]; then
+ sed -i "s/^CommPort=.*$/CommPort=\/dev\/$serialPortName/" /usr/local/adtpro/disks/ADTPro.properties &> /dev/null
+ else
+ serialPortName=$(grep 'CommPort=/dev/' ADTPro.properties 2> /dev/null | cut -f 3 -d '/')
+ fi
+ else
+ echo -e "#ADTPro.properties\n#$(date)\nCommPortSpeed=115200\nCommPortBootstrapSpeed=2400\nCommPort=/dev/$serialPortName\nCommPortBootstrapPacing=250\nHardwareHandshaking=false\nSerialIPHost=localhost\nSerialIPPort=1977" > /usr/local/adtpro/disks/ADTPro.properties
+ chmod ugo+w /usr/local/adtpro/disks/ADTPro.properties
+ fi
+
+ ADTPRO_EXTRA_JAVA_PARMS="-Dgnu.io.rxtx.SerialPorts=/dev/$serialPortName"
+
if [ -f /usr/bin/raspi-config ]; then
- export RXTXLIB=lib/rxtx/%RXTX_VERSION%/arm
- ADTPRO_EXTRA_JAVA_PARMS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/ttyAMA0"
+ export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/arm
elif [ "$OS_ARCH" = "i686" ]; then
- export RXTXLIB=lib/rxtx/%RXTX_VERSION%/i686-pc-linux-gnu
+ export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
else
if [ "$OS_ARCH" = "i386" ]; then
- export RXTXLIB=lib/rxtx/%RXTX_VERSION%/i686-pc-linux-gnu
+ export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
else
- export RXTXLIB=lib/rxtx/%RXTX_VERSION%/x86_64-unknown-linux-gnu
+ export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/x86_64-unknown-linux-gnu
fi
fi
fi
That's a big bite. There's a fair number of lines we can ignore due to the minus side being a script template. I note you try to force ONE serial port to be used here, and we've already discussed how the UDEV rules you've got now just won't quite do going forward. But I also think upstream does it wrong here by hard-coding ttyUSB0 and ttyAMA0 on the Pi. Probably the best solution all around is either a UDEV rule that does what /dev/serial SHOULD do (enumerate all serial devices, not just the USB ones), or to write some function that can build a list of serial devices. The trick there is that we'd probably prefer /dev/serial/by-path/ entries over /dev/tty* entries for those that have them.
Is there a reason you create the ADTPro properties file here instead of just running it? with serial and the port name to use in the environment?
Let's skip the OS X and Solaris stuff since that's just template related.
-if [ "$1x" = "headlessx" ]; then
- shift
- if [ "$1x" = "x" ] || [ ! -f /usr/bin/xvfb-run ]; then
- if [ ! -f /usr/bin/xvfb-run ]; then
+if [[ $headless ]]; then
+ if [[ ! $1 || ! -f /usr/bin/xvfb-run ]]; then
+ if [[ ! -f /usr/bin/xvfb-run ]]; then
echo "Headless operation requires xvfb."
+ usageExit
else
- echo "usage: adtpro.sh [ headless ] [ serial | ethernet | audio | localhost ]"
+ echo "Headless operation requires a communication mode (e.g. serial)."
+ usageExit
fi
exit 1
else
There's the rest of the headless and other argument parsing getting moved around. I'd probably change those [[ ! -f /usr/bin/xvfb-run ]]
's to ! command -v xvfb-run >/dev/null
. That's another one for upstream too.
@@ -75,5 +130,13 @@
fi
fi
+if [[ $serialPortName && $(ps aux | grep "/sbin/getty.*$serialPortName") ]]; then
+ sudo pkill -f "/sbin/getty.*$serialPortName"
+fi
+sudo pkill -f [A]DTPro
cd "$ADTPRO_HOME"/disks
-$HEADLESS"$MY_JAVA_HOME"java -Xms256m -Xmx512m "$TWEAK" $ADTPRO_EXTRA_JAVA_PARMS -cp ../lib/%ADTPRO_VERSION%:../"$RXTXLIB"/../RXTXcomm.jar:../lib/AppleCommander/AppleCommander-%AC_VERSION%.jar org.adtpro.ADTPro $*
\ No newline at end of file
+$HEADLESS"$MY_JAVA_HOME"java -Xms256m -Xmx512m "$TWEAK" $ADTPRO_EXTRA_JAVA_PARMS -cp ../lib/ADTPro.jar:../"$RXTXLIB"/../RXTXcomm.jar:../lib/AppleCommander/AppleCommander-ac.jar org.adtpro.ADTPro $* &
+if [[ $1 == "serial" ]]; then
+ echo "Starting up on interface $serialPortName. Please wait..."
+fi
+sleep 30
What was the reason for the sleep 30 in there? I'm betting that's the reason why my Pi's boot process seems to halt an annoyingly long time vs. vanilla Raspbian. ;)
That bit there with disabling a getty that might be running on the serial port in question probably isn't real systemd compatible. Likely the ttyusbhandler also breaks it. That'll want to be a systemd service file most likely. Fortunately, it's actually pretty easy to write those so that you can configure what port causes stuff to happen and what to have happen, and make the whole thing contingent on there being enough system running to actually have the thing start.
Anyway, if there's anything you can add to all of that, lemme know!
Thanks! :)
From @IvanExpert on October 25, 2015 21:55
They're adequate, but not up to date with latest A2CLOUD, and probably too long.
Copied from original issue: RasppleII/a2server#21
The vsd script is a great addition to ADTPro. However opening a Telnet session might not be the most straight forward thing to do in every scenario. Therefore I created a simplistic web front-end for vsd. I see two primary usage scenarios:
The web front-end makes use of the web server capabilities built into the standard Python libraries. So it doesn't depend on any additional installation:
#!/usr/bin/python
import BaseHTTPServer, subprocess, urlparse
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
url = urlparse.urlsplit(self.path)
if url.path != '/':
self.send_error(404)
return
if url.query:
query = dict(urlparse.parse_qsl(url.query))
if 'vsd1' in query:
subprocess.call(['vsd', '-1', query['vsd1']])
if 'vsd2' in query:
subprocess.call(['vsd', '-2', query['vsd2']])
try:
vsd1 = subprocess.check_output(['vsd', '-1'])[17:-1]
vsd2 = subprocess.check_output(['vsd', '-2'])[17:-1]
except subprocess.CalledProcessError:
vsd1 = ""
vsd2 = ""
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write('<html>\n')
self.wfile.write(' <head>\n')
self.wfile.write(' <title>A2CLOUD</title>\n')
self.wfile.write(' <meta name="viewport" content="width=device-width, initial-scale=1">\n')
self.wfile.write(' </head>\n')
self.wfile.write(' <body style="font-family:sans-serif;">\n')
self.wfile.write(' <h2>A2CLOUD</h2>\n')
self.wfile.write(' <form action="/"><p>Drive 1\n')
self.wfile.write(' <input type="text" name="vsd1" value="' + vsd1 + '" size="60" maxlength="120">\n')
self.wfile.write(' <input type="submit" name="s" value="Mount">\n')
self.wfile.write(' </form>\n')
self.wfile.write(' <form action="/"><p>Drive 2\n')
self.wfile.write(' <input type="text" name="vsd2" value="' + vsd2 + '" size="60" maxlength="120">\n')
self.wfile.write(' <input type="submit" name="s" value="Mount">\n')
self.wfile.write(' </form>\n')
self.wfile.write(' </body>\n')
self.wfile.write('</html>')
httpd = BaseHTTPServer.HTTPServer(('', 80), Handler)
httpd.serve_forever()
Beside using the HTML form it is as well possible to mount a disk image by specifying it right in the URL like http://<ip addr of Raspple II/?vsd1=<disk image name to mount in drive 1>
which allows for further scenarios.
The web front-end can be started together with the ADTPro server by saving it as /usr/local/bin/webvsd.py, making it executable and adding it to adtpro-start right after the call to adtpro.sh as sudo nohup webvsd.py &> /dev/null &
.
From @IvanExpert on October 25, 2015 21:58
Currently, Raspberry Pi's can have their physical USB ports identified and named "ttyUSBupper" and "ttyUSBlower" by UDEV rules, making it easy to connect the right cable to the right port in all cases.
Since non-Pi computers may have any configuration of USB ports and hubs, the behavior is to create "ttyUSBupper" being an alias to the first item inserted, and "ttyUSBlower" being the second item inserted. If they're both present at boot time, they'll be assigned randomly. I don't know if there's any better solution to this, but it seems inelegant.
Copied from original issue: RasppleII/a2server#23
Keyspan made several USB-serial devices popular with Mac users, including one with dual mini-DIN8 connectors. They work with Linux if you have the firmware, and it comes with the standard Linux-firmware package in Ubuntu, Fedora, and just about everything but Debian. Debian specifically excludes it in a pedantic (so, basically Debianish) interpretation of its license. We oughtta provide them as a package or something.
From @IvanExpert on October 25, 2015 22:9
This is probably my most wished-for enhancement. Create a BASIC.SYSTEM utility called Amper-Term
which would allow you to send single Bash instructions, and get responses, from AppleSoft, e.g. "&vsd2 loderunner.dsk", "&ls", etc, rather than requiring a comm program to formally log into the shell and leave what you're doing. A GS/OS CDA would be phenomenal as well, as it would allow you to quickly change disks in the virtual drives, or even grab stuff off the internet via "&wget" or what have you.
Copied from original issue: RasppleII/a2server#26
Spectrum's ANSI emulation gets ASCII 130 and 137 wrong; it's supposed to be a lowercase e with a "forward slash" accent (acute), but it has a "two dots" (diaeresis/umlaut) instead. (Compare against 160, which is lowercase a with acute.)
In addition, ASCII 137 is wrong. It's supposed to be lowercase e with diaeresis (two dots), but it's got a tilde instead (compare against 164, which is lowercase n with tilde).
Possibly character 130 should be moved to 137, though one of its dots looks wide compared to other diaeresis characters (compare against 129 or 132).
These can be verified by using the Links browser in Spectrum's ANSI emulation, with CP437 from the character set menu, and viewing: http://www.kostis.net/charsets/cp437.htm
I have emailed Ewen about this.
Now that MacIP has been demonstrated to work via macipgw, it would make sense to install Marinetti along with Spectrum in A2SERVER.
Marinetti is shipped as a single-file installer, plus a separate update to its TCPIP component. We would have to decide if we provide the installer for the user to run, or attempt to replicate its function (by figuring out what it installs where, or by asking Andrew Roughan) so that it is preinstalled along with is update (which seems preferable).
(Whoops, meant to file this under A2SERVER.)
According to the TTYtter page at http://www.floodgap.com/software/ttytter/, TTYtter is now a dead project. You can find oystter/oystter forked as a replacement which the author endorses insofar as he endorses anything at all for Twitter.
We should probably migrate to oystter in the future as a result.
Thought the overview page is still gone, the actual links that were on Apple's older software downloads page still work. These should be used, with fallback to Internet Archive if they don't download. This has been done in A2SERVER (but should be double-checked), and should also be done in A2CLOUD (including support scripts like the gsport wrapper).
The vsd script (http://appleii.ivanx.com/prnumber6/a2cloud-insert-a-disk-image/) kills the ADTPro process but it doesn't kill the xvfb process. So every disk image change leaves you with another unused xvfb.
From @IvanExpert on October 25, 2015 22:13
Per clarification from David in recent CSA2 posting.
Copied from original issue: RasppleII/a2server#32
From @IvanExpert on October 25, 2015 21:51
For speed, ADTPro now loads the disk image of a virtual disk into RAM rather than access the disk file each time out, and then flushes on writes (or might even do live writes as it used to do live reads). This causes issues if the disk image is modified outside of ADTPro. ADTPro should have a way of recognizing changes to the disk image it has in RAM. This is really an ADTPro issue, and has been submitted there:
http://sourceforge.net/p/adtpro/feature-requests/10/
Copied from original issue: RasppleII/a2server#19
On irc, Edward reports errors pop up while installing A2CLOUD:
Failed to fetch http://ppa.launchpad.net/menulibre-dev/devel/ubuntu/dists/wheezy/main/source/Sources
Failed to fetch http://ppa.launchpad.net/menulibre-dev/devel/ubuntu/dists/wheezy/main/binary-armhf/Packages
These are harmless, but they represent wheezy basically being long in the tooth and no longer supported by the 3rd party folks who provide parts of the standard Raspbian distribution from RPF used to build our image.
This can be resolved by removing the offending /etc/apt/sources.list(.d) entries when the next wheezy-based A2CLOUD release gets rolled. In the meantime I need to start redoing ADTPro for Jessie so we can get a new release out the door. :P The error doesn't hurt anything on our end, but it's worth fixing.
The warning in the gsport wrapper script to disable mouse integration when running under Virtualbox needs updating for Virtualbox 5, as it was moved into a different menu.
From @IvanExpert on October 25, 2015 22:24
UTF-16 is 2-4 byte (not relevant, but just saying)
UTF-8 is one byte 0-127, ASCII compatible; 2-6 bytes for everything else
this screws up Apple II term programs for non-ASCII chars (e.g. hyphen, smart quote)
ISO-8859-* is one byte 0-255, with 128-255 variying by "part" 1-16
ISO-8859-1 is "Latin-1", revision is ISO-8859-15, others are langauge-specific
Apple II text comm programs are going to display 0-127 anyway, since
Apple II 128-255 are redundant or MouseText
"ANSI" in a comm program means pseudo VT-100, and may also mean the "DOS CodePage 437"
(IBM PC character set), as is the case with Spectrum ANSI emulation
So it doesn't matter which ISO-8859 part, since the comm programs aren't going to use
any of them. The main thing is that it's one byte per character, unlike UTF-8
TERM=vt100 on Pi makes Linux programs mostly display B&W, and makes ctrl-chars
display on Spectrum ANSI
TERM=pcansi on Pi makes Linux programs do color for Spectrum ANSI
(TERM=ansi just breaks everything)
LANG=en_US (as opposed to en_US.UTF-8) gets you ISO-8859-1, which is better for
Spectrum ANSI, but the en_US ISO-8859-1 locale has to be available (from raspi-config)
See A2CLOUD setup for how to generate locales from Linux prompt
ProTERM VT-100 just repeats 128-255; ANSI BBS uses ASCII and mousetext to approximate DOS Code Page 437
Spectrum VT-100 is sort of arbitrary in 128-255
TERM=VT100 doesn't work with "ANSI" emulation because it outputs ctrl-O around
text styling which is a displayed character in CP437
single-byte:
ASCII is single byte 0-127 (0-31 are "C0" control codes, plus 127 is DEL)
ISO-8859-* (1-16) is ASCII for 0-127, 128-159 are "C1" control codes, 160-255 are regional characters
ISO-8859-1 is standard "Latin-1", ISO-8859-15 is updated for Euro and other chars
Microsoft has its own "codepage" numbers for character sets.
Codepage 437 (aka "ANSI BBS") is the DOS character set: ASCII from 32-126,
plus printable chars at 1-31 and 127-255; (all chars are also represented in UTF-8)
"Linedraw" font for Windows provides characters 128+ for codepage 437: ftp://ftp.microsoft.com/Softlib/MSLFILES/GC0651.EXE (use 64.4.17.176 if doesn't resolve)
Also "Terminal" font in XP provides most of it; Courier New is a Unicode font with most of the same characters
Windows-1252 (codepage 1252) is ISO-8859-1 with additional chars from 128-159 instead of C1,
including all chars in ISO-8859-15
Mac has "macintosh" or "MacRoman" encoding which is ASCII for 0-127 and
its own characters for 128-255
UTF-8 characters 0-127 is same as ASCII
UTF-8 characters 128+ are between two and four bytes and can represent everything (I guess)
UTF-16 characters are between two and four bytes, and are endian-sensitive
UTF-32 characters are always four bytes, and are endian-sensitive
Copied from original issue: RasppleII/a2server#39
From @IvanExpert on October 25, 2015 21:3
Install Alpine or Mutt, plus (important) an easy configuration script, which also has preset settings for common providers. This has not been done thus far because ease of use has been a design goal and neither Alpine nor Mutt is easy to configure; Mutt is probably the nicer choice but it is entirely dependent on a separately created configuration file. A sample configuration-creator script for Mutt was created by Alistair Ross at:
http://pastebin.com/Mawvd2pZ
I have not done anything further with it, however perhaps it can be used as a starting point.
Copied from original issue: RasppleII/a2server#14
One way that people use to Raspple is to call BBSs. tcpser helps to do that. I'd like to have the latest tcpser included in Raspple versions. It's important to use Fozztexx's version as it fixed a long-standing issue with other versions of tcpser which couldn't connect to telnetd servers.
We see it all the time, folks popping in to #a2c.chat on irc.a2central.com (c'mon and join us) fumbling with irssi because they don't know the commands yet, and they didn't learn to use screen, so they tend to not hang around, and they don't know how it all works. And it's not that there are many commands, it's just that irssi assumes you know something about it like slash commands, and that's not a safe assumption. (I tend to prefer weechat to irssi, but it's even more "we assume you know what you're doing or read the manual".)
Just a reminder this needs fixin'.
From @IvanExpert on October 25, 2015 22:11
Something to consider -- automatic login (like Raspbian has on first boot), which then throws you into a menu to do common stuff, rather than getting the screen full of text telling you what to type after you log in now.
Copied from original issue: RasppleII/a2server#28
Was putting a2chat on a separate RPi that doesn't have a2cloud installed, because I reboot my RasppleII-RPi too much. ;) and found this typo in the /usr/local/bin/a2chat. Pulled down the latest a2cloud zip to verify it's in there and yuppers, it is.
supo apt-get -y update
should be
sudo apt-get -y update
Note to self: learn code pulls and commits of fixes, instead of this.
A change in A2SERVER between 1.2.5 and 1.5.0 is that your AppleTalk shares no longer live in /media. Now they're in /srv which is more Linuxically Standardistically correct.
A2CLOUD tries to do stuff with A2SERVER in a block presently at lines 540-571 of setup.txt. This needs to be updated. It could either be made to work with either path, or just be changed to use /srv exclusively.
Trivia: Read ∀ as "for all".
Linapple's upstream developer released version 2b, but never put it into any SCM that I know of. However sometime perhaps before or after that was done, maxolasersquad/linapple was created from version 2a. There are 14 forks of this repository, and these do not encompass all versions of linapple on Github—and none of them have the 2b changes. Here's the hierarchy as best I can sort it:
Of these, @cpressey (catseye tech) and @ghedger are the ones to be watching because they've both been actively working on this codebase. Looks like ghedger has called it 2.1 at this point, but cpressey has important stuff like … a fix to the 777 problem. A merge is needed here.
And that's just one fork tree!
There you have it. That's what I was able to find easily. Several sites redistribute these or the original in various states from 2 to 2b. Two major forks. Which one do we use or do we try to encourage work toward a merge? AppleWin has had massive development since these trees and a fresh port to SDL2 could be a path of low resistance but that further fractures things and it's way beyond the scope of a2cloud and beyond my free time to even begin thinking about actively maintaining an emulator.
None of these projects is blessed by the initial creator to my knowledge who did not respond to email on the subject, so I'm inclined to assume that if someone wants claim to the successor of linapple, those others who want to see linapple still be a thing can declare by acclamation that the title is theirs. Ideally we would rebase some forks at that point.
Unzip is installed by a2cloud's setup.txt only after it may have been used at least once. It should be installed first.
This issue does not affect any system that has first installed A2SERVER, or one that has has been installed via Raspple II which automatically installs it before A2CLOUD.
With MacIP proven to work via macipgw, once we provide some user-friendly presentation in A2SERVER, we should document that in order to use it with A2CLOUD, AppleShare must be installed. Perhaps this belongs on the GSport AppleTalk documentation page.
It's undesirable to preinstall AppleShare unless the user wants it, because AppleTalk must be enabled on slot 1 or 2 to avoid two startup-blocking error screens. (It is preinstalled when using the netboot version, because of course then AppleTalk is already enabled.)
TL;DR: Redcarpet/GFM sucks for writing HTML manuals. Kramdown doesn't, but has bugs in GFM mode. Kramdown syntax differs from GFM for a few things. I blame John Gruber. README.md files need to be written in GFM for GitHub.
Longer explanation in commit log for 60d54a6:
Fix the remaining fixme's
Note: I've been using kramdown to generate HTML, and kramdown generates
id tags for headings automatically. Redcarpet does not, and in fact
Redcarpet (the official GFM implementation) does not support any
alternative means of specifying id, class, or other HTMLish things. In
other words, redcarpet is extremely limited compared to kramdown.
So just use kramdown right? Well it's not that easy. Kramdown can
parse GFM, but it has some bugs when doing so. For example, when fixing
these last fixmes, I had some level three headings, ### stuff
, which
were rendered as <p>### stuff</p>
rather than <h3>stuff</h3>
. Sigh.
When rendering the HTML using kramdown's own syntax variant, it did this
right. But kramdown's variant has some subtle differences in things
like fenced code blocks. GitHub will not render kramdown's fenced code
bocks properly, and kramdown will not render GitHub's fenced code blocks
properly unless set to parse GFM.
In terms of source code, that only matters for README.md, since GitHub
only renders README.md for you. You can't get it to render other .md
files even if you want it to. That said, using two different Markdown
variants causes problems with confusion regarding what is and isn't
valid Markdown syntax. As it is, vim doesn't fully recognize either
syntax using any syntax plugin I've tried. And the precise syntax used
on the GitHub website is obviously going to be GitHub's.
All of this to basically more eloquently say, DAMMIT JOHN GRUBER! He
readily acknowledges the limitations of the reference implementation of
Markdown, suggests anyone who wants to improve the syntax go and do so,
yet stubbornly refuses any effort to standardize these extensions. He's
encouraging a thousand niche forks, but actively trying to sabotage any
standardization. This is a widely acknowledged irritation with the
Markdown family of markup languages.
My notion going forward is that we should assume README.md is in GFM,
and all other .md files are Kramdown format. If I can come up with a
clever way to indicate this syntactic difference, I will.
One really useful feature of vim is that it is intelligent about line endings on text documents, if you're consistent about line endings on text documents. :)
There are todos and tounix tools which are over-glorified versions of the tr shell command, and someone could write a tomac as well. But at least as useful would be an editor that didn't depend on your file being in a particular line ending. It should be a couple of lines of code to try and figure out what the dominant line ending type is and go with that.
Hello,
I've been trying to rebuild my A2CLOUD.DSK from scratch, but when looking for the A2CLOUD.PO, it's not there on the a2cBinaryURL site. Same with the *.DSK. Is there a new repository for the files required to build an A2CLOUD disk image from scratch? I did build the disk image, but the STARTUP BAS file appears corrupt, so I'm trying to get a working STARTUP program for the .DSK to boot off of.
FILE: ivan.sh
a2cBinaryURL="http://blocksfree.com/downloads"
### DiskImage: Building images from scratch
sudo pkill -f ADTPro
if [[ ! $buildA2CloudDisk ]]; then
echo "A2CLOUD: Downloading 800K disk image..."
wget -qO $a2CloudDisk "${a2cBinaryURL}/a2cloud/A2CLOUD.PO"
echo "A2CLOUD: Downloading 140K disk image..."
wget -qO $a2CloudDisk140 "${a2cBinaryURL}/a2cloud/A2CLOUD.DSK"
fi
I just created a LICENSE.md for A2CLOUD in f6ecf67. This file is a little muddy because we have a script under one license that goes and just installs a bunch of stuff under a whole bunch of licenses. This issue will somewhat auto-resolve itself as we gear up for jessie support and building this thing as a proper Debian package. Just documenting the issue for now so it's known that we're aware it needs some cleaning up. :)
http://appleii.ivanx.com/prnumber6/category/a2cloud/ seems to give the impression that the ADTPro server is running after installing Raspple II. However this seems not to be true. While I can imagine that there might be reasons not to start the ADTPro server by default (maybe conflicts on serial ports?) it would be great if http://appleii.ivanx.com/prnumber6/category/a2cloud/ would reflect the actual situation, tell how to start ADTPro and provide hints on how to make it start on boot.
Proposal for @RasppleII/owners (and anyone else interested)
Currently we try to do clever things with the Raspberry Pi to assign certain USB serial devices to certain functions. If you don't speak Linux geek, I'll explain in a moment--if you do, here's the script that generates the current udev rules file:
if [[ ! -f /etc/udev/rules.d/50-usb.rules ]]; then
echo "A2CLOUD: Creating device rules for USB ports..."
udevLines=
if [[ $isRpi ]]; then
# assign ttyUSBupper, or ttyUSBupper_hubXX, for shell usb-to-serial adapter
# assign ttyUSBlower, or ttyUSBlower_hubXX, for ADTPro usb-to-serial adapter
# (A/A+ direct attach is always ttyUSBlower;
# hub attached to A/A+ will be ttyUSBupper on port 2, and ttyUSBlower on port 3)
udevLines+='KERNEL=="ttyUSB*", KERNELS=="1-1:1.0", SYMLINK+="ttyUSBlower", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBlower"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*1-1:1.0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBlower"\n'
udevLines+='KERNEL=="ttyUSB*", KERNELS=="1-1.2:1.0", SYMLINK+="ttyUSBupper", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBupper"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*1-1.2:1.0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBupper"\n'
udevLines+='KERNEL=="ttyUSB*", KERNELS=="1-1.3:1.0", SYMLINK+="ttyUSBlower", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBlower"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*1-1.3:1.0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBlower"\n'
for i in {1..25}; do
ii=$(printf %02d $i)
udevLines+='KERNEL=="ttyUSB*", KERNELS=="1-1.2.'$i':1.0", SYMLINK+="ttyUSBupper_hub'$ii'", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBupper_hub'$ii'"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*1-1.2.'$i':1.0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBupper_hub'$ii'"\n'
udevLines+='KERNEL=="ttyUSB*", KERNELS=="1-1.3.'$i':1.0", SYMLINK+="ttyUSBlower_hub'$ii'", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBlower_hub'$ii'"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*1-1.3.'$i':1.0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBlower_hub'$ii'"\n'
done
else
# on non-Pi installations, assign ttyUSBupper to ttyUSB0 and ttyUSBlower to ttyUSB1
udevLines+='KERNEL=="ttyUSB0", SYMLINK+="ttyUSBupper", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBupper"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*ttyUSB0*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBupper"\n'
udevLines+='KERNEL=="ttyUSB1", SYMLINK+="ttyUSBlower", RUN+="/usr/local/sbin/ttyusbhandler add ttyUSBlower"\n'
udevLines+='ACTION=="remove", ENV{DEVPATH}=="*ttyUSB1*", RUN+="/usr/local/sbin/ttyusbhandler remove ttyUSBlower"\n'
fi
echo -e "$udevLines" | sudo tee /etc/udev/rules.d/50-usb.rules >/dev/null
else
echo "A2CLOUD: Device rules for USB ports already exist."
fi
That spits out this 106 line file on Raspberry Pi (only 4 lines on other systems, but you probably need to reconfigure it yourself in that case). What those lines do is create one or two theoretically human-readable aliases to your USB to serial devices, based on where they're plugged in. See, normally Linux names the first one it sees ttyUSB0, and the second ttyUSB1, etc. The problem with USB is that if you boot the machine up with the devices already plugged in, they'll be in a certain order. It might not be the same order it would've been if you plugged them into a running system.
Linux has some "persistent name" rules already written, but they're not reliable because it's stupidly possible to have two indistinguishable USB-serial devices. In fact not only is it possible, but with most cheap serial dongles based on counterfeit Prolific chips or those "quality" Keyspan devices all of us Mac users have laying around somewhere, it's almost guaranteed.
@IvanExpert solved this by declaring the top USB port (on the original Raspberry Pi model B) was for serial console, the bottom was for ADTPro, and the GPIO serial was for the Apple II Pi card. The model A would be the "lower" port if you didn't have a hub plugged in. And that was perfectly logical until the model B+ came out with four ports, the ODROIDs and Banana Pis came out with arbitrary USB configurations, and of course none of this applies to people running A2CLOUD on Intel machines or under VMs.
Assuming all of that isn't a factor, the current rules will create ttyUSBupper OR ttyUSBupper_hub## for devices found on a hub. Usually there's only one of these, but there might not be, and if there's more than one you need a script to determine which of those to use. It turns out that ttyusbhandler has that logic, but a new standard Linux thingy called systemd does not. And that breaks stuff in irritating ways.
So we need new rules that always use one name! And while we're at it, can we possibly make the one name something useful? Yes we can!
#98-a2cloud.rules
# Information about how to configure serial ports manually here.
# Nutshell version is uncomment and replace KERNEL= with your match
# condition. Add some mechanism to let the user modify this part of
# the file and let us blow the rest away...
#
#KERNEL="ttyUSB0" \
# TEST!="/dev/ttyADTPro" SYMLINK+="ttyADTPro" GOTO="a2cloud_devices_end"
#KERNEL="ttyUSB1" \
# TEST!="/dev/ttyConsole" SYMLINK+="ttyConsole" GOTO="a2cloud_devices_end"
# Default serial ports for ADTPro and serial console
# # Please see <url> for details
SUBSYSTEM="tty" KERNELS=="1-1:1.0" TEST!="/dev/ttyADTPro" SYMLINK+="ttyADTPro"
SUBSYSTEM="tty" KERNELS=="1-1.3:1.0" TEST!="/dev/ttyADTPro" SYMLINK+="ttyADTPro"
SUBSYSTEM="tty" KERNELS=="1-1.3.*:1.0" TEST!="/dev/ttyADTPro" SYMLINK+="ttyADTPro"
SUBSYSTEM="tty" KERNELS=="1-1.2:1.0" TEST!="/dev/ttyConsole" SYMLINK+="ttyConsole"
SUBSYSTEM="tty" KERNELS=="1-1.2.*:1.0" TEST!="/dev/ttyConsole" SYMLINK+="ttyConsole"
# Prevent conflicts with ttyADTPro==ttyConsole
SYMLINK=="ttyADTPro" SYMLINK=="ttyConsole" SYMLINK=-"ttyADTPro"
LABEL="a2cloud_devices_end"
# Run A2CLOUD services when devices are added
ACTION=="add" SYMLINK=="ttyADTPro" RUN+="/usr/local/sbin/ttyusbhandler remove ttyADTPro"
ACTION=="remove" ENV{DEVLINKS}=="/dev/ttyADTPro" RUN+="/usr/local/sbin/ttyusbhandler remove ttyADTPro"
ACTION=="add" SYMLINK=="ttyADTPro" RUN+="/usr/local/sbin/ttyusbhandler remove ttyADTPro"
ACTION=="remove" ENV{DEVLINKS}=="/dev/ttyADTPro" RUN+="/usr/local/sbin/ttyusbhandler remove ttyADTPro"
This is still a work in progress and so far it addresses only the Raspberry Pi case for now. Let's start in the second major blob for explanations. The "KERNELS" bit is udev voodoo that specifies the USB bus and where on it the serial device lives. SYMLINK+= adds an alias to whatever the system wants to call the device to the name we want to use for it, either ttyADTPro or ttyConsole. The TEST!= bit is there to make sure that if the alias already exists, we don't try to overwrite it. I'm not 100% sure that's necessary in udev, but better safe than sorry until I do know.
Next, the possibility exists that a device might somehow get assigned both the symlinks for ttyADTPro and ttyConsole. That's a no-no and will break A2CLOUD. It doesn't happen with the rules above as written, but if you start adding your own, it might happen. So if it does, we use it as a console so that you can hopefully use the console if you need it to fix the problem. :)
Next are the rules for starting and stopping things. We're still using ttyusbhandler for that, though its logic would become a bit simpler.
That leaves the old rules. I think we probably ought to leave them there if they exist. They're a "dropping", but we don't know if they're used in any config or not. Best to just make ttyusbhandler silently ignore requests using those names.
Thoughts?
Non-Linux systems are relatively easy to determine what are and are not serial ports because they follow some semblance of rules for consistent device naming around serial and other devices. Linux doesn't.
And for all the crazy things Linux does with udev and sysfs and procfs to tell you all about the system, there's no simple way to say, "hi, what serial ports do you have?" Fortunately, on any Linux system modern enough for us to care about for this purpose, we do have some help. First, all serial devices are listed in /sys/class/tty
. Here's mine on a Debian nettop system:
tjcarter@shiro:~$ ls /sys/class/tty/
console@ tty11@ tty17@ tty22@ tty28@ tty33@ tty39@ tty44@ tty5@ tty55@ tty60@ tty9@ ttyUSB1@
ptmx@ tty12@ tty18@ tty23@ tty29@ tty34@ tty4@ tty45@ tty50@ tty56@ tty61@ ttyS0@ ttyUSB2@
tty@ tty13@ tty19@ tty24@ tty3@ tty35@ tty40@ tty46@ tty51@ tty57@ tty62@ ttyS1@ ttyUSB3@
tty0@ tty14@ tty2@ tty25@ tty30@ tty36@ tty41@ tty47@ tty52@ tty58@ tty63@ ttyS2@
tty1@ tty15@ tty20@ tty26@ tty31@ tty37@ tty42@ tty48@ tty53@ tty59@ tty7@ ttyS3@
tty10@ tty16@ tty21@ tty27@ tty32@ tty38@ tty43@ tty49@ tty54@ tty6@ tty8@ ttyUSB0@
Obviously not all of those are tty entries. But if you happen to limit the list a little, you'll see the ones that are:
tjcarter@shiro:~$ ls /sys/class/tty/*/device/driver
/sys/class/tty/ttyS0/device/driver@ /sys/class/tty/ttyS3/device/driver@ /sys/class/tty/ttyUSB2/device/driver@
/sys/class/tty/ttyS1/device/driver@ /sys/class/tty/ttyUSB0/device/driver@ /sys/class/tty/ttyUSB3/device/driver@
/sys/class/tty/ttyS2/device/driver@ /sys/class/tty/ttyUSB1/device/driver@
That's more like it! The indicated entries in /sys/class/tty
are real serial ports that exist on my system at the moment. There's also a little more information in /proc
:
tjcarter@shiro:~$ cat /proc/tty/drivers
/dev/tty /dev/tty 5 0 system:/dev/tty
/dev/console /dev/console 5 1 system:console
/dev/ptmx /dev/ptmx 5 2 system
/dev/vc/0 /dev/vc/0 4 0 system:vtmaster
usbserial /dev/ttyUSB 188 0-511 serial
serial /dev/ttyS 4 64-95 serial
pty_slave /dev/pts 136 0-1048575 pty:slave
pty_master /dev/ptm 128 0-1048575 pty:master
unknown /dev/tty 4 1-63 console
tjcarter@shiro:~$ sudo cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:unknown port:000003F8 irq:4
1: uart:unknown port:000002F8 irq:3
2: uart:unknown port:000003E8 irq:4
3: uart:unknown port:000002E8 irq:3
tjcarter@shiro:~$ sudo cat /proc/tty/driver/usbserial
usbserinfo:1.0 driver:2.0
0: module:ftdi_sio name:"FTDI USB Serial Device" vendor:0403 product:6001 num_ports:1 port:0 path:usb-0000:00:1d.7-6.1
1: module:ftdi_sio name:"FTDI USB Serial Device" vendor:0403 product:6001 num_ports:1 port:0 path:usb-0000:00:1d.7-6.2
2: module:keyspan name:"Keyspan 2 port adapter" vendor:06cd product:0110 num_ports:2 port:0 path:usb-0000:00:1d.7-6.3
3: module:keyspan name:"Keyspan 2 port adapter" vendor:06cd product:0110 num_ports:2 port:1 path:usb-0000:00:1d.7-6.3
You can determine how useful any of that is. I find it somewhat annoying to access this information using bash because I just don't have access to the tools to make use of it. I can use the sysfs interface though just fine from bash. I'd want to use python for sure if I were trying to use the older /proc interface.
That leads to the next problem: USB serial devices are wont to move around across reboots if you plug one into a USB port that is enumerated sooner on the next reboot. /dev/serial/by-id
and /dev/serial/by-path
contain entries that don't change upon reboots, supposedly. We'll use by-id
since it's human-readable after a fashion. We'll implement something that basically works(ish) using bash:
#! /bin/bash
# vim: ts=4 sw=4 tw=78 ft=sh
for device in /dev/tty*; do
# See if it's a real device
devname=$(basename $device)
if [ -d /sys/class/tty/$devname/device/driver ]; then
# According to sysfs, it is
# Now see if there's a /dev/serial entry for it
for devserial in /dev/serial/by-id/*; do
if [ "$(readlink -f $devserial)" = "$device" ]; then
# Yes, use that instead
device="$devserial"
fi
done
devices="${devices:+$devices }$device"
fi
done
# Show what we found
for dev in $devices; do
echo "$dev"
done
Doing the same in python looks like this and is a little more robust:
#! /usr/bin/env python3
# vim: ts=4 sw=4 tw=78 ft=python
import os
import glob
from pprint import pprint
# The by-id paths are supposed to be stable across reboots
deviceIdx = {}
for symlink in glob.glob('/dev/serial/by-id/*'):
deviceIdx[os.path.realpath(symlink)] = symlink
devices = []
ttySysDir = '/sys/class/tty'
for tty in os.listdir(ttySysDir):
# VCs, ptys, etc don't have /sys/class/tty/<tty>/device/driver's
if os.path.exists(os.path.join(ttySysDir, tty, 'device/driver')):
# Appears to be a real serial device
device = os.path.join('/dev', tty)
if device in deviceIdx:
# use the stable name
devices.append(deviceIdx[device])
elif os.path.exists(device):
devices.append(device)
# Show what we found
pprint(devices)
The output of these commands:
tjcarter@shiro:~$ ./findserial.sh
/dev/ttyS0
/dev/ttyS1
/dev/ttyS2
/dev/ttyS3
/dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FTGUK9F7-if00-port0
/dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FT8ZQX5V-if00-port0
/dev/serial/by-id/usb-Keyspan__a_division_of_InnoSys_Inc._Keyspan_USB_Serial_Adapter-if00-port0
/dev/serial/by-id/usb-Keyspan__a_division_of_InnoSys_Inc._Keyspan_USB_Serial_Adapter-if00-port1
tjcarter@shiro:~$ ./findserial.py
['/dev/ttyS0',
'/dev/ttyS1',
'/dev/ttyS2',
'/dev/ttyS3',
'/dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FTGUK9F7-if00-port0',
'/dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FT8ZQX5V-if00-port0',
'/dev/serial/by-id/usb-Keyspan__a_division_of_InnoSys_Inc._Keyspan_USB_Serial_Adapter-if00-port0',
'/dev/serial/by-id/usb-Keyspan__a_division_of_InnoSys_Inc._Keyspan_USB_Serial_Adapter-if00-port1']
Of course, you can see there that my FTDI adapters have serial numbers. The Keyspan doesn't, so if I plugged another one in, we'd be back to the same enumeration problem again—cheap crap usually doesn't have unique serial numbers. Which is funny because the Keyspan adapters were anything but cheap at the time they were sold!
Anyway, here's what by-path
entries look like:
tjcarter@shiro:~$ ls /dev/serial/by-path/
pci-0000:00:1d.7-usb-0:6.1:1.0-port0@ pci-0000:00:1d.7-usb-0:6.3:1.0-port0@
pci-0000:00:1d.7-usb-0:6.2:1.0-port0@ pci-0000:00:1d.7-usb-0:6.3:1.0-port1@
Kind of misleading because at first glance it looks like those are PCI devices. You have to read backwards: Ports in a tree of USB devices in a tree of PCI devices. That's gonna make users' heads hurt. It makes MY head hurt, and I know what I'm looking at!
I don't mind presenting the user with the by-path device node when we have one, provided that we give them some human-readable output. The problem is that we don't have human-readable output for the UART drivers, other than that they're UARTs. It'd be real easy to figure out on my little nettop that the four UART ports don't physically exist if we translate that for the user so they know to look for physical serial ports on the computer. There aren't any. (I really ought to see if I can disable those in the BIOS, but left them on while I was working here.)
Anyway, this sufficiently defines the problem I think. The solution is there, but it isn't ever going to be pretty due to crappy hardware and software design. The best we can do is try to tell the user what we find in as much detail as we can to help them identify which ports are which, and make sure it works before we make any assumptions that it will.
While running adtpro client with vsdrive running breaks the ADTPro server requiring that the USB port physically be removed and reinserted to get it to work again. Raspberry Pi 3, fresh install, Raspbian Stretch.
There are a couple of problems using Apple II Pi with the Raspberry Pi model 3B.
I think A2Pi is important for Raspple II and it needs to work well. The use of the A2Pi card is perhaps less critical at this stage because you can't get them presently and they work just fine with the boards that were on sale at the time you could. But I think we should get @dschmenk involved with the discussion of what maybe we can do about it. :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.