mirror of
https://github.com/RasppleII/a2cloud.git
synced 2025-04-22 18:37:07 +00:00
Compare commits
159 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3e69bf5ae7 | ||
|
6f75afe092 | ||
|
eafb691671 | ||
|
82016a398c | ||
|
34798abf11 | ||
|
1f8afb6010 | ||
|
74bb88d1d4 | ||
|
7ee6c4bad6 | ||
|
55c53b9c10 | ||
|
123a592f61 | ||
|
38d2808d9a | ||
|
c7818ab379 | ||
|
f7e46cb167 | ||
|
331f4be653 | ||
|
3e961cd4b5 | ||
|
6602f8491c | ||
|
36bf72e9d5 | ||
|
f295f42dff | ||
|
c0bf3d2214 | ||
|
0ae0ce519d | ||
|
c779085100 | ||
|
affeb535a0 | ||
|
f6555c024c | ||
|
42ac9cc6ef | ||
|
099f5b3f44 | ||
|
602b4f5fba | ||
|
2aa5e92c78 | ||
|
c260ff9d74 | ||
|
3431bfa812 | ||
|
639c86b96f | ||
|
b1ffe93b14 | ||
|
8b5149fe52 | ||
|
822f54794d | ||
|
238db84c78 | ||
|
41f829e4dd | ||
|
c0da2b5301 | ||
|
6ec5ce310f | ||
|
4bf2edc2ea | ||
|
f731c75a5c | ||
|
c8a3a4ada5 | ||
|
a84c0b2e8e | ||
|
4ae325f990 | ||
|
d30c9eb409 | ||
|
8831ee59a4 | ||
|
1301e430ce | ||
|
744210338c | ||
|
30ccb87cd8 | ||
|
2d65ec0ee0 | ||
|
e10e80e517 | ||
|
2b9cd2c95d | ||
|
a3d67123cc | ||
|
4bee0fee5a | ||
|
6fb6a068e2 | ||
|
eb6ace7850 | ||
|
a12c3ccbcf | ||
|
f156fcb6af | ||
|
32a599c93d | ||
|
f9e0861005 | ||
|
f1a77b537d | ||
|
491226e721 | ||
|
37e833f8a8 | ||
|
313e478ed9 | ||
|
d58da9307a | ||
|
55485fc50c | ||
|
49fa865ec5 | ||
|
11f239d730 | ||
|
51d825a2b6 | ||
|
11cf8145da | ||
|
1824c4aa43 | ||
|
78d247a0ef | ||
|
40b55a599e | ||
|
83a40d7af6 | ||
|
5ad310b567 | ||
|
4a90902dc8 | ||
|
2550d3556c | ||
|
045f971e9c | ||
|
944a25e50c | ||
|
43bcf19c5b | ||
|
c794e646de | ||
|
62817abe28 | ||
|
1335c067b2 | ||
|
35841f2b1d | ||
|
deda15c48b | ||
|
2a99f51d17 | ||
|
a91ea1aef6 | ||
|
eddaf0d72d | ||
|
82697c0945 | ||
|
e3f7ca02b5 | ||
|
dc6745bb21 | ||
|
600de08a2c | ||
|
a1a26ae6fb | ||
|
e65da70236 | ||
|
d1273a9150 | ||
|
fe7e2f058a | ||
|
a23b98fd92 | ||
|
378282fea6 | ||
|
a34e0f9698 | ||
|
9606193bd7 | ||
|
a3c4a2a4c8 | ||
|
23f03694b7 | ||
|
cfbe5c2794 | ||
|
660eb80ec8 | ||
|
c94853ef0c | ||
|
7da9bf63ac | ||
|
66d67df3c6 | ||
|
546deb63d9 | ||
|
6422658d43 | ||
|
6c59cae33b | ||
|
e57b75c952 | ||
|
762e24ef1a | ||
|
cdd613f757 | ||
|
cbe9548964 | ||
|
91809be8d4 | ||
|
87e27f8209 | ||
|
ac54df546e | ||
|
4d95c2e0ac | ||
|
6228e52b06 | ||
|
9eeb44b7c9 | ||
|
4d9990cd91 | ||
|
17872f2bbf | ||
|
ac3a35a68e | ||
|
c61f6ebb3b | ||
|
e3a0bd40d4 | ||
|
109462c5a6 | ||
|
b5e430819f | ||
|
7ada5a8bca | ||
|
da08d8249c | ||
|
bdfbbe61c3 | ||
|
a9120efa39 | ||
|
358c9a3d6d | ||
|
695eeec4d9 | ||
|
d3bf03680f | ||
|
17b13fa9b4 | ||
|
f97f6b1b2a | ||
|
e53ea4ac8e | ||
|
a4444bfd32 | ||
|
82b9d9d13d | ||
|
0667ebe009 | ||
|
f6ecf674d2 | ||
|
60377b7e6b | ||
|
ab9428bbeb | ||
|
35c18b4ced | ||
|
c939de8c32 | ||
|
c7431dbf52 | ||
|
c74c1af3b7 | ||
|
6897a33672 | ||
|
d79a6d7714 | ||
|
20815bf010 | ||
|
e943aa7823 | ||
|
2718d81572 | ||
|
9b23c44b00 | ||
|
cf727f8f75 | ||
|
45044692c5 | ||
|
2f6f4ddb12 | ||
|
4b8dea38d2 | ||
|
c2deff81ae | ||
|
cf4bc9ea92 | ||
|
b07ab9faad | ||
|
e2623cbcf9 |
0
.a2cloud_source
Normal file
0
.a2cloud_source
Normal file
407
CHANGELOG.md
Normal file
407
CHANGELOG.md
Normal file
@ -0,0 +1,407 @@
|
||||
# Changelog
|
||||
|
||||
Notable changes to a2cloud will be documented here. This document is for
|
||||
users, rather than developers. If you want an immutable history of all
|
||||
changes made, you can follow git history so far as it goes and we'll try
|
||||
to preserve more detail from the time before as we may. We will try to
|
||||
update older entries to reflect changes that have been reverted, please
|
||||
file an issue if you notice something the changelog says should work, and
|
||||
it no longer does.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Installation run from source tree (or git repo) no longer downloads any
|
||||
part of the installation from the internet since you've already got it.
|
||||
|
||||
- Created new scripts for a2cloud-setup and a2cloud-update to use that
|
||||
actually download the source tree and install from that. This avoids
|
||||
some potential bugs and better security and integrity checks later.
|
||||
|
||||
- New scripts in scripts/ you can run separately from the full installer,
|
||||
install_archive_tools, install_comm_tools, and install_emulators. There
|
||||
are others too, but these are the ones you might want to be able to run
|
||||
yourself.
|
||||
|
||||
- lftp, an advanced ftp client with lots of power, tab-completion, etc.
|
||||
Much more user-friendly than the basic ftp client while maintaining the
|
||||
command line interface. Supports mirroring, if you want that.
|
||||
|
||||
- mc (Midnight Commander), a Norton Commander style file manager. It too
|
||||
has its own FTP interface capability and might be considered a possible
|
||||
alternative to cftp, assuming you become comfortable with using mc for
|
||||
file management tasks.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Actually install unzip as prerequisite for undoit.
|
||||
|
||||
- Correct typo in a2chat
|
||||
|
||||
- No longer disables ::1 for exim. Having that used to cause an error, so
|
||||
we'd modified your configuration to remove the use of IPv6. We don't
|
||||
undo that if it was done in the past, but a new install won't do it.
|
||||
|
||||
### Changed
|
||||
|
||||
- Unexpectedly large version bump. Because the last released version was
|
||||
1.9.x, we haven't really got version-space for pre-releases, so we've
|
||||
bumped the pre-release tree to version 2.9.0 to give us plenty of room
|
||||
for pre-releases before a major version bump.
|
||||
|
||||
- Oysttyer version we install is now 2.9.1.
|
||||
|
||||
- Modified the format of the this changelog ultimately to be hopefully
|
||||
more user-friendly.
|
||||
|
||||
- Ivan Drucker has agreed to allow his scripts and future work to be
|
||||
released under the CC0 Public Domain release. Previously his scripts were
|
||||
under the "WTFPL". Creative Commons is less "expressive", but more legally
|
||||
correct in countries without explicit support for public domain or a sense
|
||||
of humor. ;)
|
||||
|
||||
- On desktop Debian systems, we now use default-jre instead of Oracle.
|
||||
For now we're still using Oracle on RPi, but that may soon change.
|
||||
|
||||
### Removed
|
||||
|
||||
- cftp has been removed. It was always highly-buggy alpha software and
|
||||
it didn't do much. If you want that kind of interface with some more
|
||||
maturity, connect to your ftp server with lynx. Or see above.
|
||||
|
||||
- The ttytter command is gone. TTYtter is abandoned upstream, but the
|
||||
developer's allowed others to take up development under a new name.
|
||||
Oysttyer may already be installed on your system and we've already been
|
||||
using it, just continuing to call it tttytter.
|
||||
|
||||
- The A2CLOUD_SCRIPT_URL and A2CLOUD_BINARY_URL environment variables,
|
||||
which probably nobody else was using since they were kind of only for
|
||||
a2cloud developers anyway, are gone. Just run scripts from the source
|
||||
tree you're working on now.
|
||||
|
||||
- The raspbian-update script is gone. Also gone are the aliases for
|
||||
raspi-config, appleiipi-update, and rasppleii-update. (FIXME: a2server
|
||||
has debupdate as a replacement. Do we want it in a2cloud?)
|
||||
|
||||
## [1.9.0] - 2016-07-23
|
||||
|
||||
* [40b55a5] fix motd, and icon creation error messages in setup
|
||||
* [83a40d7] make "baud" command compatible with systemd
|
||||
|
||||
## [1.8.3] - 2016-01-19
|
||||
|
||||
### Added
|
||||
* First release from GitHub version
|
||||
|
||||
### Changes by Ivan Drucker
|
||||
* fix bug where language isn't properly selected for A2 login
|
||||
* download from Apple first, then Internet Archive as fallback
|
||||
|
||||
### Changes by Joseph Carter
|
||||
* Archived Ivan Drucker's A2CLOUD site in source tree
|
||||
* As this package will be native package, convert its changelog to Debian
|
||||
style. Developers may want to install the devscripts package and have a
|
||||
look at the manpage for dch(1). Mac developers, if you use TextExpander,
|
||||
I can share a snippet for RFC-2822 compliant dates.
|
||||
* Make adtpro.sh delay only happen when running interactively.
|
||||
* Begin using $PATH to find things so we can replace local binaries with
|
||||
packages later on.
|
||||
* Use unar package if it's available.
|
||||
* Use download.apple.com for Apple // files when possible, with archive.org
|
||||
as a fallback.
|
||||
* setup.txt is now 7-bit clean (the only reason it wasn't is the extended
|
||||
changelog at the bottom)
|
||||
|
||||
### Changes from 1.8.2
|
||||
* download from Internet Archive
|
||||
|
||||
## [1.8.1] - 2015-05-05
|
||||
|
||||
* ADTPro 2.0.1
|
||||
* Apple II Pi client 1.5
|
||||
* set JAVA_HOME correctly for Java 8 (Pi, webupd8, Ubuntu for Pi 2B)
|
||||
|
||||
## [1.8.0] - 2015-03-17
|
||||
|
||||
* compatible with every Raspberry Pi, including Raspberry Pi 2 Model B
|
||||
* GSport installed for non-Raspberry Pi computers, with option for
|
||||
new GS/OS+Spectrum installation, or GSport Internet Starter Kit premade
|
||||
image
|
||||
* add Links web browser
|
||||
* desktop shortcuts and Apple II menu group for emulators and ADTPro
|
||||
* adds LXTerminal to desktop for non-A2Pi version
|
||||
* new "a2cloud-update os" command will perform full Raspple II update,
|
||||
including Raspbian OS and NOOBS install manager, A2CLOUD, A2SERVER, and
|
||||
Apple II Pi
|
||||
* ProDOS instruction screen on GSOS install
|
||||
* provide via downloaded program that is dd notrunc'd over PRODOS (instead
|
||||
of writeCharsHex)
|
||||
* figure out why lines in autostart are supposed to start with @ (daemon;
|
||||
restarts command on crash)
|
||||
* install AppleCommander-1.3.5.13id (so Spectrum installer will work)
|
||||
* fix mouse in VirtualBox framebuffer, requires uninstalling (or temporarily
|
||||
disabling, if possible) VirtualBox guest additions
|
||||
* offer to uninstall vboxguestmodule if gsport is in run console
|
||||
* rename slot6drive1 and 2 to not contain "-blank" in slot6.tgz and gsport
|
||||
and kegs (x86) archives
|
||||
* fix webupd8team getting added twice to sources.list
|
||||
* command "a2cloud-update rasppleii" to update raspple ii
|
||||
* prevent samba update causing dialog to come up
|
||||
* create rasppleii-update
|
||||
* make rasppleii-update universal even for non-Raspple II installs -- it's
|
||||
just raspbian-update + a2cloud-update + a2server-update
|
||||
* download gsport and kegs icons
|
||||
* no longer opens terminal window (since icons exist)
|
||||
* create aliases for raspbian-update and rasppleii-update
|
||||
* update A2CLOUD help file and aliases for GSport
|
||||
* create raspbian-update
|
||||
* update a2cloud-help
|
||||
* update motd (vm, raspple ii/a2cloud-pi) for gsport
|
||||
* see if shortcuts work in Raspple II 110
|
||||
* check for /etc/xdg/lxsession/LXDE-pi; if so:
|
||||
* create ~/.config/menus/lxde-pi-applications.menu, with reference to
|
||||
/etc/xdg/menus/lxde-pi-applications.menu
|
||||
* no xrandr VBOX0 on the Pi; remove it if present (a2cloud 1.7.x may have
|
||||
put it there)
|
||||
* user groups for pi user not only apple2
|
||||
* gsport-setup and kegs post install text to say ctrl-F12 for reboot
|
||||
* add "links" to motd and help
|
||||
* added 'disablesafemode' to NOOBS recovery.cmdline (also in
|
||||
raspbian-update) to make it work on (at least) my A+
|
||||
* option for GISK rather than clean setup for GSport on x86
|
||||
* provide actual command for clean GSOS + Spectrum install, which is what
|
||||
gsport runs if no HD available
|
||||
* provide command for clean GSOS install for KEGS
|
||||
* add Dave's preflight/postflight stuff (groups, ownership permissions) for
|
||||
gsport
|
||||
* install libpcap0.8-dev as part of Apple II Pi, GSport install, and GSport
|
||||
launcher
|
||||
* make kegs-setup
|
||||
* make kegs splash text
|
||||
* doesn't add VirtualBox 800x600 if installing on Pi
|
||||
* stop xrandr from being added multiple times to autostart in VirtualBox
|
||||
* only install vbox 800x600 if running in VirtualBox
|
||||
* disable screen blanking in vbox console
|
||||
* disable screensaver/blanking in vbox LXDE
|
||||
* don't create LXTerminal desktop shortcut if RPi
|
||||
* -6 arg provides empty ProDOS disks in S6D1 and S6D2 to GSport/KEGS to
|
||||
speed things up
|
||||
* can test if password is "raspberry" or "apple2" and advise accordingly
|
||||
* enable Uthernet by default in gsport-setup
|
||||
* enable AppleTalk Turbo by default in gsport-setup
|
||||
* make kegs run as root
|
||||
* consolidate gsport-setup and kegs-setup
|
||||
* gsport-setup is gsport, gsport-setup -k is kegs
|
||||
* clean up KEGS/GSport installer sections to be consistent
|
||||
* create kegs-setup placeholders that call gsport-setup -k
|
||||
* gsport-setup only offer system disks/GSport if java/acmd are available
|
||||
* suppress policykit error that appears after upgrade (see
|
||||
http://www.raspberrypi.org/forums/viewtopic.php?t=98617 for details)
|
||||
* see if uninstalling vbox additions is really necessary (nope)
|
||||
|
||||
## [1.7.2] - 2015-02-07
|
||||
|
||||
* supports Raspberry Pi Model A and A+ (and Pi 2 Model B)
|
||||
* manually triggers udev rules during startup if ttyusbhandler script didn't
|
||||
execute (resolves issues with Raspbian 2015-01-31/kernel 3.18)
|
||||
* doesn't provide Java space warning if java is already installed
|
||||
|
||||
## [1.7.1] - 2014-08-11
|
||||
|
||||
* A2CLOUD is no longer “beta” on non-Raspberry Pi computers
|
||||
* A2CLOUD includes KEGS and Linapple on debian_x86
|
||||
* kegs launch script creates additional symlink called ROM
|
||||
* linapple launch script sets up framebuffer and udev mouse rule
|
||||
* A2CLOUD has a faster install script for non-Raspberry Pi computers
|
||||
(downloads debian7_x86 and rpi binaries)
|
||||
* unbit/unexec/bsq archive tools are installed
|
||||
* perl version for ttytter not hardcoded
|
||||
* apt-get clean after all installs
|
||||
* installer option to compile all rather than download binaries
|
||||
* login message mentions A2SERVER if it is installed
|
||||
* LXDE terminal window now in global autostart (opens for any user)
|
||||
* LXDE desktop defaults to 800x600 if running in VirtualBox VM
|
||||
|
||||
## [1.7.0] - 2014-08-02
|
||||
|
||||
* a2cloud-setup installs Java 8 if not already installed
|
||||
|
||||
## [1.6.9] - 2014-07-24
|
||||
|
||||
* ADTPro 2.0.0 (quicker and more reliable transfer; selectable filenames from
|
||||
list)
|
||||
* new A2CLOUD disks with A2PI client 1.8
|
||||
* tested working on Raspberry Pi Model B+ (use USB ports closest to Ethernet
|
||||
jack for ttyUSBlower and ttyUSBupper)
|
||||
|
||||
## [1.6.8] - 2014-04-07
|
||||
|
||||
* ADTPro 1.3.0
|
||||
* tests for adtpro existence with either adtpro.sh or ADTPro.html
|
||||
* TTYtter installs properly on non-Pi systems
|
||||
|
||||
## [1.6.7] - 2014-02-19
|
||||
|
||||
* cppo installed from a2cloud directory on web server (a2server has symlink)
|
||||
* fixed cppo -e bug that always created a resource fork file even if there
|
||||
is no resource fork
|
||||
* shk2image leaves nothing behind in /tmp
|
||||
* wildcard copy all files on A2PI disk except PRODOS/BASIC.SYSTEM/*A3* to
|
||||
A2CLOUD disks when building
|
||||
* A2CLOUD boot floppy contains A2PI client version 1.4
|
||||
* update before install for a2chat, a2news, kegs, kegs-setup, linapple,
|
||||
gsport, gsport-setup
|
||||
* a2cloud-setup updates a2news/a2chat/kegs/kegs-setup/linapple wrappers
|
||||
* disables IPv6 for exim4 to properly prevent startup error messages;
|
||||
restores log folder if not there
|
||||
* A2CLOUD boot floppy splash screen provides simple menu for virtual drives,
|
||||
Apple II Pi, or BASIC
|
||||
* A2CLOUD.HDV is now called A2CLOUD.PO (a symbolic link called A2CLOUD.HDV
|
||||
is still there for backwards compatibility/habits)
|
||||
* renamed MACRO files on server to be .txt and moved to files
|
||||
* added screen to a2cloud-help
|
||||
|
||||
## [1.6.6] - 2014-02-17
|
||||
|
||||
* beta support for Debian and Ubuntu Linux on non-Pi machines
|
||||
* compiles binaries rather than downloads if not running on Pi
|
||||
* gets and supports Oracle x86 Java if not on Pi
|
||||
* installs X11 and LXDE if not installed
|
||||
* ttyUSBupper is always ttyUSB0, ttyUSBlower is always ttyUSB1
|
||||
* adtpro.sh supports USB-to-serial on all architectures
|
||||
* installs curl if not installed (for ttytter)
|
||||
* ttytter support for color and avoiding non-ASCII characters when running
|
||||
under Screen
|
||||
* opens LXTerminal window by default when starting graphical desktop
|
||||
* a2cloud-setup installs Screen if not already installed, also -v arg
|
||||
* a2cloud-setup shows installed and available versions
|
||||
* a2cloud-setup -y bypasses all prompts (removed -n)
|
||||
* a2cloudrc is now downloaded rather than created by script
|
||||
* LANG is now set in /usr/local/etc/a2cloud-lang rather than in a2cloudrc
|
||||
* fixed bug which checked for nulib2 instead of unar when seeing if needing
|
||||
to compile
|
||||
* setup exits properly whether run via source or shell
|
||||
* moved cftp to files
|
||||
|
||||
## [1.6.5] - 2014-02-05
|
||||
|
||||
* can use "term mono" and "term color" instead of "term vt100" and "term
|
||||
pcansi", "none" also works
|
||||
* minor reorganization of configuration of a2cloudrc and screenrc
|
||||
|
||||
## [1.6.4] - 2014-01-31
|
||||
|
||||
* support for "screen" command to allow switching between multiple terminals
|
||||
on Apple II
|
||||
* term command now has -f argument to force emulation setting
|
||||
* bash.bashrc now calls /usr/local/etc/a2cloudrc, which in turn calls
|
||||
a2cloud-aliases
|
||||
|
||||
## [1.6.3] - 2014-01-23
|
||||
|
||||
* Set TTYtter to always use -ssl mode, which is required by Twitter after
|
||||
14-Jan-14.
|
||||
* Set TTYtter to avoid display of non-ASCII characters on serial port shell
|
||||
* Set TTYtter to use color ANSI text (for IIgs) if shell is currently set to
|
||||
display it
|
||||
* Provided TTYtter readline module for enhanced input with -readline option
|
||||
* Added "appleiipi-update" command
|
||||
|
||||
## [1.6.2 - 2014-01-19
|
||||
|
||||
* Improved display of non-ASCII characters in Apple II terminal emulation
|
||||
programs by using ISO-8859 charset for serial port instead of UTF-8
|
||||
* adds 'term' command for setting vt100 or ANSI emulation
|
||||
This should help with Spectrum's ANSI display
|
||||
* perform apt-get clean at end of A2CLOUD install
|
||||
* Added "sciibin" and "unblu" for converting BinSCII and Binary II files
|
||||
* add 300 to the supported rates of baud command, in case you *really* want
|
||||
to kick it old school
|
||||
* alias a2cloud-update to a2cloud-setup
|
||||
* cmd line options and prompts to install everything or install individual
|
||||
pieces
|
||||
* revised intrudiction info in setup script
|
||||
|
||||
## [1.6.1] - 2014-01-14
|
||||
|
||||
* Added "telnet" and "ttytter" (Twitter client)
|
||||
* fix for network boot failure when set up under v1.6
|
||||
* prevents exim4 error messages after Tin installation
|
||||
|
||||
## [1.6.0] - 2013-12-31
|
||||
|
||||
### Changed in 1.6.0
|
||||
* include check for ADTPro updates
|
||||
* remove hardcoding of ADTPro version in favor of script variable
|
||||
* asks for prodos volume name for new disk image; 8192 max
|
||||
* fixed order of files on 140K disk to be consistent with 800K disk
|
||||
* adtpro-start start now checks for USB adapter before starting
|
||||
* restarts ADTPro server on vsd1/vsd2 after prompting
|
||||
* created vsdsync alias to adtpro-restart; acmd warns if neeed
|
||||
* acmd warns if vsd1/vsd2 changes, and advises vsdsync if so
|
||||
* acmd now provides acmd help even on AppleCommander error
|
||||
* updates ADTPro/VSDRIVE to 1.2.9
|
||||
* pro: VSDRIVE can be run via ProDOS program launcher, not just BASIC
|
||||
* pro: much faster virtual drive read performance
|
||||
* con: short delay on vsd# commands
|
||||
* con: need to type vsdsync after changing active virtual drive image
|
||||
directly on the Pi
|
||||
|
||||
### Changed in 1.5.3
|
||||
* gets motd from web
|
||||
* sets password to apple2
|
||||
* if A2SERVER is installed, shares the ADTPro disks folder as ADTDISKS on the
|
||||
network
|
||||
* don't prompt for restart after install by default
|
||||
* avahi-daemon installed (so "raspberrypi.local" works as on Bonjour-enabled
|
||||
machines)
|
||||
* include backup server for shrinkit
|
||||
|
||||
## [1.5.2] - 2013-12-22
|
||||
|
||||
### Changed in 1.5.2
|
||||
* Apple II Pi is now installed with GSport emulator and “apple2user” packages
|
||||
* speedier install by downloading A2CLOUD disk images instead of building them
|
||||
* cleans up after installation
|
||||
* misc bug fixes
|
||||
* -h option for installer help
|
||||
|
||||
### Changed in 1.5.1
|
||||
* added "dos2pro" command
|
||||
|
||||
## [1.5] - 2013-12-01
|
||||
|
||||
* Adds IRC and newsreader clients (Irssi and Tin) and, with shortcuts for
|
||||
Apple II community ("a2chat" and "a2news" commands)
|
||||
* adds KEGS and LinApple emulators
|
||||
* installs Apple II Pi
|
||||
* easy installation via Raspple II
|
||||
|
||||
## [1.2.3] - 2013-11-30
|
||||
|
||||
### Changed after 1.2.3
|
||||
* Date is approximated in changelog format conversion
|
||||
* Rewrote entry to combine multiple different changelogs
|
||||
|
||||
### Changed in 1.2.3
|
||||
* A2PI client version 1.3 added to A2CLOUD disk
|
||||
|
||||
### Changed in 1.2.2
|
||||
* download pre-compiled unar/lsar, nulib2, and cftp if possible
|
||||
* install only runtime dependencies for these tools if compiling them is
|
||||
unnecessary
|
||||
* console (built-in serial) login disabled, to allow Apple II Pi to have
|
||||
that port
|
||||
* installs xrdp/tightvncserver for remote desktop access from another
|
||||
computer
|
||||
* adds DSK2FILE image utility to A2CLOUD disk
|
||||
|
||||
## [1.0] - 2013-09-02
|
||||
|
||||
* first proper release with full documentation, bug fixes, and demo video
|
||||
|
||||
## [0.99beta] - 2013-07-27
|
||||
|
||||
* internet access and virtual drives for any Apple II via a Raspberry Pi;
|
||||
introduced at KansasFest 2013
|
121
COPYING_CC0.txt
Normal file
121
COPYING_CC0.txt
Normal file
@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
18
LICENSE.md
Normal file
18
LICENSE.md
Normal file
@ -0,0 +1,18 @@
|
||||
License for A2CLOUD
|
||||
===================
|
||||
|
||||
a2cloud was written by:
|
||||
|
||||
- [Ivan Drucker (2013-2017)][ivanx]
|
||||
- [T. Joseph Carter (2015-2018)][iKarith]
|
||||
|
||||
To the extent possible under law, the person who associated CC0 with
|
||||
a2cloud has waived all copyright and related or neighboring rights
|
||||
to a2cloud.
|
||||
|
||||
You should have received a copy of the CC0 legalcode along with this
|
||||
work in the file named COPYING_CC0.txt. If not, see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
|
||||
[ivanx]: http://ivanx.com/
|
||||
[iKarith]: https://blocksfree.com/
|
1599
docs/ivanx/index.md
1599
docs/ivanx/index.md
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ! $(dpkg -l irssi 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing irssi..."
|
||||
supo apt-get -y update
|
||||
sudo apt-get -y install irssi &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-n" && $2 ]]; then
|
||||
nickname=$2
|
||||
elif [[ $1 == "-n" ]]; then
|
||||
nickname="0"
|
||||
elif [[ -f ~/.irssi/a2c.nickname ]]; then
|
||||
nickname=$(cat ~/.irssi/a2c.nickname)
|
||||
else
|
||||
nickname=
|
||||
fi
|
||||
|
||||
while [[ ! $nickname || ! $(grep -i '^[a-z_\-\\^{}|`][a-z0-9_\-\\^{}|`]*$' <<< $nickname) ]]; do
|
||||
echo -n "Enter a nickname for chat (to change later, use 'a2chat -n'): "
|
||||
read
|
||||
nickname=$REPLY
|
||||
done
|
||||
|
||||
mkdir -p ~/.irssi
|
||||
echo $nickname > ~/.irssi/a2c.nickname
|
||||
|
||||
if [[ -f ~/.irssi/startup ]]; then
|
||||
mv ~/.irssi/startup ~/.irssi/startup.orig
|
||||
fi
|
||||
echo -e "/network add -autosendcmd '/join #a2c.chat' Palomino.A2\n/server add -auto -network Palomino.A2 irc.a2central.com\n" > ~/.irssi/startup
|
||||
|
||||
if [[ -f ~/.irssi/config ]]; then
|
||||
cp ~/.irssi/config ~/.irssi/config.orig
|
||||
fi
|
||||
|
||||
irssi -n $nickname
|
||||
|
||||
rm ~/.irssi/startup &> /dev/null
|
||||
if [[ -f ~/.irssi/startup.orig ]]; then
|
||||
mv ~/.irssi/startup.orig ~/.irssi/startup
|
||||
fi
|
||||
|
||||
rm ~/.irssi/config &> /dev/null
|
||||
if [[ -f ~/.irssi/config.orig ]]; then
|
||||
mv ~/.irssi/config.orig ~/.irssi/config
|
||||
fi
|
@ -1,87 +0,0 @@
|
||||
# A2CLOUD aliases:
|
||||
|
||||
alias a2cloud-setup='wget -qO /tmp/a2cloud-setup ivanx.com/a2cloud/setup/; source /tmp/a2cloud-setup'
|
||||
alias a2cloud-help='(IFS=""; while read thisLine; do [[ ${#thisLine} -eq 0 ]] && echo || echo "$(tput bold)${thisLine%% *}$(tput sgr0) ${thisLine#* }"; done < /usr/local/etc/a2cloud-help.txt | more)'
|
||||
alias a2cloud-version='cat /usr/local/etc/A2CLOUD-version'
|
||||
alias a2cloud-update='a2cloud-setup'
|
||||
|
||||
alias system-shutdown='sudo shutdown -h now'
|
||||
alias system-restart='sudo shutdown -r now'
|
||||
|
||||
|
||||
alias raspi-config='[[ -f /usr/bin/raspi-config ]] && sudo /usr/bin/raspi-config || echo "raspi-config not found. Are you using a Raspberry Pi with Raspbian?"'
|
||||
alias appleiipi-update="sudo apt-get -y update && sudo apt-get -y --force-yes install a2pi apple2user gsport"
|
||||
alias raspbian-update='wget -qO /tmp/raspbian-update ivanx.com/a2cloud/setup/raspbian-update.txt; source /tmp/raspbian-update'
|
||||
alias rasppleii-update='raspbian-update a2cloud a2server'
|
||||
|
||||
|
||||
alias welcome-message-edit='sudo nano /etc/motd'
|
||||
|
||||
alias showip='ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1'
|
||||
alias showmac='ifconfig eth0 | grep "HWaddr" | cut -dH -f2 | cut -c7-23'
|
||||
alias showip-wifi='ifconfig wlan0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1'
|
||||
alias showmac-wifi='ifconfig wlan0 | grep "HWaddr" | cut -dH -f2 | cut -c7-23'
|
||||
alias ifreset='sudo rm /etc/udev/rules.d/70-persistent-net.rules; echo Interfaces removed. You should system-restart now.'
|
||||
|
||||
alias adtpro-stop='sudo pkill -f [A]DTPro'
|
||||
|
||||
|
||||
alias adtpro-restart='sudo pkill -f [A]DTPro; while [[ $(ps aux | grep [A]DTPro) ]]; do sleep 1; done; adtpro-start'
|
||||
|
||||
alias usblogin-off='sudo sed -i "s/^\(.*-scanttyUSB\)/#\1/" /etc/inittab; sudo init q; sudo pkill -f [g]etty'
|
||||
alias usblogin-on='sudo sed -i "s/^#\(.*-scanttyUSB\)/\1/" /etc/inittab; sudo init q'
|
||||
|
||||
|
||||
|
||||
alias term='source term'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
alias vsd1='source /usr/local/bin/vsd -d1'
|
||||
alias vsd2='source /usr/local/bin/vsd -d2'
|
||||
forfloppy () { [[ $1 ]] && { mv "$1" /usr/local/adtpro/disks && echo "moved $1 to /usr/local/adtpro/disks" || echo "Unsuccessful. $1 was not moved."; } || echo "Usage: forfloppy imageFileName"; }
|
||||
|
||||
alias vsdsync='adtpro-restart'
|
||||
|
||||
alias nulib=nulib2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
alias a2cat='acmd -l'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VSD1=$(readlink /usr/local/adtpro/disks/Virtual.po)
|
||||
VSD2=$(readlink /usr/local/adtpro/disks/Virtual2.po)
|
||||
ADTDISKS=/usr/local/adtpro/disks; A2DISKS=/usr/local/adtpro/disks
|
||||
A2CLOUD=/usr/local/adtpro/disks/A2CLOUD.HDV
|
||||
GSDISKS=/usr/local/share/gsdisks
|
||||
GSHD=/usr/local/share/gsdisks/gsoshd.hdv
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ttytter () { ( ansi=; seven=; [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]] && { seven="-seven"; [[ $TERM=="ansi" || $TERM=="pcansi" ]] && ansi="-ansi"; }; [[ -f /usr/bin/ttytter ]] && /usr/bin/ttytter -ssl $seven $ansi $@ || /usr/local/bin/ttytter -ssl $seven $ansi $@ ); }
|
||||
|
||||
|
||||
alias raspple-update='rasppleii-update'
|
||||
alias rasappleii-update='rasppleii-update'
|
||||
alias rasapple-update='rasppleii-update'
|
@ -1,87 +0,0 @@
|
||||
A2CLOUD commands:
|
||||
(note : new commands may be added; use a2cloud-setup to refresh)
|
||||
|
||||
a2cloud-help : show this list of commands
|
||||
a2cloud-version : see installed version of A2CLOUD
|
||||
a2cloud-update : update A2CLOUD, or add features
|
||||
|
||||
system-shutdown : shut down the A2CLOUD machine (or VM)
|
||||
system-restart : shut down and restart the A2CLOUD machine (or VM)
|
||||
|
||||
Raspberry Pi commands, if you're using one:
|
||||
raspi-config : configure Raspberry Pi
|
||||
appleiipi-update : update Apple II Pi and GSport
|
||||
raspbian-update : update Raspbian operating system
|
||||
rasppleii-update : update Raspbian OS, A2CLOUD, A2SERVER, Apple II Pi
|
||||
Apple II Pi: for help, visit http://schmenk.is-a-geek.com/wordpress
|
||||
|
||||
welcome-message-edit : change the welcome message
|
||||
|
||||
showip : show the current ethernet IP address of the server
|
||||
showmac : show the MAC (Ethernet hardware) address of the server
|
||||
showip-wifi : show the current wifi IP address of the server
|
||||
showmac-wifi : show the MAC (wifi hardware) address of the server
|
||||
ifreset : reset all network interfaces (requires restart)
|
||||
|
||||
adtpro-stop : stop the ADTPro service
|
||||
adtpro-start : start the ADTPro service
|
||||
(note: autostarts on appearance of eligible USB-to-serial adapter)
|
||||
adtpro-restart : restart the ADTPro service
|
||||
|
||||
usblogin-off : disable shell login for USB-to-serial adapter
|
||||
usblogin-on : enable shell login with USB-to-serial adapter on upper
|
||||
USB port or hub attached to it, or highest-numbered port on hub
|
||||
attached to lower USB port
|
||||
|
||||
term [-d] mono : use VT-100 (mostly monochrome) emulation in serial
|
||||
shell login for ProTERM, Spectrum, Z-Link, etc. (-d sets default)
|
||||
term [-d] color : use ANSI color and PC graphic text in serial shell
|
||||
login for Spectrum or other PC-ANSI terminal (-d sets default)
|
||||
baud : show or set serial port shell baud rate
|
||||
screen : switch between multiple terminal screens
|
||||
|
||||
vsd1 : show or set the disk image assigned to virtual drive 1
|
||||
vsd2 : show or set the disk image assigned to virtual drive 2
|
||||
forfloppy : move the disk image to the ADTPro disk images folder
|
||||
(/usr/local/adtpro/disks) in preparation for transfer
|
||||
vsdsync : update ADTPro server with the current virtual drive images
|
||||
|
||||
nulib2 : create, extract, and work with NuFX (ShrinkIt) archive files
|
||||
sciibin : decode BinSCII file (they start with 'FiLeStArTfIlEsTaRt')
|
||||
unblu/usq/unbit/unexec : decode Binary II, Squeezed, Executioner,
|
||||
or monitor hex entry EXEC file (old Apple II distribution formats)
|
||||
|
||||
unar : extract non-Apple II archive files (multiformat)
|
||||
lsar : list contents of non-Apple II archive files (multiformat)
|
||||
|
||||
a2cat: catalog Apple II disk image (any format)
|
||||
acmd : do stuff with files inside Apple II disk images
|
||||
mkpo : make blank ProDOS disk image file
|
||||
dos2pro: copy files from DOS 3.3 disk image to ProDOS disk image
|
||||
dopo : convert DOS-ordered disk image to ProDOS, or vice-versa
|
||||
cppo : catalog and copy files from ProDOS image file (slow, but works)
|
||||
shk2image : extract files from ShrinkIt archive to disk image file
|
||||
|
||||
environment variables :
|
||||
$VSD1 = disk image currently "inserted" in virtual drive 1
|
||||
$VSD2 = disk image currently "inserted" in virtual drive 2
|
||||
$ADTDISKS = ADTPro disks directory (/usr/local/adtpro/disks)
|
||||
$A2CLOUD = 800K A2CLOUD disk (/usr/local/adtpro/disks/A2CLOUD.HDV)
|
||||
$GSDISKS = GSport/KEGS disks directory (/usr/local/share/gsdisks)
|
||||
$GSHD = GSport/KEGS hard drive (/usr/local/share/gsdisks/gsoshd.hdv)
|
||||
|
||||
internet tools:
|
||||
ftp : connect to an FTP site (command line operation)
|
||||
cftp : connect to an FTP site (full screen operation)
|
||||
lynx : browse the web (in text only, of course)
|
||||
links : browse the web (alternative to lynx; press ESC for menu)
|
||||
wget : download a single URL from an FTP or web site
|
||||
irssi : IRC chat (general purpose)
|
||||
a2chat : IRC chat (automatically opens to Apple II channel)
|
||||
a2news : read and post on Usenet discussions (default Apple II topics)
|
||||
ttytter : tweet like there's no tomorrow
|
||||
|
||||
emulators:
|
||||
gsport : GSport Apple IIgs emulator
|
||||
kegs : KEGS Apple IIgs emulator
|
||||
linapple : LinApple Apple IIe emulator
|
@ -1,34 +0,0 @@
|
||||
source /usr/local/etc/a2cloud-aliases
|
||||
|
||||
if [[ -f /usr/local/java/bin/java ]]; then
|
||||
export JAVA_HOME=/usr/local/java
|
||||
elif [[ -f /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/jre/bin/java ]]; then # Ubuntu 14.04 RPi2
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle-armhf/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle-armhf
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle
|
||||
fi
|
||||
[[ ! $(grep java <<< $PATH) ]] && PATH=$PATH:$JAVA_HOME/bin
|
||||
|
||||
if [[ -f /usr/local/etc/a2cloud-lang ]]; then
|
||||
lang8bit=$(cat /usr/local/etc/a2cloud-lang)
|
||||
else
|
||||
lang8bit=C
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
myTTY=$(ps hp $(ps hp $(ps hp $$ -o ppid) -o ppid) -o tty)
|
||||
else
|
||||
myTTY=$(tty)
|
||||
export ttyTERM="$TERM"
|
||||
fi
|
||||
if [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]]; then
|
||||
LANG=$lang8bit
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
TERM=$ttyTERM
|
||||
fi
|
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
defaultNNTP="news.aioe.org"
|
||||
defaultGroups="comp.emulators.apple2:\ncomp.sys.apple2:\ncomp.sys.apple2.comm:\ncomp.sys.apple2.marketplace:\ncomp.sys.apple2.programmer:\ncomp.sys.apple2.usergroups:"
|
||||
|
||||
if [[ ! $(dpkg -l tin 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing Tin newsreader..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install tin &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-h" || $1 == "--help" ]]; then
|
||||
echo "Usage: a2news [-s nntpServerAddress] [-m postingEmailAddress] [otherTinOptions]"
|
||||
echo " note: for full options, instead use 'tin'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $1 == "-s" || $1 == "-m" ]]; do
|
||||
if [[ $1 == "-s" && $2 ]]; then
|
||||
nntpServer=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-m" && $2 ]]; then
|
||||
emailAddress=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/.tin
|
||||
|
||||
if [[ ! -f ~/.newsrc ]]; then
|
||||
IFS=''; echo -e "$defaultGroups" > ~/.newsrc
|
||||
fi
|
||||
|
||||
if [[ $nntpServer || ! -f ~/.tin/nntp.server ]]; then
|
||||
[[ ! $nntpServer ]] && nntpServer="$defaultNNTP"
|
||||
echo "$nntpServer" > ~/.tin/nntp.server
|
||||
else
|
||||
nntpServer=$(cat ~/.tin/nntp.server)
|
||||
fi
|
||||
|
||||
if [[ $emailAddress || ! -f ~/.tin/tinrc ]]; then
|
||||
while [[ ! $emailAddress || ! $(grep "@" <<< $emailAddress) || ! $(grep "\." <<< $emailAddress) ]]; do
|
||||
echo -n "Enter the email address you want to post as: "
|
||||
read
|
||||
emailAddress=$REPLY
|
||||
done
|
||||
if [[ -f ~/.tin/tinrc ]]; then
|
||||
sed -i "s/^mail_address=.*$/mail_address=$emailAddress/" ~/.tin/tinrc
|
||||
else
|
||||
echo "mail_address=$emailAddress" > ~/.tin/tinrc
|
||||
fi
|
||||
fi
|
||||
|
||||
NNTPSERVER=$nntpServer tin -r "$@"
|
@ -1,151 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
decToHex () {
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex value from 00-FF
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $arg1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$arg1" 2> /dev/null) == $arg1 ) \
|
||||
&& ( $arg1 -ge 0 ) && ( $arg1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
printf %02X "$arg1"
|
||||
}
|
||||
|
||||
echoerr() {
|
||||
echo "$@" 1>&2;
|
||||
}
|
||||
|
||||
helpExit () {
|
||||
if [[ -s $acmdStdErr ]]; then
|
||||
if [[ $(grep CommandLineHelp $acmdStdErr) ]]; then
|
||||
grep -v ^-[pge][[:space:]] $acmdStdErr | grep -v '^ or' | grep -v 0x2000 1>&2
|
||||
echoerr "-g <imagename> <filename> [<outputFilename>] copy filename out of any"
|
||||
echoerr " disk image. Using - for outputFilename will copy to stdout."
|
||||
echoerr "-e <imagename> <filename> [<outputFilename>] like -g, with conversion"
|
||||
echoerr " to modern file format if possible."
|
||||
echoerr "-p <imagename> <filename> [[$|0x]<type>] [[$|0x]<auxtype>] copy filename"
|
||||
echoerr " into ProDOS disk image. <type> is either three-letter or numeric"
|
||||
echoerr " ProDOS file type (BIN if omitted). Will read from stdin if supplied."
|
||||
echoerr " ProDOS subdirectories in <filename> will be created if needed."
|
||||
echoerr "-c <filename> <imagename> [[$|0x]<type>] [[$|0x]<auxtype>] synonym for -p"
|
||||
echoerr " with filename and imagename reversed."
|
||||
else
|
||||
cat $acmdStdErr
|
||||
fi
|
||||
if [[ $arg1 == "-h" ]]; then
|
||||
exitVal=0
|
||||
else
|
||||
exitVal=1
|
||||
fi
|
||||
else
|
||||
if [[ $vsd1_md5 && ( "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ) ]]; then
|
||||
if [[ "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ]]; then
|
||||
echoerr "One of the virtual drive image files has changed while ADTPro server is active."
|
||||
echoerr " If using VSDRIVE, type 'vsdsync' now to see changes and prevent corruption."
|
||||
fi
|
||||
fi
|
||||
exitval=0
|
||||
fi
|
||||
rm $acmdStdErr &> /dev/null
|
||||
exit $exitVal
|
||||
}
|
||||
|
||||
arg1=$1
|
||||
|
||||
acmdStdErr="/tmp/acmd_$RANDOM$RANDOM"
|
||||
|
||||
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
|
||||
|
||||
if [[ ! $2 || $arg1 == "-h" ]]; then
|
||||
java -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar 2> $acmdStdErr
|
||||
[[ $? -eq 127 ]] && exit 127 || helpExit $arg1
|
||||
fi
|
||||
|
||||
if [[ $arg1 != "-i" && $arg1 != "-ls" && $arg1 != "-l" && $arg1 != "-ll" && $arg1 != "-x" && $arg1 != "-g" && $arg1 != "-e" && $(ps aux | grep [A]DTPro) ]]; then
|
||||
vsd1_md5="$(md5sum /usr/local/adtpro/disks/Virtual.po)"
|
||||
vsd2_md5="$(md5sum /usr/local/adtpro/disks/Virtual2.po)"
|
||||
fi
|
||||
|
||||
if [[ ( $arg1 == "-p" || $arg1 == "-c" || $arg1 == "-g" || $arg1 == "-e" ) && $2 && $3 ]]; then
|
||||
|
||||
getArg=
|
||||
if [[ $arg1 == "-p" ]]; then
|
||||
prodosArg="$3"
|
||||
imageArg="$2"
|
||||
elif [[ $arg1 == "-c" ]]; then
|
||||
prodosArg="$2"
|
||||
imageArg="$3"
|
||||
elif [[ $arg1 == "-g" || $arg1 == "-e" ]]; then
|
||||
fileArg="$3"
|
||||
imageArg="$2"
|
||||
getArg="$arg1"
|
||||
else
|
||||
exit 2;
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
if [[ $getArg ]]; then # get file
|
||||
outFile=
|
||||
[[ $3 && $3 != "-" ]] && outFile="$3"
|
||||
[[ ! $3 ]] && outFile="${2##*/}"
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar $getArg "$imageArg" "$fileArg" $outFile 2> $acmdStdErr
|
||||
else # put file
|
||||
|
||||
# test ProDOS name legitimacy
|
||||
prodosPath=$(tr [:lower:] [:upper:] <<< $prodosArg )
|
||||
IFS_orig="$IFS"; IFS="/";
|
||||
prodosPathParts="$prodosPath"
|
||||
for thisProdosPathPart in $prodosPathParts; do
|
||||
if [[ ${#thisProdosPathPart} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $thisProdosPathPart) ]]; then
|
||||
echoerr "Invalid ProDOS name: $prodosPath"; exit 1;
|
||||
fi
|
||||
done
|
||||
IFS="$IFS_orig"
|
||||
|
||||
# process filetype
|
||||
[[ ${3:0:2} == "0x" ]] && ftArg="\$${3:2}" || ftArg="$3"
|
||||
auxType="$4"
|
||||
|
||||
# assume BIN/$2000 if filetype omitted
|
||||
if [[ ! $ftArg ]]; then
|
||||
ft="BIN"
|
||||
auxType="\$2000"
|
||||
# accept hex or decimal number for file type
|
||||
elif [[ ( ${ftArg:0:1} == '$' && ${#ftArg} -eq 3 ) || $(grep [0-9] <<< ${ftArg:0:1}) ]]; then
|
||||
if [[ ${ftArg:0:1} == '$' ]]; then
|
||||
fc=$(tr [:upper:] [:lower:] <<< ${ftArg:1:2})
|
||||
else
|
||||
fc=$(decToHex $ftArg | tr [:upper:] [:lower:])
|
||||
fi
|
||||
P_00=UNK; P_01=BAD; P_02=PCD; P_03=PTX; P_04=TXT; P_05=PDA; P_06=BIN; P_07=FNT; P_08=FOT; P_09=BA3; P_0a=DA3; P_0b=WPF; P_0c=SOS; P_0f=DIR; P_10=RPD; P_11=RPI; P_12=AFD; P_13=AFM; P_14=AFR; P_15=SCL; P_16=PFS; P_19=ADB; P_1a=AWP; P_1b=ASP; P_20=TDM; P_21=IPS; P_22=UPV; P_29=3SD; P_2a=8SC; P_2b=8OB; P_2c=8IC; P_2d=8LD; P_2e=P8C; P_41=OCR; P_42=FTD; P_50=GWP; P_51=GSS; P_52=GDB; P_53=DRW; P_54=GDP; P_55=HMD; P_56=EDU; P_57=STN; P_58=HLP; P_59=COM; P_5a=CFG; P_5b=ANM; P_5c=MUM; P_5d=ENT; P_5e=DVU; P_60=PRE; P_6b=BIO; P_6d=DVR; P_6e=PRE; P_6f=HDV; P_80=GEZ; P_81=GE1; P_82=GEO; P_83=GE3; P_84=GE4; P_85=GE5; P_86=GE6; P_87=GE7; P_88=GE8; P_89=GE9; P_8a=GEA; P_8b=GEB; P_8c=GEC; P_8d=GED; P_8e=GEE; P_8f=GEF; P_a0=WP_; P_ab=GSB; P_ac=TDF; P_ad=BDF; P_b0=SRC; P_b1=OBJ; P_b2=LIB; P_b3=S16; P_b4=RTL; P_b5=EXE; P_b6=STR; P_b7=TSF; P_b8=NDA; P_b9=CDA; P_ba=TOL; P_bb=DRV; P_bc=LDF; P_bd=FST; P_bf=DOC; P_c0=PNT; P_c1=PIC; P_c2=ANI; P_c3=PAL; P_c5=OOG; P_c6=SCR; P_c7=CDV; P_c8=FON; P_c9=FND; P_ca=ICN; P_d5=MUS; P_d6=INS; P_d7=MDI; P_d8=SND; P_db=DBM; P_e0=SHK; P_e2=DTS; P_ee=R16; P_ef=PAS; P_f0=CMD; P_f9=P16; P_fa=INT; P_fb=IVR; P_fc=BAS; P_fd=VAR; P_fe=REL; P_ff=SYS;
|
||||
ftVar="P_$fc";
|
||||
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc";
|
||||
else
|
||||
ft="$ftArg"
|
||||
fi
|
||||
|
||||
# set auxtype to $0801 for Applesoft programs if not specified
|
||||
[[ $ft == "BAS" && ! $auxType ]] && auxType="\$0801"
|
||||
|
||||
# test for absence of stdin [[ -t 0 ]] and if absent use ProDOS name
|
||||
if [[ -t 0 ]]; then
|
||||
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType < $prodosArg 2> $acmdStdErr
|
||||
else
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType 2> $acmdStdErr
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
imageArg="$2"
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar "$@" 2> $acmdStdErr
|
||||
|
||||
fi
|
||||
|
||||
helpExit
|
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# don't do anything if ADTPro is already running
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
|
||||
1&>2 echo "ADTPro server is already running."
|
||||
|
||||
else
|
||||
|
||||
# look for eligible USB-to-serial adapter
|
||||
ttyUSB=
|
||||
# if lower USB port
|
||||
if [[ -c /dev/ttyUSBlower ]]; then
|
||||
ttyUSB=ttyUSBlower
|
||||
# if hub in lower port, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
# if hub in upper port with multiple adapters, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
fi
|
||||
|
||||
if [[ $ttyUSB ]]; then
|
||||
echo -n "Please wait..."
|
||||
sudo nohup adtpro.sh headless serial &> /dev/null
|
||||
echo "ok."
|
||||
else
|
||||
1>&2 echo "No USB-to-serial adapter found in the lower USB port, or"
|
||||
1>&2 echo " a hub on the lower USB port, or the lowest-numbered port"
|
||||
1>&2 echo " of a hub on the upper USB port. Not starting ADTPro server."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,141 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ADTPro - *nix startup shell script
|
||||
#
|
||||
# Note:
|
||||
# Invoke with the name of the communications button to push
|
||||
# in order to start with that mode active (i.e. './adtpro.sh ethernet')
|
||||
#
|
||||
# You can set two variables here:
|
||||
# 1. $MY_JAVA_HOME - to pick a particular java to run under
|
||||
# 2. $ADTPRO_HOME - to say where you installed ADTPro
|
||||
#
|
||||
# Set default ADTPRO_HOME to be the fully qualified
|
||||
# current working directory.
|
||||
#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.
|
||||
# NOTE: be sure to include a trailing slash on MY_JAVA_HOME,
|
||||
# but not on ADTPRO_HOME.
|
||||
#
|
||||
# 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 -m`
|
||||
|
||||
[[ $1 == "headless" ]] && { headless=1; shift; } || headless=
|
||||
|
||||
if [[ $1 && ( $1 != "serial" && $1 != "ethernet" && $1 != "audio" && $1 != "localhost" ) ]]; then
|
||||
usageExit
|
||||
fi
|
||||
|
||||
# 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-2.2pre2-local/arm
|
||||
elif [ "$OS_ARCH" = "i686" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
if [ "$OS_ARCH" = "i386" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/x86_64-unknown-linux-gnu
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# For OSX, use this:
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
if [ "$OS_ARCH" = "powerpc" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.1-7-bins-r2/Mac_OS_X
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/mac-10.5
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Solaris, use this:
|
||||
if [ "$OS" = "SunOS" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/sparc-sun-solaris2.10-32
|
||||
fi
|
||||
|
||||
# Set up the library location.
|
||||
export TWEAK1="-Djava.library.path="
|
||||
export TWEAK=$TWEAK1$ADTPRO_HOME/$RXTXLIB
|
||||
|
||||
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 "Headless operation requires a communication mode (e.g. serial)."
|
||||
usageExit
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
HEADLESS="xvfb-run --auto-servernum "
|
||||
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.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
|
@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 -ne 300 && $1 -ne 1200 && $1 -ne 2400 && $1 -ne 4800 && $1 -ne 9600 && $1 -ne 19200 && $1 -ne 38400 && $1 -ne 57600 && $1 -ne 115200 ]]; then
|
||||
echo 'Usage: baud [-d] 300|1200|2400|4800|9600|19200|38400|57600|115200';
|
||||
echo ' -d sets default speed for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
else
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/ttyAMA0 .* /ttyAMA0 $1 /" /etc/inittab;
|
||||
sudo sed -i "s/ttyAMA0,[0-9]*/ttyAMA0,$1/g" /boot/cmdline.txt;
|
||||
sudo sed -i "s/\(ttyUSB.*\) .* /\1 $1 /g" /etc/inittab;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $(tty | grep tty) ]]; then
|
||||
stty -F $(tty) $1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tput bold)$(tty) current $(stty -a -F $(tty) | grep -o 'speed .* baud')$(tput sgr0)"
|
||||
echo -e "$(tput bold)default speed at login: $(grep ttyUSB /etc/inittab | sed 's/^.*ttyUSB[^ ]* \(.*\) .*$/\1/') baud$(tput sgr0)"
|
@ -1,761 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# need to test:
|
||||
# does both -e and -ad work as expected? what if you do both?
|
||||
|
||||
|
||||
#--ID-bashbyter routines
|
||||
|
||||
decToHex () {
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex value from 00-FF
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$1" 2> /dev/null) == $1 ) \
|
||||
&& ( $1 -ge 0 ) && ( $1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
printf %02X "$1"
|
||||
}
|
||||
|
||||
hexToDec () {
|
||||
# converts single-byte hexadecimal value to decimal equivalent
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: decimal value
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ${#1} -eq 2 ]] || return 21
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 21
|
||||
# args are valid
|
||||
printf %d "0x$1"
|
||||
}
|
||||
|
||||
hexToBin () {
|
||||
# converts single-byte hexadecimal value to binary string
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: binary string value
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ${#1} -eq 2 ]] || return 21
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 21
|
||||
# args are valid
|
||||
for n in 0 1; do
|
||||
if [[ ${1:n:1} == "0" ]]; then b="0000"
|
||||
elif [[ ${1:n:1} == "1" ]]; then b="0001"
|
||||
elif [[ ${1:n:1} == "2" ]]; then b="0010"
|
||||
elif [[ ${1:n:1} == "3" ]]; then b="0011"
|
||||
elif [[ ${1:n:1} == "4" ]]; then b="0100"
|
||||
elif [[ ${1:n:1} == "5" ]]; then b="0101"
|
||||
elif [[ ${1:n:1} == "6" ]]; then b="0110"
|
||||
elif [[ ${1:n:1} == "7" ]]; then b="0111"
|
||||
elif [[ ${1:n:1} == "8" ]]; then b="1000"
|
||||
elif [[ ${1:n:1} == "9" ]]; then b="1001"
|
||||
elif [[ ${1:n:1} == "A" ]]; then b="1010"
|
||||
elif [[ ${1:n:1} == "B" ]]; then b="1011"
|
||||
elif [[ ${1:n:1} == "C" ]]; then b="1100"
|
||||
elif [[ ${1:n:1} == "D" ]]; then b="1101"
|
||||
elif [[ ${1:n:1} == "E" ]]; then b="1110"
|
||||
elif [[ ${1:n:1} == "F" ]]; then b="1111"
|
||||
fi
|
||||
echo -n $b
|
||||
done
|
||||
}
|
||||
|
||||
binToDec () {
|
||||
# converts single-byte binary string (8 bits) value to decimal
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: decimal value
|
||||
dec=0
|
||||
bits=$1
|
||||
while (( ${#bits} < 8 )); do
|
||||
bits="0$bits"
|
||||
done
|
||||
for n in {0..7}; do
|
||||
(( dec+=( ${bits:$n:1} * ( 2**(7-$n) ) ) ))
|
||||
done
|
||||
echo -n $dec
|
||||
}
|
||||
|
||||
binToHex () {
|
||||
# converts single-byte binary string (8 bits) value to hex
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: hex value
|
||||
echo $(decToHex $(binToDec $1))
|
||||
}
|
||||
|
||||
charToDec () {
|
||||
# converts single character to corresponding decimal value
|
||||
# stdin OR arg: one character
|
||||
# [arg overrides stdin; stdin is required for NUL (0) or LF (0x0A)]
|
||||
# out: decimal value from 0-255
|
||||
#exit: 8=extraneous arg, 9=invalid stdin,
|
||||
# 11=missing stdin/arg, 21=invalid arg
|
||||
[[ ( ! -t 0 ) && $1 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $2 ]] && return 8; [[ $1 ]] || return 11; }
|
||||
# arg/stdin is potentially valid (additional check below)
|
||||
charX="$1X"; [[ $1 ]] || charX="$(cat; echo -n 'X';)"
|
||||
[[ ${#charX} -le 2 ]] || return $(( $([[ $1 ]]; echo $?) ? 9 : 21 ))
|
||||
# above line verifies that arg/stdin is valid
|
||||
[[ ${#charX} -ne 2 ]] && { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
charToHex () {
|
||||
# converts single character to corresponding hexadecimal value
|
||||
# stdin OR arg: one character
|
||||
# [arg overrides stdin; stdin is required for NUL (0) or LF (0x0A)]
|
||||
# out: decimal value from 0-255
|
||||
#exit: 8=extraneous arg, 9=invalid stdin,
|
||||
# 11=missing stdin/arg, 21=invalid arg
|
||||
[[ ( ! -t 0 ) && $1 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $2 ]] && return 8; [[ $1 ]] || return 11; }
|
||||
# arg/stdin is potentially valid (additional check below)
|
||||
charX="$1X"; [[ $1 ]] || charX="$(cat; echo -n 'X';)"
|
||||
[[ ${#charX} -le 2 ]] || return $(( $([[ $1 ]]; echo $?) ? 9 : 21 ))
|
||||
# above line verifies that stdin/arg is valid
|
||||
[[ ${#charX} -ne 2 ]] && { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
decToChar () {
|
||||
# converts single-byte decimal value to equivalent character
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$1" 2> /dev/null ) == $1 ) \
|
||||
&& ( $1 -ge 0 ) && ( $1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
echo -n -e "\x$(printf %02X "$1")"
|
||||
}
|
||||
|
||||
hexToChar () {
|
||||
# converts single-byte hexadecimal value to corresponding character
|
||||
# arg: two-digit hexadecimal number from 00-FF
|
||||
# out: one character
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ${#1} -eq 2 ]] || return 21
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 21
|
||||
# args are valid
|
||||
echo -n -e "\x$1"
|
||||
}
|
||||
|
||||
readchars () {
|
||||
# read one or more characters from a file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is until end of file)
|
||||
# out: sequence of characters
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11
|
||||
[[ $4 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
[[ $3 ]] && { [[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) ]] || return 23; }
|
||||
# args are valid
|
||||
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
||||
2> /dev/null
|
||||
}
|
||||
|
||||
readcharDec () {
|
||||
# read one character from file & convert to equivalent decimal value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
### 2-15-11 above tested on OS X and Linux
|
||||
|
||||
writechars () {
|
||||
# write one or more characters (bytes) to file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before writing)
|
||||
# arg3 OR stdin: sequence of characters
|
||||
# [stdin required if writing NUL (0) or trailing LF (0x0A) chars]
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 13=missing stdin/arg3, 22=invalid arg2
|
||||
[[ $1 ]] || { [[ -t 0 ]] || cat > /dev/null; return 11; }
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && \
|
||||
( $2 -ge 0 ) ]] || { [[ -t 0 ]] || cat > /dev/null; return 22; } }
|
||||
[[ ( ! -t 0 ) && $3 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $4 ]] && return 8; [[ $3 ]] || return 13; }
|
||||
# args are valid
|
||||
if [[ -t 0 ]]; then
|
||||
echo -n "$3" | \
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
else
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
writecharDec () {
|
||||
# write corresponding character of single-byte decimal value into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: decimal number from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
# out: nothing
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$(printf %02X "$3")" | \
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
}
|
||||
|
||||
writecharHex () {
|
||||
# write corresponding character of single-byte hex value into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: two-digit hexadecimal number from 00-FF
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
[[ $(printf %02X "0x$3" 2> /dev/null) == \
|
||||
$(echo -n "$3" | tr [a-z] [A-Z]) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$3" | \
|
||||
dd of="$1" bs=1 seek=$2 conv=notrunc 2> /dev/null
|
||||
}
|
||||
|
||||
writecharsHex () {
|
||||
# write corresponding characters of hex values into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF, period delimited (not checked!)
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
p=0
|
||||
offset=$2
|
||||
len=${#3}
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2}
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == \
|
||||
$(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$outByte" | \
|
||||
dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null
|
||||
(( p += 3 ))
|
||||
(( offset++ ))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# ---
|
||||
|
||||
pdosDateToUnixDate () {
|
||||
# input: ProDOS date/time bit sequence string in format:
|
||||
# yyyyyyymmmmddddd000hhhhh00mmmmmm
|
||||
# output: seconds since Unix epoch (1-Jan-1970), or current date/time if no ProDOS date
|
||||
year=$(( $(binToDec ${1:0:7}) + 1900 ))
|
||||
(( $year < 1940 )) && (( year+=100 ))
|
||||
month=$(binToDec ${1:7:4})
|
||||
day=$(binToDec ${1:11:5})
|
||||
hour=$(binToDec ${1:19:5})
|
||||
minute=$(binToDec ${1:26:6})
|
||||
date -d "$year-$month-$day $hour:$minute:00" "+%s" 2> /dev/null
|
||||
}
|
||||
|
||||
unixDateToADDate () {
|
||||
# input: seconds since Unix epoch (1-Jan-1970 00:00:00 GMT)
|
||||
# output: seconds since Netatalk epoch (1-Jan-2000 00:00:00 GMT),
|
||||
# in four period-delimited hex bytes (big endian)
|
||||
adDate=$(( $1 - 946684800 ));
|
||||
if (( $adDate < 0 )); then
|
||||
(( adDate+=4294967296 )) # to get negative hex number
|
||||
fi
|
||||
adDateHex=$(printf %08X $adDate)
|
||||
echo "${adDateHex:0:2}.${adDateHex:2:2}.${adDateHex:4:2}.${adDateHex:6:2}"
|
||||
}
|
||||
|
||||
# cppo support routines:
|
||||
# arg1: directory block
|
||||
# arg2: file index (if applicable)
|
||||
# arg3: directory chunk # (if applicable)
|
||||
|
||||
# returns byte position in disk image file
|
||||
getStartPos () {
|
||||
echo $(( ($1 * 512) + (39 * ( ($2 + ($2>11) ) % 13) ) + ( ($2>11) ? 4 : 43) ))
|
||||
}
|
||||
|
||||
getStorageType () {
|
||||
start=$(getStartPos $1 $2)
|
||||
firstByte=$(readcharDec "$image" $start)
|
||||
echo $(($firstByte/16))
|
||||
}
|
||||
|
||||
getFileName () {
|
||||
start=$(getStartPos $1 $2)
|
||||
firstByte=$(readcharDec "$image" $start)
|
||||
entryType=$(($firstByte/16))
|
||||
nameLength=$(($firstByte-$entryType*16))
|
||||
echo $(readchars "$image" $(($start+1)) $nameLength)
|
||||
}
|
||||
|
||||
getFileType () {
|
||||
start=$(getStartPos $1 $2)
|
||||
echo $(readcharHex "$image" $(($start+16)) )
|
||||
}
|
||||
|
||||
getKeyPointer () {
|
||||
start=$(getStartPos $1 $2)
|
||||
echo $(( $(readcharDec "$image" $(($start+17)) ) + \
|
||||
$(readcharDec "$image" $(($start+18)) ) * 256 ))
|
||||
}
|
||||
|
||||
getFileLength () {
|
||||
start=$(getStartPos $1 $2)
|
||||
echo $(( $(readcharDec "$image" $(($start+21)) ) + \
|
||||
$(readcharDec "$image" $(($start + 22)) ) * 256 + \
|
||||
$(readcharDec "$image" $(($start + 23)) ) * 65536 ))
|
||||
}
|
||||
|
||||
getAuxType () {
|
||||
start=$(getStartPos $1 $2)
|
||||
echo $(readcharHex "$image" $(($start+32)) ).$(readcharHex "$image" $(($start+31)) )
|
||||
}
|
||||
|
||||
getCreationDate () {
|
||||
#outputs prodos creation date/time as Unix time (seconds since Jan 1 1970 GMT)
|
||||
#or "NONE" if there is none
|
||||
start=$(getStartPos $1 $2)
|
||||
pdosDate=\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+25)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+24)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+27)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+26)) ) )
|
||||
pdosDateToUnixDate $pdosDate || echo "NONE"
|
||||
}
|
||||
|
||||
getModifiedDate () {
|
||||
#outputs prodos modified date/time as Unix time (seconds since Jan 1 1970 GMT)
|
||||
start=$(getStartPos $1 $2)
|
||||
pdosDate=\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+34)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+33)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+36)) ) )\
|
||||
$( hexToBin $(readcharHex "$image" $(($start+35)) ) )
|
||||
pdosDateToUnixDate $pdosDate || echo "NONE"
|
||||
}
|
||||
|
||||
#isLocked () {
|
||||
# #returns 1 (meaning locked) if bit 7, 6, or 1 are clear; otherwise returns 0
|
||||
# start=$(getStartPos $1 $2)
|
||||
# access=$( $hexToBin $(readcharHex "$image" $(($start+30)) ) )
|
||||
# if [[ ${access:0:1} != "1" || ${access:1:1} != "1" || ${access:7:1} != "1" ]]; then
|
||||
# echo 1
|
||||
# else
|
||||
# echo 0
|
||||
# fi
|
||||
#}
|
||||
|
||||
getVolumeName () {
|
||||
echo $(getWorkingDirName 2)
|
||||
}
|
||||
|
||||
getWorkingDirName () {
|
||||
start=$(( $1 * 512 ))
|
||||
firstByte=$(readcharDec "$image" $(($start+4)) )
|
||||
entryType=$(($firstByte/16))
|
||||
nameLength=$(($firstByte-$entryType*16))
|
||||
echo $(readchars "$image" $(($start+5)) $nameLength)
|
||||
}
|
||||
|
||||
getDirEntryCount () {
|
||||
start=$(( $1 * 512 ))
|
||||
echo $(( $(readcharDec "$image" $(($start+37)) ) + \
|
||||
$(readcharDec "$image" $(($start+38)) ) * 256 ))
|
||||
}
|
||||
|
||||
getDirNextChunkPointer () {
|
||||
start=$(( $1 * 512 ))
|
||||
echo $(( $(readcharDec "$image" $(($start+2)) ) + \
|
||||
$(readcharDec "$image" $(($start+3)) ) * 256 ))
|
||||
}
|
||||
|
||||
# -- script begins in earnest here
|
||||
|
||||
copyFile () {
|
||||
activeFileBytesCopied=0
|
||||
storageType=$(getStorageType $1 $2)
|
||||
keyPointer=$(getKeyPointer $1 $2)
|
||||
fileLen=$(getFileLength $1 $2)
|
||||
if (( $storageType == 1 )); then #seedling
|
||||
copyBlock $keyPointer $fileLen
|
||||
elif (( $storageType == 2 )); then #sapling
|
||||
processIndexBlock $keyPointer
|
||||
elif (( $storageType == 3 )); then #tree
|
||||
processMasterIndexBlock $keyPointer
|
||||
elif (( $storageType == 5)); then #forked fileLen
|
||||
processForkedFile $keyPointer
|
||||
fi
|
||||
}
|
||||
|
||||
copyBlock () {
|
||||
#arg1: block to copy
|
||||
#arg2: bytes to write (should be 512, unless final block with less than 512 bytes)
|
||||
#echo $1 $2 $activeFileBytesCopied
|
||||
(( $1 == 0 )) && blockSource=/dev/zero || blockSource="$image"
|
||||
if (( $resourceFork > 0 )); then
|
||||
[[ $AD ]] && dd if="$blockSource" of="$ADdir/$targetName" bs=1 count=$2 skip=$(($1*512)) seek=$(($activeFileBytesCopied + 741)) 2> /dev/null
|
||||
[[ $EX ]] && dd if="$blockSource" of="$targetDir/${eTargetName}r" bs=1 count=$2 skip=$(($1*512)) seek=$activeFileBytesCopied 2> /dev/null
|
||||
else
|
||||
dd if="$blockSource" of="$targetDir/$targetName" bs=1 count=$2 skip=$(($1*512)) seek="$activeFileBytesCopied" 2> /dev/null
|
||||
fi
|
||||
activeFileBytesCopied=$(( $activeFileBytesCopied + $2 ))
|
||||
}
|
||||
|
||||
processDir () {
|
||||
# arg1: dirBlock
|
||||
# arg2/3/4/5: for non-key chunks: entryCount, entry#,
|
||||
# workingDirName, processedEntryCount
|
||||
|
||||
local entryCount
|
||||
local e
|
||||
local pe
|
||||
local workingDirName
|
||||
|
||||
if [[ $2 ]]; then
|
||||
entryCount=$2
|
||||
e=$3
|
||||
workingDirName=$4
|
||||
pe=$5
|
||||
else
|
||||
e=0
|
||||
pe=0
|
||||
entryCount=$(getDirEntryCount $1)
|
||||
workingDirName=$(getWorkingDirName $1)
|
||||
DIRPATH="$DIRPATH/$workingDirName"
|
||||
if [[ $PDOSPATH_INDEX ]]; then
|
||||
if (( $PDOSPATH_INDEX == 1 )); then
|
||||
if [[ "/$PDOSPATH_SEGMENT" != "$DIRPATH" ]]; then
|
||||
echo "ProDOS volume name does not match disk image."
|
||||
exit 2
|
||||
else
|
||||
(( PDOSPATH_INDEX++ ))
|
||||
PDOSPATH_SEGMENT=${PDOSPATH[PDOSPATH_INDEX]}
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo $DIRPATH
|
||||
fi
|
||||
fi
|
||||
while (( $pe < $entryCount )); do
|
||||
if (( $(getStorageType $1 $e) > 0 )); then
|
||||
processEntry $1 $e
|
||||
(( pe++ ))
|
||||
fi
|
||||
(( e++ ))
|
||||
(( ($e + ( $e>11 ) ) % 13 )) || { processDir $(getDirNextChunkPointer $1) $entryCount $e $workingDirName $pe; break; }
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
processEntry () {
|
||||
#echo $(getFileName $1 $2) $(getStorageType $1 $2) $(getFileType $1 $2) $(getKeyPointer $1 $2) $(getFileLength $1 $2) $(getAuxType $1 $2) $(getCreationDate $1 $2) $(getModifiedDate $1 $2)
|
||||
activeFileName=$(getFileName $1 $2)
|
||||
activeFileSize=$(getFileLength $1 $2)
|
||||
[[ $PDOSPATH_INDEX ]] || echo " $activeFileName"
|
||||
|
||||
if [[ ( ! $PDOSPATH_INDEX ) || ( $activeFileName == $PDOSPATH_SEGMENT ) ]]; then
|
||||
|
||||
if (( $(getStorageType $1 $2) == 13 )); then
|
||||
[[ $PDOSPATH_INDEX ]] || targetDir="$targetDir/$activeFileName"
|
||||
ADdir="$targetDir/.AppleDouble"
|
||||
[[ $DIR || -d $targetDir ]] || mkdir -p $targetDir
|
||||
[[ $DIR || ! $AD || -d $ADdir ]] || mkdir -p $ADdir
|
||||
if [[ $PDOSPATH_SEGMENT ]]; then
|
||||
(( PDOSPATH_INDEX++ ))
|
||||
PDOSPATH_SEGMENT=${PDOSPATH[PDOSPATH_INDEX]}
|
||||
fi
|
||||
processDir $(getKeyPointer $1 $2)
|
||||
DIRPATH=${DIRPATH%/*}
|
||||
[[ $PDOSPATH_INDEX ]] || targetDir="$targetDir/.."
|
||||
ADdir="$targetDir/.AppleDouble"
|
||||
else
|
||||
[[ $DIR ]] && return
|
||||
[[ $targetName ]] || targetName=$activeFileName
|
||||
[[ $EX ]] && eTargetName="$targetName#$(getFileType $1 $2 | tr [:upper:] [:lower:])$(getAuxType $1 $2 | sed 's/\.//' | tr [:upper:] [:lower:])"
|
||||
touch "$targetDir/$targetName"
|
||||
makeADfile
|
||||
copyFile $1 $2
|
||||
creationDate=$(getCreationDate $1 $2);
|
||||
modifiedDate=$(getModifiedDate $1 $2);
|
||||
if [[ $creationDate == "NONE" && $modifiedDate != "NONE" ]]; then
|
||||
creationDate=$modifiedDate
|
||||
elif [[ $creationDate != "NONE" && $modifiedDate == "NONE" ]]; then
|
||||
modifiedDate=$creationDate
|
||||
elif [[ $creationDate == "NONE" && $modifiedDate == "NONE" ]]; then
|
||||
creationDate=$(date "+%s")
|
||||
modifiedDate=$creationDate
|
||||
fi
|
||||
if [[ $AD ]]; then # AppleDouble
|
||||
# set dates
|
||||
ADfilePath="$ADdir/$targetName"
|
||||
writecharsHex "$ADfilePath" 637 $(unixDateToADDate $creationDate).$(unixDateToADDate $modifiedDate)
|
||||
writecharHex "$ADfilePath" 645 80
|
||||
writecharHex "$ADfilePath" 649 80
|
||||
#set type/creator
|
||||
writechars "$ADfilePath" 653 "p"
|
||||
writecharsHex "$ADfilePath" 654 "$(getFileType $1 $2).$(getAuxType $1 $2)"
|
||||
writechars "$ADfilePath" 657 "pdos"
|
||||
fi
|
||||
touch -d @$modifiedDate "$targetDir/$targetName"
|
||||
if [[ $EX ]]; then # extended name
|
||||
mv "$targetDir/$targetName" "$targetDir/$eTargetName"
|
||||
[[ -f $targetDir/${eTargetName}r ]] && touch -d @$modifiedDate "$targetDir/${eTargetName}r"
|
||||
fi
|
||||
[[ $PDOSPATH_SEGMENT ]] && syncExit
|
||||
targetName=
|
||||
fi
|
||||
|
||||
#else
|
||||
#echo "$activeFileName doesn't match $PDOSPATH_SEGMENT"
|
||||
fi
|
||||
}
|
||||
|
||||
processForkedFile () {
|
||||
# finder info except type/creator
|
||||
fInfoA_entryType=$(readcharDec "$image" 9)
|
||||
fInfoB_entryType=$(readcharDec "$image" 27)
|
||||
if (( $fInfoA_entryType==1 )); then
|
||||
readchars "$image" 18 8 | writechars "$image" 661
|
||||
elif (( $fInfoA_entryType==2 )); then
|
||||
readchars "$image" 10 16 | writechars "$image" 669
|
||||
fi
|
||||
if (( $fInfoB_entryType==1 )); then
|
||||
readchars "$image" 36 8 | writechars "$image" 661
|
||||
elif (( $fInfoB_entryType==2 )); then
|
||||
readchars "$image" 28 16 | writechars "$image" 669
|
||||
fi
|
||||
|
||||
for f in 0 256; do
|
||||
resourceFork=$f
|
||||
activeFileBytesCopied=0
|
||||
forkStart=$(( ($1 * 512) )) # start of Forked File key block
|
||||
# echo --$forkStart
|
||||
forkStorageType=$(readcharDec "$image" $(($forkStart+$f+0)) )
|
||||
forkKeyPointer=$(( $(readcharDec "$image" $(($forkStart+$f+1)) ) + \
|
||||
$(readcharDec "$image" $(($forkStart+$f+2)) ) * 256 ))
|
||||
forkFileLen=$(( $(readcharDec "$image" $(($forkStart+$f+5)) ) + \
|
||||
$(readcharDec "$image" $(($forkStart+$f+6)) ) * 256 + \
|
||||
$(readcharDec "$image" $(($forkStart+$f+7)) ) * 65536 ))
|
||||
activeFileSize=$forkFileLen
|
||||
if (( $resourceFork > 0 )); then
|
||||
rsrcForkLenHex=$(readcharHex "$image" $(($forkStart+$f+7)) ).\
|
||||
$(readcharHex "$image" $(($forkStart+$f+6)) ).\
|
||||
$(readcharHex "$image" $(($forkStart+$f+5)) )
|
||||
# echo ">>>$rsrcForkLenHex"
|
||||
echo " [resource fork]"
|
||||
[[ $AD ]] && writecharsHex "$ADdir/$targetName" 35 "$rsrcForkLenHex"
|
||||
else
|
||||
echo " [data fork]"
|
||||
fi
|
||||
if (( $forkStorageType == 1 )); then #seedling
|
||||
copyBlock $forkKeyPointer $forkFileLen
|
||||
elif (( $forkStorageType == 2 )); then #sapling
|
||||
processIndexBlock $forkKeyPointer
|
||||
elif (( $forkStorageType == 3 )); then #tree
|
||||
processMasterIndexBlock $forkKeyPointer
|
||||
fi
|
||||
done
|
||||
# echo
|
||||
resourceFork=0
|
||||
}
|
||||
|
||||
processMasterIndexBlock() {
|
||||
processIndexBlock $1 1
|
||||
}
|
||||
|
||||
processIndexBlock () {
|
||||
#arg1: indexBlock
|
||||
#arg2: if set, it's a Master Index Block
|
||||
local pos=0
|
||||
local bytesRemaining
|
||||
while (( $activeFileBytesCopied < $activeFileSize )); do
|
||||
targetBlock=$(( $(readcharDec $image $(($1*512+$pos)) ) + $(readcharDec $image $(($1*512+($pos+256) )) )*256 ))
|
||||
if [[ $2 ]]; then
|
||||
processIndexBlock $targetBlock
|
||||
else
|
||||
bytesRemaining=$(($activeFileSize - $activeFileBytesCopied))
|
||||
bs=$(( $bytesRemaining<512 ? $bytesRemaining : 512 ))
|
||||
copyBlock $targetBlock $bs
|
||||
fi
|
||||
(( pos++ ))
|
||||
(( $pos > 255 )) && break # go to next entry in Master Index Block (tree)
|
||||
done
|
||||
}
|
||||
|
||||
makeADfile () {
|
||||
ADfilePath="$ADdir/$targetName"
|
||||
[[ ! $AD ]] && return
|
||||
dd if=/dev/zero of="$ADfilePath" bs=741 count=1 2> /dev/null
|
||||
writecharsHex "$ADfilePath" $(hexToDec 00) "00.05.16.07.00.02.00.00" # ADv2 header
|
||||
writecharsHex "$ADfilePath" $(hexToDec 18) "00.0D" # number of entries
|
||||
writecharsHex "$ADfilePath" $(hexToDec 1A) "00.00.00.02.00.00.02.E5.00.00.00.00" # Resource Fork
|
||||
writecharsHex "$ADfilePath" $(hexToDec 26) "00.00.00.03.00.00.00.B6.00.00.00.00" # Real Name
|
||||
writecharsHex "$ADfilePath" $(hexToDec 32) "00.00.00.04.00.00.01.B5.00.00.00.00" # Comment
|
||||
writecharsHex "$ADfilePath" $(hexToDec 3E) "00.00.00.08.00.00.02.7D.00.00.00.10" # Dates Info
|
||||
writecharsHex "$ADfilePath" $(hexToDec 4A) "00.00.00.09.00.00.02.8D.00.00.00.20" # Finder Info
|
||||
writecharsHex "$ADfilePath" $(hexToDec 56) "00.00.00.0B.00.00.02.C1.00.00.00.08" # ProDOS file info
|
||||
writecharsHex "$ADfilePath" $(hexToDec 62) "00.00.00.0D.00.00.02.B5.00.00.00.00" # AFP short name
|
||||
writecharsHex "$ADfilePath" $(hexToDec 6E) "00.00.00.0E.00.00.02.B1.00.00.00.04" # AFP File Info
|
||||
writecharsHex "$ADfilePath" $(hexToDec 7A) "00.00.00.0F.00.00.02.AD.00.00.00.04" # AFP Directory ID
|
||||
# dbd (second time) will create DEV, INO, SYN, SV~
|
||||
}
|
||||
|
||||
syncExit () {
|
||||
if [[ -d /usr/local/etc/netatalk && $AD ]]; then
|
||||
echo "File(s) have been copied to the target directory. If the directory" 1>&2
|
||||
echo "is shared by Netatalk, please use 'afpsync' now." 1>&2
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "usage:"
|
||||
echo "copy all files: cppo [-ad|-e] imagefile targetDirectory"
|
||||
echo "copy one file : cppo [-ad|-e] imagefile /FULL/PRODOS/FILE/PATH targetPath"
|
||||
echo "catalog image : cppo -cat imagefile"
|
||||
echo
|
||||
echo "cppo copies either one file or all files from a ProDOS raw disk image"
|
||||
echo "to a folder shared by Netatalk. -cat displays all files on the image."
|
||||
echo "No verification or validation of the disk image is performed."
|
||||
echo
|
||||
echo "-ad enables creating AppleDouble header files and copying resource forks."
|
||||
echo "-e appends the ProDOS type and auxtype to filenames, and copies resource"
|
||||
echo " forks, so they can be preserved when added to ShrinkIt archives by"
|
||||
echo " nulib2 (using its -e option)."
|
||||
echo
|
||||
echo "Wildcard matching (*) is not supported."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- start
|
||||
|
||||
if [[ $1 == "-ad" ]]; then
|
||||
AD=1
|
||||
shift
|
||||
fi
|
||||
if [[ $1 == "-e" ]]; then
|
||||
[[ $AD ]] && usage
|
||||
EX=1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-cat" ]]; then
|
||||
DIR=1
|
||||
shift
|
||||
fi
|
||||
|
||||
[[ ( $DIR && $1 ) || ( $1 && $2 ) ]] || usage
|
||||
[[ $3 && ( ${2:0:1} != "/" ) && ( ${2:0:1} != ":" ) ]] && usage
|
||||
|
||||
image="$1"
|
||||
[[ -f "$image" ]] || { echo "Source image not found."; exit 2; }
|
||||
if [[ $3 ]]; then
|
||||
pdospath=$(echo $2 | tr [:lower:] [:upper:])
|
||||
targetPath=$3
|
||||
if [[ -d $targetPath ]]; then
|
||||
targetDir=$targetPath
|
||||
else
|
||||
targetDir="${targetPath%/*}"
|
||||
targetName="${targetPath##*/}"
|
||||
fi
|
||||
[[ -d $targetDir ]] || { echo "Target directory not found."; exit 2; }
|
||||
else
|
||||
if [[ ! $DIR ]]; then
|
||||
[[ -d "$2" ]] || { echo "Target directory not found."; exit 2; }
|
||||
fi
|
||||
fi
|
||||
|
||||
activeDirBlock=0
|
||||
activeFileName=""
|
||||
activeFileSize=0
|
||||
activeFileBytesCopied=0
|
||||
resourceFork=0
|
||||
|
||||
if [[ $3 ]]; then
|
||||
IFS='/:'
|
||||
PDOSPATH=($pdospath)
|
||||
unset IFS
|
||||
[[ ! ${PDOSPATH[0]} ]] && (( PDOSPATH_INDEX++ ))
|
||||
PDOSPATH_SEGMENT=${PDOSPATH[PDOSPATH_INDEX]}
|
||||
ADdir="$targetDir/.AppleDouble"
|
||||
[[ ! $AD || -d $ADdir ]] || mkdir $ADdir
|
||||
processDir 2
|
||||
echo "ProDOS file not found within image file."
|
||||
exit 2
|
||||
else
|
||||
if [[ ! $DIR ]]; then
|
||||
targetDir="$2/$(getVolumeName)"
|
||||
ADdir="$targetDir/.AppleDouble"
|
||||
[[ -d $targetDir ]] || mkdir -p $targetDir
|
||||
[[ ! $AD || -d $ADdir ]] || mkdir -p $ADdir
|
||||
fi
|
||||
processDir 2
|
||||
[[ $DIR ]] || syncExit
|
||||
fi
|
@ -1,882 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""cppo: Copy or catalog one or all files from a ProDOS raw disk image.
|
||||
|
||||
copy all files:
|
||||
cppo [-ad|-e] imagefile target_directory
|
||||
copy one file:
|
||||
cppo [-ad|-e] imagefile /FULL/PRODOS/FILE/PATH target_path
|
||||
catalog image:
|
||||
cppo -cat imagefile
|
||||
|
||||
-ad : Create AppleDouble header files and preserve resource forks.
|
||||
-e : Append ProDOS type and auxtype to filenames, and copy resource
|
||||
forks, for adding to ShrinkIt archives with Nulib2
|
||||
using its -e option.
|
||||
|
||||
Wildcard matching/globbing (*) is not supported.
|
||||
No verification or validation of the disk image is performed.
|
||||
|
||||
(Compatible with Python 2.6 and later, including 3.x.)
|
||||
"""
|
||||
|
||||
# cppo by Ivan X, ivan@ivanx.com, ivanx.com/appleii
|
||||
|
||||
# If anyone's looking at this, and feels it's not sufficiently Pythonic,
|
||||
# I know that. It's pretty much a line-for-line conversion of the original
|
||||
# Bash script. I did start a beautiful from-the-ground-up object-oriented
|
||||
# version, then realized it would be faster to translate it ugly and quick.
|
||||
|
||||
# imports for python 3 code compatibility
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
|
||||
# Intentially fails on pre-2.6 so user can see what's wrong
|
||||
b'ERROR: cppo requires Python 2.6 or later, including 3.x.'
|
||||
|
||||
class Globals(object):
|
||||
pass
|
||||
|
||||
g = Globals()
|
||||
|
||||
g.imageData = b''
|
||||
g.outFileData = bytearray(b'')
|
||||
g.adFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
|
||||
g.activeDirBlock = None
|
||||
g.activeFileName = None
|
||||
g.activeFileSize = None
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
|
||||
g.PDOSPATH = []
|
||||
g.PDOSPATH_INDEX = 0
|
||||
g.PDOSPATH_SEGMENT = None
|
||||
g.DIRPATH = ""
|
||||
|
||||
g.targetName = None
|
||||
g.targetDir = ""
|
||||
g.ADdir = None
|
||||
g.imageFile = None
|
||||
|
||||
g.AD = 0
|
||||
g.EX = 0
|
||||
g.DIR = 0
|
||||
g.silent = 0
|
||||
|
||||
# functions
|
||||
|
||||
def pdosDateToUnixDate(arg1):
|
||||
# input: ProDOS date/time bit sequence string in format:
|
||||
# "yyyyyyymmmmddddd000hhhhh00mmmmmm" (ustr)
|
||||
# output: seconds since Unix epoch (1-Jan-1970),
|
||||
# or current date/time if no ProDOS date
|
||||
year = (binToDec(slyce(arg1,0,7)) + 1900)
|
||||
if (year < 1940): year += 100
|
||||
month = binToDec(slyce(arg1,7,4))
|
||||
day = binToDec(slyce(arg1,11,5))
|
||||
hour = binToDec(slyce(arg1,19,5))
|
||||
minute = binToDec(slyce(arg1,26,6))
|
||||
# print(year, month, day, hour, minute)
|
||||
td = (datetime.datetime(year, month, day, hour, minute) -
|
||||
datetime.datetime(1970,1,1))
|
||||
unixDate_naive = (td.days*24*60*60 + td.seconds)
|
||||
td2 = (datetime.datetime.fromtimestamp(unixDate_naive) -
|
||||
datetime.datetime.utcfromtimestamp(unixDate_naive))
|
||||
utcoffset = (td2.days*24*60*60 + td2.seconds)
|
||||
# print(unixDate_naive - utcoffset)
|
||||
return (unixDate_naive - utcoffset) # local time zone with DST
|
||||
|
||||
def unixDateToADDate(arg1):
|
||||
# input: seconds since Unix epoch (1-Jan-1970 00:00:00 GMT)
|
||||
# output: seconds since Netatalk epoch (1-Jan-2000 00:00:00 GMT),
|
||||
# in hex-ustr (big endian)
|
||||
adDate = (arg1 - 946684800)
|
||||
if (adDate < 0 ):
|
||||
adDate += 4294967296 # to get negative hex number
|
||||
adDateHex = to_hex(adDate).zfill(8).upper()
|
||||
# print(arg1, adDate, adDateHex)
|
||||
return adDateHex
|
||||
|
||||
# cppo support routines:
|
||||
# arg1: directory block
|
||||
# arg2: file index (if applicable)
|
||||
# arg3: directory chunk # (if applicable)
|
||||
|
||||
#most of these not tested yet in Python
|
||||
# returns byte position in disk image file
|
||||
def getStartPos(arg1, arg2):
|
||||
return ( (arg1 * 512) +
|
||||
(39 * ((arg2 + (arg2 > 11)) % 13)) +
|
||||
(4 if (arg2 > 11) else 43) )
|
||||
|
||||
def getStorageType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
return (firstByte//16)
|
||||
|
||||
def getFileName(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+1, nameLength)
|
||||
|
||||
def getFileType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return readcharHex(g.imageData, start+16)
|
||||
|
||||
def getKeyPointer(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+17) +
|
||||
readcharDec(g.imageData, start+18)*256)
|
||||
|
||||
def getFileLength(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+21) +
|
||||
readcharDec(g.imageData, start+22)*256 +
|
||||
readcharDec(g.imageData, start+23)*65536)
|
||||
|
||||
def getAuxType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharHex(g.imageData, start+32) +
|
||||
readcharHex(g.imageData, start+31))
|
||||
|
||||
def getCreationDate(arg1, arg2):
|
||||
#outputs prodos creation date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+25)) +
|
||||
hexToBin(readcharHex(g.imageData, start+24)) +
|
||||
hexToBin(readcharHex(g.imageData, start+27)) +
|
||||
hexToBin(readcharHex(g.imageData, start+26)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getModifiedDate(arg1, arg2):
|
||||
#outputs prodos modified date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+34)) +
|
||||
hexToBin(readcharHex(g.imageData, start+33)) +
|
||||
hexToBin(readcharHex(g.imageData, start+36)) +
|
||||
hexToBin(readcharHex(g.imageData, start+35)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getVolumeName():
|
||||
return getWorkingDirName(2)
|
||||
|
||||
def getWorkingDirName(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
firstByte = readcharDec(g.imageData, start+4)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+5, nameLength)
|
||||
|
||||
def getDirEntryCount(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+37) +
|
||||
readcharDec(g.imageData, start+38)*256)
|
||||
|
||||
def getDirNextChunkPointer(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+2) +
|
||||
readcharDec(g.imageData, start+3)*256)
|
||||
|
||||
# -- script begins in earnest here
|
||||
|
||||
def copyFile(arg1, arg2):
|
||||
g.outFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
g.activeFileBytesCopied = 0
|
||||
storageType = getStorageType(arg1, arg2)
|
||||
keyPointer = getKeyPointer(arg1, arg2)
|
||||
fileLen = getFileLength(arg1, arg2)
|
||||
if (storageType == 1): #seedling
|
||||
copyBlock(keyPointer, fileLen)
|
||||
elif (storageType == 2): #sapling
|
||||
processIndexBlock(keyPointer)
|
||||
elif (storageType == 3): #tree
|
||||
processMasterIndexBlock(keyPointer)
|
||||
elif (storageType == 5): #extended (forked)
|
||||
processForkedFile(keyPointer)
|
||||
|
||||
def copyBlock(arg1, arg2):
|
||||
#arg1: block to copy
|
||||
#arg2: bytes to write (should be 512,
|
||||
# unless final block with less than 512 bytes)
|
||||
#print(arg1 + " " + arg2 + " " + g.activeFileBytesCopied)
|
||||
if (arg1 == 0):
|
||||
outBytes = (b'\x00' * arg2)
|
||||
else:
|
||||
outBytes = slyce(g.imageData, arg1*512, arg2)
|
||||
if (g.resourceFork > 0):
|
||||
if g.AD:
|
||||
g.adFileData[g.activeFileBytesCopied+741:
|
||||
(g.activeFileBytesCopied+741 + arg2)] = outBytes
|
||||
if g.EX:
|
||||
g.exFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
else:
|
||||
g.outFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
g.activeFileBytesCopied += arg2
|
||||
|
||||
def processDir(arg1, arg2=None, arg3=None, arg4=None, arg5=None):
|
||||
# arg1: dirBlock
|
||||
# arg2/3/4/5: for non-key chunks: entryCount, entry#,
|
||||
# workingDirName, processedEntryCount
|
||||
|
||||
entryCount = None
|
||||
e = None
|
||||
pe = None
|
||||
workingDirName = None
|
||||
|
||||
if arg2:
|
||||
entryCount = arg2
|
||||
e = arg3
|
||||
workingDirName = arg4
|
||||
pe = arg5
|
||||
else:
|
||||
e = 0
|
||||
pe = 0
|
||||
entryCount = getDirEntryCount(arg1)
|
||||
workingDirName = getWorkingDirName(arg1).decode("L1")
|
||||
g.DIRPATH = (g.DIRPATH + "/" + workingDirName)
|
||||
if g.PDOSPATH_INDEX:
|
||||
if (g.PDOSPATH_INDEX == 1):
|
||||
if (("/" + g.PDOSPATH_SEGMENT) != g.DIRPATH):
|
||||
print("ProDOS volume name does not match disk image.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
else:
|
||||
print(g.DIRPATH)
|
||||
while (pe < entryCount):
|
||||
if (getStorageType(arg1, e) > 0):
|
||||
processEntry(arg1, e)
|
||||
pe += 1
|
||||
e += 1
|
||||
if not ((e + ( e>11 ) ) % 13):
|
||||
processDir(getDirNextChunkPointer(arg1),
|
||||
entryCount,
|
||||
e,
|
||||
workingDirName,
|
||||
pe)
|
||||
break
|
||||
|
||||
def processEntry(arg1, arg2):
|
||||
'''
|
||||
print(getFileName(arg1, arg2), getStorageType(arg1, arg2),
|
||||
getFileType(arg1, arg2), getKeyPointer(arg1, arg2),
|
||||
getFileLength(arg1, arg2), getAuxType(arg1, arg2),
|
||||
getCreationDate(arg1, arg2), getModifiedDate(arg1, arg2))
|
||||
'''
|
||||
g.activeFileName = getFileName(arg1 ,arg2).decode("L1")
|
||||
g.activeFileSize = getFileLength(arg1, arg2)
|
||||
|
||||
if ((not g.PDOSPATH_INDEX) or (g.activeFileName == g.PDOSPATH_SEGMENT)):
|
||||
|
||||
if (getStorageType(arg1, arg2) == 13): # if ProDOS directory
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = (g.targetDir + "/" + g.activeFileName)
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not (g.DIR or os.path.isdir(g.targetDir)):
|
||||
makedirs(g.targetDir)
|
||||
if not (g.DIR or (not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
processDir(getKeyPointer(arg1, arg2))
|
||||
g.DIRPATH = g.DIRPATH.rsplit("/", 1)[0]
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = g.targetDir.rsplit("/", 1)[0]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
else: # if ProDOS file
|
||||
if not g.PDOSPATH_INDEX:
|
||||
print(" " + g.activeFileName)
|
||||
if g.DIR:
|
||||
return
|
||||
if not g.targetName:
|
||||
g.targetName = g.activeFileName
|
||||
if g.EX:
|
||||
eTargetName = (g.targetName + "#" +
|
||||
getFileType(arg1, arg2).lower() +
|
||||
getAuxType(arg1, arg2).lower())
|
||||
touch(g.targetDir + "/" + g.targetName)
|
||||
if g.AD: makeADfile()
|
||||
copyFile(arg1, arg2)
|
||||
saveFile((g.targetDir + "/" + g.targetName), g.outFileData)
|
||||
creationDate = getCreationDate(arg1, arg2)
|
||||
modifiedDate = getModifiedDate(arg1, arg2)
|
||||
if (creationDate is None and modifiedDate is not None):
|
||||
creationDate = modifiedDate
|
||||
elif (creationDate is not None and modifiedDate is None):
|
||||
modifiedDate = creationDate
|
||||
elif (creationDate is None and modifiedDate is None):
|
||||
creationDate = (datetime.datetime.today() -
|
||||
datetime.datetime(1970,1,1)).days*24*60*60
|
||||
modifiedDate = creationDate
|
||||
if g.AD: # AppleDouble
|
||||
# set dates
|
||||
ADfilePath = (g.ADdir + "/" + g.targetName)
|
||||
writecharsHex(g.adFileData,
|
||||
637,
|
||||
(unixDateToADDate(creationDate) +
|
||||
unixDateToADDate(modifiedDate)))
|
||||
writecharHex(g.adFileData, 645, "80")
|
||||
writecharHex(g.adFileData, 649, "80")
|
||||
#set type/creator
|
||||
writechars(g.adFileData, 653, b'p')
|
||||
writecharsHex(g.adFileData,
|
||||
654,
|
||||
(getFileType(arg1, arg2) +
|
||||
getAuxType(arg1, arg2)))
|
||||
writechars(g.adFileData, 657, b'pdos')
|
||||
saveFile(ADfilePath, g.adFileData)
|
||||
touch((g.targetDir + "/" + g.targetName), modifiedDate)
|
||||
if g.EX: # extended name
|
||||
os.rename((g.targetDir + "/" + g.targetName),
|
||||
(g.targetDir + "/" + eTargetName))
|
||||
if (len(g.exFileData) > 0):
|
||||
saveFile((g.targetDir + "/" + eTargetName + "r"),
|
||||
g.exFileData)
|
||||
touch((g.targetDir + "/" + eTargetName + "r"),
|
||||
modifiedDate)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
syncExit()
|
||||
g.targetName = None
|
||||
|
||||
#else:
|
||||
#print(g.activeFileName + " doesn't match " + g.PDOSPATH_SEGMENT)
|
||||
|
||||
def processForkedFile(arg1):
|
||||
# finder info except type/creator
|
||||
fInfoA_entryType = readcharDec(g.imageData, 9)
|
||||
fInfoB_entryType = readcharDec(g.imageData, 27)
|
||||
if (fInfoA_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 18, 8))
|
||||
elif (fInfoA_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 10, 16))
|
||||
if (fInfoB_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 36, 8))
|
||||
elif (fInfoB_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 28, 16))
|
||||
|
||||
for f in [0, 256]:
|
||||
g.resourceFork = f
|
||||
g.activeFileBytesCopied = 0
|
||||
forkStart = (arg1 * 512) # start of Forked File key block
|
||||
# print("--" + forkStart)
|
||||
forkStorageType = readcharDec(g.imageData, forkStart+f+0)
|
||||
forkKeyPointer = (readcharDec(g.imageData, forkStart+f+1) +
|
||||
readcharDec(g.imageData, forkStart+f+2)*256)
|
||||
forkFileLen = (readcharDec(g.imageData, forkStart+f+5) +
|
||||
readcharDec(g.imageData, forkStart+f+6)*256 +
|
||||
readcharDec(g.imageData, forkStart+f+7)*256*256)
|
||||
g.activeFileSize = forkFileLen
|
||||
if (g.resourceFork > 0):
|
||||
rsrcForkLenHex = (readcharHex(g.imageData, forkStart+f+7) +
|
||||
readcharHex(g.imageData, forkStart+f+6) +
|
||||
readcharHex(g.imageData, forkStart+f+5))
|
||||
# print(">>>" + rsrcForkLenHex)
|
||||
print(" [resource fork]")
|
||||
if g.AD:
|
||||
writecharsHex(g.adFileData, 35, rsrcForkLenHex)
|
||||
else:
|
||||
print(" [data fork]")
|
||||
if (forkStorageType == 1): #seedling
|
||||
copyBlock(forkKeyPointer, forkFileLen)
|
||||
elif (forkStorageType == 2): #sapling
|
||||
processIndexBlock(forkKeyPointer)
|
||||
elif (forkStorageType == 3): #tree
|
||||
processMasterIndexBlock(forkKeyPointer)
|
||||
# print()
|
||||
g.resourceFork = 0
|
||||
|
||||
def processMasterIndexBlock(arg1):
|
||||
processIndexBlock(arg1, True)
|
||||
|
||||
def processIndexBlock(arg1, arg2=False):
|
||||
#arg1: indexBlock
|
||||
#arg2: if True, it's a Master Index Block
|
||||
pos = 0
|
||||
bytesRemaining = g.activeFileSize
|
||||
while (g.activeFileBytesCopied < g.activeFileSize):
|
||||
targetBlock = (readcharDec(g.imageData, arg1*512+pos) +
|
||||
readcharDec(g.imageData, arg1*512+(pos+256))*256)
|
||||
if arg2:
|
||||
processIndexBlock(targetBlock)
|
||||
else:
|
||||
bytesRemaining = (g.activeFileSize - g.activeFileBytesCopied)
|
||||
bs = (bytesRemaining if (bytesRemaining < 512) else 512)
|
||||
copyBlock(targetBlock, bs)
|
||||
pos += 1
|
||||
if (pos > 255):
|
||||
break # go to next entry in Master Index Block (tree)
|
||||
|
||||
def makeADfile():
|
||||
if not g.AD: return
|
||||
touch(g.ADdir + "/" + g.targetName)
|
||||
g.adFileData = bytearray(b'\x00' * 741)
|
||||
# ADv2 header
|
||||
writecharsHex(g.adFileData, hexToDec("00"), "0005160700020000")
|
||||
# number of entries
|
||||
writecharsHex(g.adFileData, hexToDec("18"), "000D")
|
||||
# Resource Fork
|
||||
writecharsHex(g.adFileData, hexToDec("1A"), "00000002000002E500000000")
|
||||
# Real Name
|
||||
writecharsHex(g.adFileData, hexToDec("26"), "00000003000000B600000000")
|
||||
# Comment
|
||||
writecharsHex(g.adFileData, hexToDec("32"), "00000004000001B500000000")
|
||||
# Dates Info
|
||||
writecharsHex(g.adFileData, hexToDec("3E"), "000000080000027D00000010")
|
||||
# Finder Info
|
||||
writecharsHex(g.adFileData, hexToDec("4A"), "000000090000028D00000020")
|
||||
# ProDOS file info
|
||||
writecharsHex(g.adFileData, hexToDec("56"), "0000000B000002C100000008")
|
||||
# AFP short name
|
||||
writecharsHex(g.adFileData, hexToDec("62"), "0000000D000002B500000000")
|
||||
# AFP File Info
|
||||
writecharsHex(g.adFileData, hexToDec("6E"), "0000000E000002B100000004")
|
||||
# AFP Directory ID
|
||||
writecharsHex(g.adFileData, hexToDec("7A"), "0000000F000002AD00000004")
|
||||
# dbd (second time) will create DEV, INO, SYN, SV~
|
||||
|
||||
def syncExit():
|
||||
if (not g.silent and g.AD and os.path.isdir("/usr/local/etc/netatalk")):
|
||||
print("File(s) have been copied to the target directory. " +
|
||||
"If the directory")
|
||||
print("is shared by Netatalk, please type 'afpsync' now.")
|
||||
# saveFile(g.imageFile, g.imageData)
|
||||
sys.exit(0)
|
||||
|
||||
def usage():
|
||||
print(sys.modules[__name__].__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
# --- ID bashbyter functions (adapted)
|
||||
|
||||
def decToHex(arg1):
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex string from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def hexToDec(arg1):
|
||||
# converts single-byte hexadecimal value to decimal equivalent
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: decimal value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def hexToBin(arg1):
|
||||
# converts single-byte hexadecimal value to binary string
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: binary string value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bin(arg1).zfill(8)
|
||||
|
||||
def binToDec(arg1):
|
||||
# converts single-byte binary string (8 bits) value to decimal
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: decimal value
|
||||
return to_dec([arg1])
|
||||
|
||||
def binToHex(arg1):
|
||||
# converts single-byte binary string (8 bits) value to hex
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: hex value
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def charToDec(arg1):
|
||||
# converts single char (of type bytes) to corresponding decimal value
|
||||
# arg: one char (of type bytes)
|
||||
# out: decimal value from 0-255
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def charToHex(arg1):
|
||||
# converts single char (of type bytes) to corresponding hex value
|
||||
# arg: one char (of type bytes)
|
||||
# out: hexadecimal value from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def decToChar(arg1):
|
||||
# converts single-byte decimal value to equivalent char (of type bytes)
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_bytes(arg1)
|
||||
|
||||
def hexToChar(arg1):
|
||||
# converts single-byte hex value to corresponding char (of type bytes)
|
||||
# arg: two-digit hexadecimal number from 00-FF
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bytes(arg1)
|
||||
|
||||
def readchars(arg1, arg2=0, arg3=0):
|
||||
# read one or more characters from a bytes variable
|
||||
# arg1: bytes or bytearray variable
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is to end of bytes var)
|
||||
# out: sequence of characters (bytes or bytearray)
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if (arg3<0): sys.exit(23)
|
||||
if (arg3 == 0):
|
||||
arg3 = len(arg1)
|
||||
return slyce(arg1, arg2, arg3)
|
||||
|
||||
def readcharDec(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to equivalent dec value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_dec(slyce(arg1, arg2, 1))
|
||||
|
||||
def readcharHex(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to corresponding hex value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_hex(slyce(arg1, arg2, 1))
|
||||
|
||||
def writechars(arg1, arg2, arg3):
|
||||
# write one or more characters (bytes) to bytearray
|
||||
# arg1: bytearray variable
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: sequence of bytes (or bytearray)
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not (isinstance(arg3, bytes) or isinstance(arg3, bytearray)):
|
||||
sys.exit(23)
|
||||
arg1[arg2:arg2+len(arg3)] = arg3
|
||||
|
||||
def writecharDec(arg1, arg2, arg3):
|
||||
# write corresponding char of single-byte decimal value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: decimal number from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
# out: nothing
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isnumber(arg3): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharHex(arg1, arg2, arg3):
|
||||
# write corresponding character of single-byte hex value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: two-digit hexadecimal number from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharsHex(arg1, arg2, arg3):
|
||||
# write corresponding characters of hex values into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+len(to_bytes(arg3))] = to_bytes(arg3)
|
||||
|
||||
#---- IvanX general purpose functions ----#
|
||||
|
||||
def slyce(val, start_pos=0, length=1, reverse=False):
|
||||
"""returns slice of object (but not a slice object)
|
||||
allows specifying length, and 3.x "bytes" consistency"""
|
||||
the_slyce = val[start_pos:start_pos+length]
|
||||
return (the_slyce[::-1] if reverse else the_slyce)
|
||||
|
||||
def to_hex(val):
|
||||
"""convert bytes, decimal number, or [bin-ustr] to two-digit hex values
|
||||
unlike hex(), accepts bytes; has no leading 0x or trailing L"""
|
||||
from binascii import b2a_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = int(val[0], 2)
|
||||
if isinstance(val, bytes): # bytes
|
||||
return b2a_hex(val).decode("L1")
|
||||
elif isnumber(val):
|
||||
# .encode().decode() always returns unicode in both P2 and P3
|
||||
return (hex(val)[2:].split("L")[0]).encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_hex() requires bytes, int/long, or [bin-ustr]")
|
||||
|
||||
def hex_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce as hex-ustr"""
|
||||
return to_hex(slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def dec_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to decimal int/long"""
|
||||
return to_dec(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def bin_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to bin-ustr"""
|
||||
return to_bin(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def to_dec(val):
|
||||
"""convert bytes, hex-ustr or [bin-ustr] to decimal int/long"""
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
return int(val[0], 2)
|
||||
elif isinstance(val, bytes): # bytes
|
||||
return int(to_hex(val), 16)
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return int(val, 16)
|
||||
else:
|
||||
raise Exception("to_dec() requires bytes, hex-ustr or [bin-ustr]")
|
||||
|
||||
def to_bin(val):
|
||||
"""convert bytes, hex-ustr, or int/long to bin-ustr"""
|
||||
if isinstance(val, bytes): # bytes
|
||||
return (bin(to_dec(to_hex(val))))[2:].encode("L1").decode("L1")
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return (bin(int(val, 16)))[2:].encode("L1").decode("L1")
|
||||
elif isnumber(val): # int/long
|
||||
return (bin(val))[2:].encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_bin() requires bytes, hex-ustr, or int/long")
|
||||
|
||||
def to_bytes(val):
|
||||
"""converts hex-ustr, int/long, or [bin-ustr] to bytes"""
|
||||
from binascii import a2b_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = to_hex(val[0])
|
||||
if isnumber(val): # int/long
|
||||
val = to_hex(val)
|
||||
if isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return a2b_hex(bytes(val.encode("L1"))) # works on both P2 and P3
|
||||
else:
|
||||
raise Exception(
|
||||
"to_bytes() requires hex-ustr, int/long, or [bin-ustr]")
|
||||
|
||||
def shift(items):
|
||||
"""Shift list items to left, losing the first item.
|
||||
|
||||
in : list
|
||||
out: list
|
||||
"""
|
||||
for i in range(0, (len(items)-1)):
|
||||
items[i] = items[i+1]
|
||||
del items[-1]
|
||||
return items
|
||||
|
||||
def s(string):
|
||||
"""Perform local variable substution, e.g. 'total: {num} items'"""
|
||||
# http://stackoverflow.com/questions/2960772/
|
||||
# putting-a-variable-inside-a-string-python
|
||||
# http://stackoverflow.com/questions/6618795/
|
||||
# get-locals-from-calling-namespace-in-python
|
||||
import inspect
|
||||
frame = inspect.currentframe()
|
||||
try:
|
||||
rVal = string.format(**frame.f_back.f_locals)
|
||||
finally:
|
||||
del frame
|
||||
return rVal
|
||||
|
||||
def get_object_names(cls, include_subclasses=True):
|
||||
object_names = []
|
||||
for (this_object_name, this_object_id) in list(globals().items()):
|
||||
if include_subclasses:
|
||||
if isinstance(this_object_id, cls):
|
||||
object_names.append(this_object_name)
|
||||
else:
|
||||
if type(this_object_id) is cls:
|
||||
object_names.append(this_object_name)
|
||||
return object_names
|
||||
|
||||
def touch(filePath, modTime=None):
|
||||
# http://stackoverflow.com/questions/1158076/implement-touch-using-python
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "ab"):
|
||||
os.utime(filePath, (None if (modTime is None) else (modTime, modTime)))
|
||||
|
||||
def mkdir(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.mkdir(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def makedirs(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.makedirs(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def loadFile(filePath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "rb") as imageHandle:
|
||||
return imageHandle.read()
|
||||
|
||||
def saveFile(filePath, fileData):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "wb") as imageHandle:
|
||||
imageHandle.write(fileData)
|
||||
|
||||
def isnumber(number):
|
||||
try: # make sure it's not a string
|
||||
len(number)
|
||||
return False
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
int(number)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
#---- end IvanX general purpose functions ----#
|
||||
|
||||
|
||||
# --- start
|
||||
|
||||
args = sys.argv
|
||||
if (len(args) == 1):
|
||||
usage()
|
||||
|
||||
if (args[1] == "-s"):
|
||||
g.silent=1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-ad"):
|
||||
g.AD = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-e"):
|
||||
if g.AD: usage()
|
||||
g.EX = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-cat"):
|
||||
g.DIR = 1
|
||||
args = args[1:]
|
||||
|
||||
if not ((g.DIR and len(args) >= 2) or (len(args) >= 3)):
|
||||
usage()
|
||||
if ((len(args) == 4) and
|
||||
(slyce(args[2],0,1) != "/") and
|
||||
(slyce(args[2],0,1) != ":")):
|
||||
usage()
|
||||
|
||||
g.imageFile = args[1]
|
||||
if not os.path.isfile(g.imageFile):
|
||||
print("Source " + g.imageFile + " was not found.")
|
||||
sys.exit(2)
|
||||
g.imageData = loadFile(g.imageFile)
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = args[2].upper()
|
||||
targetPath = args[3]
|
||||
if os.path.isdir(targetPath):
|
||||
g.targetDir = targetPath
|
||||
else:
|
||||
g.targetDir = targetPath.rsplit("/", 1)[0]
|
||||
g.targetName = targetPath.rsplit("/", 1)[1]
|
||||
if not os.path.isdir(g.targetDir):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
if not os.path.isdir(args[2]):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
|
||||
g.activeDirBlock = 0
|
||||
g.activeFileName = ""
|
||||
g.activeFileSize = 0
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
g.PDOSPATH_INDEX = 0
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = g.PDOSPATH.replace(':', '/').split('/')
|
||||
if not g.PDOSPATH[0]:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
mkdir(g.ADdir)
|
||||
processDir(2)
|
||||
print("ProDOS file not found within image file.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
# print(args[0], args[1], args[2])
|
||||
g.targetDir = (args[2] + "/" + getVolumeName().decode("L1"))
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not os.path.isdir(g.targetDir):
|
||||
makedirs(g.targetDir)
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
processDir(2)
|
||||
if not g.DIR:
|
||||
syncExit()
|
||||
|
@ -1,80 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# follows gzip syntax -- acts in place if filename provided, outputs to
|
||||
# stdout with -c, accepts stdin and outputs to stdout if filename is - or absent
|
||||
|
||||
# output to stdout?
|
||||
if [[ "$1" == "-c" ]]; then
|
||||
shift;
|
||||
stdout=1;
|
||||
else
|
||||
stdout=
|
||||
fi
|
||||
|
||||
# use stdin?
|
||||
if [[ ! $1 || "$1" == "-" ]]; then
|
||||
stdin=1
|
||||
stdout=1
|
||||
elif [[ $1 && ! -f "$1" ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename] 1>&2";
|
||||
exit 1;
|
||||
else
|
||||
stdin=
|
||||
fi
|
||||
|
||||
if [[ ! $stdout ]]; then
|
||||
#get filename extension, in lowercase
|
||||
f="$(tr [:upper:] [:lower:] <<< ${1##*.})";
|
||||
|
||||
#if it's dsk/do/po, get name without extension
|
||||
[[ "$f" == "dsk" || "$f" == "do" || "$f" == "po" ]] && of="${1%.*}" || of="$1";
|
||||
|
||||
#if name had .po extension, append .dsk to outfile name, otherwise append .po
|
||||
[[ "$f" == "po" ]] && of="$of.dsk" || of="$of.po"
|
||||
|
||||
# set outfile param for dd
|
||||
ofile="$of"
|
||||
else
|
||||
ofile="/tmp/$$.dopo_out"
|
||||
fi
|
||||
|
||||
if [[ ! $stdin ]]; then
|
||||
# set infile param for dd
|
||||
ifile="$1"
|
||||
elif [[ -t 0 ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename]" 1>&2; exit 1;
|
||||
else
|
||||
ifile="/tmp/$$.dopo_in"
|
||||
cat > "$ifile"
|
||||
fi
|
||||
|
||||
# verify file is 140K by successfully reading 140K'th byte, and failing to read the one past
|
||||
[[ $(dd if="$ifile" of=/dev/null bs=1 skip=143359 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 1 || $(dd if="$ifile" of=/dev/null bs=1 skip=143360 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 0 ]] && badInput=1 || badInput=
|
||||
|
||||
if [[ $badInput ]]; then
|
||||
if [[ ! $stdin ]]; then
|
||||
echo -n "$1 doesn't appear to be a 140K image. Continue? " 1>&2;
|
||||
read
|
||||
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]] || exit 1;
|
||||
else
|
||||
echo "warning: Input file doesn't appear to be a 140K image." 1>&2
|
||||
echo " Output file is likely to be useless." 1>&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# for each track
|
||||
for t in {0..34}; do
|
||||
# read each sector in the right sequence to make (or unmake)
|
||||
# valid ProDOS blocks (sector pairs)
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
# copy the sector from the old file to the new one
|
||||
dd if="$ifile" of="$ofile" bs=256 count=1 skip=$(( t*16 + s )) seek=$(( t*16 + (s==0 || s==15 ? s : 15-s) )) 2> /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
# remove the old one
|
||||
[[ ! $stdin && ! $stdout ]] && rm "$1" &> /dev/null
|
||||
|
||||
# dump to stdout if -c or stdin used
|
||||
[[ $stdout ]] && { cat $ofile; rm $ofile &> /dev/null; }
|
||||
[[ $stdin ]] && rm $ifile &> /dev/null;
|
@ -1,124 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
readcharDec () {
|
||||
# read one character from file & convert to equivalent decimal value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
### start
|
||||
|
||||
usage () {
|
||||
echo "Usage:"
|
||||
echo "all files: dos2pro dosImageName"
|
||||
echo "one file : dos2pro dosImageName DOSFILE"
|
||||
echo "notes:"
|
||||
echo " Wildcard matching (*) is not supported."
|
||||
echo " Illegal prodos characters will be made into periods, and names"
|
||||
echo " will be truncated at 15 characters and possibly overwrite"
|
||||
echo " other files if they match a previous name conversion."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $1 == "-h" || $1 == "--help" || ! $1 || ! -f "$1" ]] && usage
|
||||
|
||||
dosImage="$1"
|
||||
fileName="$2"
|
||||
|
||||
dosImageBasename=$(basename "$dosImage")
|
||||
proImage="${dosImageBasename%.*}_prodos.po"
|
||||
|
||||
if [[ ! -f "$proImage" ]]; then
|
||||
echo "Creating $proImage..."
|
||||
mkpo -b 280 "$proImage"
|
||||
else
|
||||
echo "Found $proImage..."
|
||||
fi
|
||||
|
||||
if [[ ! $(acmd -i "$dosImage" 2> /dev/null | grep "Disk Format: DOS 3.3") ]]; then
|
||||
echo "The file '$dosImage' doesn't appear to be a DOS 3.3 disk image."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dosLines=$(acmd -ll "$dosImage")
|
||||
|
||||
IFS=''
|
||||
while read thisLine; do
|
||||
if [[ ${thisLine:0:2} == "* " || ${thisLine:0:2} == " " ]]; then
|
||||
dosName=$(cut -c 5- <<< $thisLine | rev | sed 's/^[^ ]* [^ ]* [^ ]* [^ ]* [^ ]* \(.*$\)/\1/' | rev)
|
||||
if [[ ! $fileName || "$fileName" == "$dosName" ]]; then
|
||||
|
||||
dosType=$(cut -c 3 <<< $thisLine)
|
||||
if [[ $dosType == "A" ]]; then
|
||||
proType="BAS"
|
||||
binAddr="0801"
|
||||
elif [[ $dosType == "I" ]]; then
|
||||
proType="INT"
|
||||
elif [[ $dosType == "T" ]]; then
|
||||
proType="TXT"
|
||||
elif [[ $dosType == "B" ]]; then
|
||||
proType="BIN"
|
||||
sector=$(rev <<< $thisLine | cut -f2 -d ' ' | rev | cut -c 2-)
|
||||
track=$(rev <<< $thisLine | cut -f3 -d ' ' | rev | cut -c 2-)
|
||||
offset=$(( (track * 16 + sector) * 256 + 12 ))
|
||||
track=$(readcharDec "$dosImage" $offset)
|
||||
sector=$(readcharDec "$dosImage" $((offset+1)))
|
||||
offset=$(( (track * 16 + sector) * 256 ))
|
||||
binAddr=$(readcharHex "$dosImage" $((offset+1)))$(readcharHex "$dosImage" $offset)
|
||||
else
|
||||
echo "Error: Unknown DOS 3.3 file type."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
proName=$(sed 's/^[^A-Za-z]/A/' <<< $dosName | sed 's/[^A-Za-z0-9\.]/./g')
|
||||
|
||||
auxType=
|
||||
[[ $binAddr ]] && auxType="\$$binAddr"
|
||||
echo "Copying '$dosName' to '$proName'"
|
||||
acmd -g "$dosImage" "$dosName" - | acmd -p "$proImage" "$proName" "$proType" "$auxType"
|
||||
filesCopied=1
|
||||
fi
|
||||
fi
|
||||
done <<< $dosLines
|
||||
|
||||
if [[ ! $filesCopied ]]; then
|
||||
if [[ $fileName ]]; then
|
||||
echo "File '$fileName' not found on DOS 3.3 disk image."
|
||||
else
|
||||
echo "No files copied."
|
||||
fi
|
||||
fi
|
@ -1,6 +0,0 @@
|
||||
wget -qO /tmp/gsport-setup appleii.ivanx.com/a2cloud/setup/gsport-setup.txt
|
||||
if [[ $(wc -c /tmp/gsport-setup | grep '^0 ') ]]; then
|
||||
echo "Please connect to the internet to set up GSport."
|
||||
else
|
||||
source /tmp/gsport-setup "$@"
|
||||
fi
|
@ -1,573 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n') | tr [A-Z] [a-z]
|
||||
}
|
||||
|
||||
readchars () {
|
||||
# read one or more characters from a file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is until end of file)
|
||||
# out: sequence of characters
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11
|
||||
[[ $4 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
[[ $3 ]] && { [[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) ]] || return 23; }
|
||||
# args are valid
|
||||
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
||||
2> /dev/null
|
||||
}
|
||||
|
||||
writecharsHex () {
|
||||
# write corresponding characters of hex values into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF, period delimited (not checked!)
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
p=0
|
||||
offset=$2
|
||||
len=${#3}
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2}
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == \
|
||||
$(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$outByte" | \
|
||||
dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null
|
||||
(( p += 3 ))
|
||||
(( offset++ ))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
### start
|
||||
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1 || isRpi=
|
||||
|
||||
emulatorName="GSport"
|
||||
emulatorStart="gsport"
|
||||
emulatorSetup="gsport-setup"
|
||||
romFileName="ROM"
|
||||
configFileName="config.txt"
|
||||
|
||||
imagesDir="/usr/local/share/gsdisks"
|
||||
gsosHD="gsoshd.hdv"
|
||||
gsosHDvolName="GSOS.HD"
|
||||
tempDir="/tmp/gs"
|
||||
|
||||
rom=ROM3
|
||||
slot6=
|
||||
autoAnswerYes=
|
||||
noDisks=
|
||||
gisk=
|
||||
installDisks=
|
||||
kegs=
|
||||
|
||||
{ acmd &> /dev/null || [[ $? -ne 127 ]]; } && acmdOK=1 || acmdOK=
|
||||
|
||||
|
||||
while { [[ $1 ]] || (( (0 + $gisk + $noDisks + $installDisks + 0) > 1 )); }; do
|
||||
arg=$(tr -d '-' <<< ${1,,})
|
||||
if [[ $arg == "6" ]]; then
|
||||
slot6=1
|
||||
shift
|
||||
elif [[ $arg == "rom1" ]]; then
|
||||
rom=ROM1
|
||||
shift
|
||||
elif [[ $arg == "rom3" ]]; then
|
||||
rom=ROM3
|
||||
shift
|
||||
elif [[ $arg == "n" ]]; then
|
||||
noDisks=1
|
||||
shift
|
||||
elif [[ $arg == "g" ]]; then
|
||||
gisk=1
|
||||
shift
|
||||
elif [[ $arg == "i" ]]; then
|
||||
installDisks=1
|
||||
shift
|
||||
elif [[ $arg == "y" ]]; then
|
||||
autoAnswerYes=1
|
||||
shift
|
||||
elif [[ $arg == "k" ]]; then
|
||||
kegs=1
|
||||
shift
|
||||
else
|
||||
echo "Usage: $emulatorSetup [rom1|rom3] [-6] [-y [-g|-i|-n]]"
|
||||
echo "rom1: use GS ROM 01"
|
||||
echo "rom3: use GS ROM 03"
|
||||
echo "-k: set up KEGS (rather than GSport)"
|
||||
echo "-6: put blank disks in slot 6"
|
||||
echo "-y: auto-answer yes (no prompting)"
|
||||
echo "-i: use GS/OS and Spectrum installer disk images (use with -y)"
|
||||
echo "-g: use GSport Internet Starter Kit disk image (use with -y)"
|
||||
echo "-n: don't provide any disk images (use with -y)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $kegs ]]; then
|
||||
emulatorName="KEGS"
|
||||
emulatorStart="kegs"
|
||||
emulatorSetup="kegs-setup"
|
||||
romFileName="rom.kegs"
|
||||
configFileName="config.kegs"
|
||||
fi
|
||||
|
||||
echo
|
||||
if [[ ! -f /usr/local/lib/$romFileName ]]; then
|
||||
echo "$emulatorName needs to be set up. This may take several minutes."
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Do you want to set up $emulatorName now? ";
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Ok, let's go!"
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
noDisks=
|
||||
gisk=
|
||||
while true; do
|
||||
option1=0
|
||||
option2=0
|
||||
echo
|
||||
echo "Do you want to:"
|
||||
echo
|
||||
if [[ $acmdOK ]]; then
|
||||
[[ $kegs ]] && andSpectrum= || andSpectrum="and Spectrum "
|
||||
echo "1) install GS/OS ${andSpectrum}from the installer disk images"
|
||||
option1=1
|
||||
fi
|
||||
if [[ ! $kegs ]]; then
|
||||
echo "2) use the premade GSport Internet Starter Kit hard drive image"
|
||||
option2=2
|
||||
fi
|
||||
echo "3) prepare $emulatorName for use but don't provide any disk images"
|
||||
echo "4) do nothing and quit"
|
||||
echo
|
||||
echo -n "Your choice: "
|
||||
read
|
||||
noDisks=
|
||||
if [[ ${REPLY} == "4" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
elif [[ ${REPLY} == "3" ]]; then
|
||||
noDisks=1; break
|
||||
elif [[ ${REPLY} == $option2 ]]; then
|
||||
gisk=1; break
|
||||
elif [[ ${REPLY} == $option1 ]]; then
|
||||
gisk=; break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$imagesDir"
|
||||
sudo chmod ugo+rw "$imagesDir"
|
||||
mkdir -p "$tempDir"
|
||||
cd "$tempDir"
|
||||
|
||||
echo "Updating package lists..."
|
||||
sudo apt-get -y update > /dev/null
|
||||
|
||||
if [[ ! -f /usr/local/bin/unar ]]; then
|
||||
echo "Installing The Unarchiver..."
|
||||
sudo apt-get -y install libgnustep-base1.22
|
||||
sudo apt-get -y clean
|
||||
wget -qO- appleii.ivanx.com/a2cloud/setup/unar.tgz | sudo tar Pzx
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/bin/mkpo ]]; then
|
||||
echo "Installing mkpo..."
|
||||
sudo wget -qO /usr/local/bin/mkpo appleii.ivanx.com/a2cloud/setup/mkpo.txt
|
||||
sudo chmod ugo+x /usr/local/bin/mkpo
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/bin/nulib2 ]]; then
|
||||
echo "Installing nulib2..."
|
||||
wget -qO- appleii.ivanx.com/a2cloud/setup/nulib2.tgz | sudo tar Pzx
|
||||
fi
|
||||
|
||||
if [[ ! -f $imagesDir/ROM1 ]]; then
|
||||
echo "Getting GS ROM 01..."
|
||||
wget -qO ROM1.zip http://web.archive.org/web/20130216031247/http://www.whatisthe2gs.apple2.org.za/files/rom1.zip
|
||||
unzip ROM1.zip &> /dev/null
|
||||
mv APPLE2GS.ROM $imagesDir/ROM1
|
||||
chmod ugo-w $imagesDir/ROM1
|
||||
fi
|
||||
|
||||
if [[ ! -f $imagesDir/ROM3 ]]; then
|
||||
echo "Getting GS ROM 3..."
|
||||
wget -qO ROM3.zip http://web.archive.org/web/20130216031247/http://www.whatisthe2gs.apple2.org.za/files/rom3.zip
|
||||
unzip ROM3.zip &> /dev/null
|
||||
mv APPLE2GS.ROM2 $imagesDir/ROM3
|
||||
chmod ugo-w $imagesDir/ROM3
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/lib/$romFileName || $arg ]]; then
|
||||
echo "Setting $emulatorName to use $rom..."
|
||||
echo " (to change, use '$emulatorSetup rom1' or '$emulatorSetup rom3')"
|
||||
sudo rm /usr/local/lib/$romFileName &> /dev/null
|
||||
sudo ln -s $imagesDir/$rom /usr/local/lib/$romFileName &> /dev/null
|
||||
sudo ln -s $romFileName /usr/local/lib/ROM &> /dev/null
|
||||
fi
|
||||
|
||||
if [[ $slot6 ]]; then
|
||||
echo "Putting blank disks in slot 6..."
|
||||
sudo sed -i 's@^s6d1.*$@s6d1 = $imagesDir/slot6drive1.po@' /usr/local/lib/$configFileName
|
||||
sudo sed -i 's@^s6d2.*$@s6d2 = $imagesDir/slot6drive2.po@' /usr/local/lib/$configFileName
|
||||
if [[ ! -f $imagesDir/slot6drive1.po || ! -f $imagesDir/slot6drive2.po ]]; then
|
||||
wget -qO- ivanx.com/a2cloud/files/slot6.tgz | sudo tar Pzx 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $kegs ]]; then
|
||||
# set AppleTalk to turbo (works more reliably than Normal)
|
||||
echo "Setting AppleTalk to turbo..."
|
||||
if ! grep -q 'g_appletalk_turbo' /usr/local/lib/$configFileName; then
|
||||
if grep -q 'bram1\[00\]' /usr/local/lib/$configFileName; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_appletalk_turbo = 1\n\n\1/' /usr/local/lib/$configFileName
|
||||
else
|
||||
echo -e '\ng_appletalk_turbo = 1' | sudo tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/g_appletalk_turbo = 0/g_appletalk_turbo = 1/' /usr/local/lib/$configFileName
|
||||
|
||||
# enable Uthernet
|
||||
echo "Enabling Uthernet card emulation..."
|
||||
if ! grep -q 'g_ethernet[^_]' /usr/local/lib/$configFileName; then
|
||||
if grep -q 'bram1\[00\]' /usr/local/lib/$configFileName; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_ethernet = 1\n\n\1/' /usr/local/lib/$configFileName
|
||||
else
|
||||
echo -e '\ng_ethernet = 1' | sudo tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/g_ethernet = 0/g_ethernet = 1/' /usr/local/lib/$configFileName
|
||||
|
||||
# GISK
|
||||
if [[ $gisk ]]; then
|
||||
echo "Getting GSport Internet Starter Kit..."
|
||||
wget -O /tmp/GSport_Internet_Starter_Kit.zip http://sourceforge.net/projects/gsport/files/Emulator%20Software%20Images/GSport_Internet_Starter_Kit.zip
|
||||
unzip -d /tmp /tmp/GSport_Internet_Starter_Kit.zip "GSport Internet Starter Kit/GSport Internet Starter Kit.2mg"
|
||||
sudo mv "/tmp/GSport Internet Starter Kit/GSport Internet Starter Kit.2mg" $imagesDir
|
||||
rm -r /tmp/GSport*
|
||||
if [[ $(grep ^s7d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d1.*$:s7d1 = $imagesDir/GSport Internet Starter Kit.2mg:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d1 = $imagesDir/GSport Internet Starter Kit.2mg" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
noDisks=1
|
||||
fi
|
||||
if [[ $noDisks ]]; then
|
||||
echo
|
||||
echo
|
||||
echo "Setup complete. You can now start $emulatorName."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Press return to continue..."
|
||||
read
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# non-GISK; get installer disks
|
||||
if [[ ! -f $imagesDir/INSTALL.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEM.DISK.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEMTOOLS1.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEMTOOLS2.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/FONTS.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYNTHLAB.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/"$gsosHD" ]] \
|
||||
|| [[ ! $kegs && ! -f $imagesDir/spectrum.hdv ]]; then
|
||||
|
||||
# if [[ ! $autoAnswerYes ]]; then
|
||||
# echo
|
||||
# echo -n "Do you want to download the GS/OS installer disks"
|
||||
# if [[ ! -f $imagesDir/"$gsosHD" ]]; then
|
||||
# echo -n -e "\nand create a hard disk image file"
|
||||
# fi
|
||||
# if [[ ! $kegs && -f /usr/local/bin/acmd && ! -f $imagesDir/spectrum.hdv ]]; then
|
||||
# echo -n -e "\nand download Spectrum communications software"
|
||||
# fi
|
||||
# echo -n "? "
|
||||
# read
|
||||
# fi
|
||||
|
||||
REPLY="y"
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo
|
||||
activeDisk=0
|
||||
for diskname in Install System.Disk SystemTools1 SystemTools2 Fonts synthLAB; do
|
||||
(( activeDisk++ ))
|
||||
outfile="$imagesDir/$(tr [:lower:] [:upper:] <<< $diskname).HDV"
|
||||
if [[ ! -f "$outfile" ]]; then
|
||||
echo "Getting GS/OS disk ${activeDisk} of 6: $diskname"
|
||||
wget -qO "Disk_${activeDisk}_of_7-$diskname.sea.bin" "http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FApple_II%2FApple_IIGS_System_6.0.1%2FDisk_${activeDisk}_of_7-$diskname.sea.bin"
|
||||
unar -k skip "Disk_${activeDisk}_of_7-$diskname.sea.bin" &> /dev/null
|
||||
truncate -s 819284 "Disk ${activeDisk} of 7-${diskname}.sea"
|
||||
dd if="Disk ${activeDisk} of 7-${diskname}.sea" of=${outfile} bs=84 skip=1 &> /dev/null
|
||||
chmod ugo-w "$outfile"
|
||||
if [[ $activeDisk -eq 1 ]]; then
|
||||
if [[ $(grep ^s5d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s5d1.*$:s5d1 = $imagesDir/INSTALL.HDV:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s5d1 = $imagesDir/INSTALL.HDV" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
else
|
||||
if [[ $(grep ^s7d$activeDisk /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d$activeDisk.*$:s7d$activeDisk = $outfile:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d$activeDisk = $outfile" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "GS/OS disk ${activeDisk} of 6: $diskname has already been downloaded."
|
||||
fi
|
||||
done
|
||||
rm *.sea* &> /dev/null
|
||||
|
||||
if [[ ! -f $imagesDir/"$gsosHD" ]]; then
|
||||
echo "Creating 32 MB blank image at $imagesDir/$gsosHD..."
|
||||
if [[ -f /usr/local/bin/acmd ]]; then
|
||||
# if acmd exists, make a ProDOS disk with GS-ShrinkIt and Teach
|
||||
|
||||
if [[ ! -f /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar ]]; then
|
||||
echo "Installing AppleCommander-1.3.5.13id..."
|
||||
sudo mkdir -p /usr/local/adtpro/lib/AppleCommander
|
||||
wget -qO /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar http://downloads.sourceforge.net/project/applecommander/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar
|
||||
rm /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar &> /dev/null
|
||||
ln -s AppleCommander-1.3.5.13id-ac.jar /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar
|
||||
fi
|
||||
|
||||
echo "Copying ProDOS..."
|
||||
acmd -g "$imagesDir/INSTALL.HDV" PRODOS "PRODOS#ff0000"
|
||||
#writecharsHex "PRODOS#ff0000" 0 "4C.00.C5.00"
|
||||
wget -qO- ivanx.com/a2cloud/files/${emulatorName}SPLASH.SYS | dd of="PRODOS#ff0000" conv=notrunc &> /dev/null
|
||||
echo "Copying Teach..."
|
||||
cppo -e $imagesDir/SYSTEMTOOLS2.HDV /SYSTEMTOOLS2/TEACH . &> /dev/null
|
||||
echo "Downloading GS-ShrinkIt..."
|
||||
wget -qO- http://web.archive.org/web/20131031160750/http://nulib.com/library/gshk11.sea | nulib2 -x -e - GSHK &> /dev/null
|
||||
nulib2 -a -e $gsosHD.shk "PRODOS#"* "GSHK#"* "TEACH#"* &> /dev/null
|
||||
acmd -convert $gsosHD.shk $imagesDir/"$gsosHD" 65535
|
||||
rm "PRODOS#"* "GSHK#"* "TEACH#"* $gsosHD.shk &> /dev/null
|
||||
|
||||
acmd -n $imagesDir/"$gsosHD" $gsosHDvolName
|
||||
dd bs=512 count=1 conv=notrunc if="$imagesDir/INSTALL.HDV" of="$imagesDir/$gsosHD" 2> /dev/null
|
||||
sudo chmod ugo+rw $imagesDir/"$gsosHD"
|
||||
#acmd -p "$imagesDir/$gsosHD" PRODOS SYS < $tempDir/PRODOS
|
||||
#rm $tempDir/PRODOS
|
||||
fi
|
||||
if [[ $(grep ^s7d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d1.*$:s7d1 = $imagesDir/$gsosHD:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d1 = $imagesDir/$gsosHD" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $(grep ^g_limit_speed /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^g_limit_speed.*$:g_limit_speed = 0:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "g_limit_speed = 0" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
|
||||
if [[ -f /usr/local/bin/acmd && ! $(acmd -ls $imagesDir/$gsosHD | grep 'GSHK') ]]; then
|
||||
echo
|
||||
echo "Downloading GS-ShrinkIt..."
|
||||
wget -qO- http://web.archive.org/web/20131031160750/http://nulib.com/library/gshk11.sea | acmd -p $imagesDir/$gsosHD GS.SHRINKIT.SEA S16
|
||||
fi
|
||||
|
||||
|
||||
# Spectrum starts here
|
||||
|
||||
if [[ ! $kegs ]]; then
|
||||
|
||||
mkdir -p /tmp/spectrum
|
||||
cd /tmp/spectrum
|
||||
|
||||
imageName="/tmp/spectrum/spectrum.dmg"
|
||||
hfsName="/tmp/spectrum/spectrumH.dmg"
|
||||
ullName="/tmp/spectrum/uthernet.bxy"
|
||||
|
||||
if [[ ! -f /usr/bin/hcopy || ! -f /usr/bin/macsave ]]; then
|
||||
echo "Installing HFS utilities..."
|
||||
sudo apt-get -y install hfsutils macutils &> /dev/null
|
||||
else
|
||||
echo "HFS utilities are already installed."
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar ]]; then
|
||||
echo "Installing AppleCommander..."
|
||||
sudo mkdir -p /usr/local/adtpro/lib/AppleCommander
|
||||
wget -qO /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar http://downloads.sourceforge.net/project/applecommander/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar
|
||||
rm /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar &> /dev/null
|
||||
ln -s AppleCommander-1.3.5.13id-ac.jar /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar
|
||||
fi
|
||||
|
||||
if [[ ! -f "$imageName" ]]; then
|
||||
echo "Downloading Spectrum Deluxe..."
|
||||
wget -qO spectrum.dmg http://www.wannop.info/speccie/software/spectrum_2.5.3_deluxe.dmg
|
||||
else
|
||||
echo "Spectrum Deluxe has already been downloaded."
|
||||
fi
|
||||
|
||||
mkdir -p mnt
|
||||
mkdir -p extract
|
||||
mkdir -p shkstage
|
||||
cp "$imageName" "$hfsName"
|
||||
sudo mount -r -t hfs "$imageName" mnt
|
||||
hmount "$hfsName"
|
||||
|
||||
IFS=''
|
||||
cd /tmp/spectrum/mnt
|
||||
find Spectrum.2.5.3 -type d | while read thisDirPath; do
|
||||
mkdir -p /tmp/spectrum/shkstage/"$thisDirPath"
|
||||
hcd
|
||||
IFS='/'
|
||||
for thisDir in $thisDirPath; do
|
||||
hcd $thisDir
|
||||
done
|
||||
echo " Copying: $(hpwd)"
|
||||
IFS=''
|
||||
cd /tmp/spectrum/extract
|
||||
hls -1 | while read thisFile; do
|
||||
hcopy -m "$thisFile" - 2> /dev/null | macsave -f 2> /dev/null
|
||||
if [[ -f "$thisFile".info ]]; then
|
||||
if [[ $(readcharHex "$thisFile".info 65) == "70" ]]; then
|
||||
fileType=$(readcharHex "$thisFile".info 66)
|
||||
auxType=$(readcharHex "$thisFile".info 67)$(readcharHex "$thisFile".info 68)
|
||||
else
|
||||
auxType="0000"
|
||||
fMac=$(readchars "$thisFile".info 65 4)
|
||||
if [[ "$fMac" == "PS16" ]]; then
|
||||
fileType="b3";
|
||||
elif [[ "$fMac" == "PSYS" ]]; then
|
||||
fileType="ff";
|
||||
elif [[ "$fMac" == "BINA" ]]; then
|
||||
fileType="00";
|
||||
elif [[ "$fMac" == "TEXT" ]]; then
|
||||
fileType="04";
|
||||
elif [[ "$fMac" == "MIDI" ]]; then
|
||||
fileType="D7";
|
||||
elif [[ "$fMac" == "AIFF" || "$fMac" == "AIFC" ]]; then
|
||||
fileType="D8";
|
||||
elif [[ "$fMac" == "dImg" ]]; then
|
||||
fileType="E0";
|
||||
else
|
||||
echo "WARNING: unknown file type '$fMac' found for file $thisFile"
|
||||
fi
|
||||
fi
|
||||
[[ -f "$thisFile".rsrc ]] && mv "$thisFile".rsrc /tmp/spectrum/shkstage/"$thisDirPath"/"${thisFile}#${fileType}${auxType}r"
|
||||
[[ -f "$thisFile".data ]] && mv "$thisFile".data /tmp/spectrum/shkstage/"$thisDirPath"/"${thisFile}#${fileType}${auxType}"
|
||||
rm "$thisFile".info 2> /dev/null
|
||||
fi
|
||||
done
|
||||
cd /tmp/spectrum/mnt
|
||||
done
|
||||
|
||||
cd /tmp/spectrum/shkstage/Spectrum*
|
||||
humount
|
||||
sudo umount /tmp/spectrum/mnt
|
||||
|
||||
mkdir -p Marinetti/Uthernet
|
||||
cp SAFE2.Archive/Link.Layers/"Uthernet#bc4083" Marinetti/Uthernet
|
||||
echo -n "After installing Marinetti, put Uthernet in the TCPIP folder of your System folder, and restart GS/OS. Then open Control Panels, choose TCP/IP, and choose Setup Connection. Choose Uthernet for the link layer. Under Primary Domain Name Server, enter 8.8.8.8, then click Configure and select Slot 3 and DHCP. Then click Save." > Marinetti/Uthernet/"Uthernet.README#040000"
|
||||
|
||||
echo "Making archive for conversion to disk image..."
|
||||
rm /tmp/spectrum/spectrum.shk 2> /dev/null
|
||||
nulib2 -a -r -0 -e /tmp/spectrum/spectrum.shk * &> /dev/null
|
||||
echo "Converting archive to disk image..."
|
||||
acmd -convert /tmp/spectrum/spectrum.shk $imagesDir/spectrum.hdv 20480
|
||||
acmd -n $imagesDir/spectrum.hdv SPECTRUM.DELUXE
|
||||
|
||||
if [[ $(grep ^s7d7 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d7.*$:s7d7 = $imagesDir/spectrum.hdv:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d7 = $imagesDir/spectrum.hdv" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
|
||||
cd /tmp
|
||||
|
||||
rm -rf /tmp/spectrum/extract /tmp/spectrum/shkstage /tmp/spectrum/spectrum.shk /tmp/spectrum/mnt &> /dev/null
|
||||
fi
|
||||
# Spectrum ends here
|
||||
fi
|
||||
fi
|
||||
|
||||
cd
|
||||
rm -r "$tempDir"
|
||||
|
||||
echo
|
||||
echo
|
||||
if [[ -f "$imagesDir/$gsosHD" ]]; then
|
||||
echo
|
||||
echo "You can now start $emulatorName."
|
||||
echo "When the installer boots, you can click Easy Update or Customize"
|
||||
echo "to install GS/OS, if you downloaded the installer disks aobve."
|
||||
else
|
||||
# if no acmd, create unformatted disk
|
||||
# requires that the disk first be formatted with Advanced Disk Utility
|
||||
dd bs=512 count=65535 if=/dev/zero of=$imagesDir/"$gsosHD" 2> /dev/null
|
||||
writecharsHex $imagesDir/"$gsosHD" 0 "00.4C.00.C5.00"
|
||||
echo
|
||||
echo "You can now start $emulatorName."
|
||||
echo
|
||||
echo "If you downloaded the installer disks above:"
|
||||
echo "When the installer boots, quit it, change to the SystemTools1 disk,"
|
||||
echo "run Advanced Disk Utility, click Disk until a hard drive icon appears"
|
||||
echo "that says Uninitialized, and initialize it. Then quit Advanced Disk"
|
||||
echo "Utility, change to the Install Disk, and run Installer. When it loads,"
|
||||
echo "click Easy Update or Customize to install GS/OS."
|
||||
echo
|
||||
fi
|
||||
echo "When it's done, reboot."
|
||||
echo "(Use Shut Down, ctrl-F12, or ctrl-solidapple-equals.)"
|
||||
if [[ -f "$imagesDir/spectrum.hdv" ]]; then
|
||||
echo
|
||||
echo "Then on the Spectrum disk, optionally install:"
|
||||
echo "Marinetti (plus update): TCP/IP driver for GS/OS"
|
||||
echo "Uthernet: Ethernet driver for Marinetti"
|
||||
echo "Spectrum: serial and telnet communications"
|
||||
echo "SAFE: FTP client"
|
||||
echo "SNAP: Usenet newsgroups (NNTP) client"
|
||||
echo "SAM2: Email (POP) client"
|
||||
fi
|
||||
echo
|
||||
echo "After installing, press F4 and choose 'Disk Configuration' to"
|
||||
echo "eject all disks other than slot 7 drive 1."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Press return to continue..."
|
||||
read
|
||||
fi
|
@ -1,122 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run GSport on the console, or in an X Window."
|
||||
else
|
||||
|
||||
if [[ -f /usr/local/lib/ROM ]]; then
|
||||
if [[ ! $(grep snd-pcm-oss /etc/modules) ]]; then
|
||||
echo "Configuring GSport sound..."
|
||||
echo "snd-pcm-oss" | sudo tee -a /etc/modules > /dev/null
|
||||
[[ ! $(lsmod | grep snd_pcm_oss) ]] && sudo modprobe snd-pcm-oss
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l xfonts-base 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport fonts..."
|
||||
sudo apt-get -y update
|
||||
touch /tmp/updated
|
||||
sudo apt-get -y install xfonts-base &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l libpcap0.8-dev 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport networking..."
|
||||
[[ ! -f /tmp/updated ]] && sudo apt-get -y update
|
||||
sudo apt-get -y install libpcap0.8-dev &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
rm /tmp/updated &> /dev/null
|
||||
else
|
||||
gsport-setup
|
||||
[[ $? -ne 0 ]] && exit 1
|
||||
fi
|
||||
|
||||
displayOK=
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
displayOK=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /usr/local/etc/gsportconsolewarningoff ]] && { dpkg -l | grep -q -i virtualbox; }; then
|
||||
echo
|
||||
echo "If you have difficulties moving the mouse in GS/OS, choose"
|
||||
echo "'Disable Mouse Integration' from the Machine menu. To free the mouse"
|
||||
echo "from the virtual machine, press the Host key (shown in the lower right"
|
||||
echo "corner of the virtual machine window)."
|
||||
echo
|
||||
echo "Press alt-F4 to exit GSport."
|
||||
echo
|
||||
echo "Press return to continue,"
|
||||
echo -n " or type 'OK' if you want to stop seeing this message: "
|
||||
read
|
||||
if [[ $REPLY == "ok" || $REPLY == "ok" || $REPLY == "Ok" ]]; then
|
||||
sudo touch /usr/local/etc/gsportconsolewarningoff
|
||||
fi
|
||||
# echo "If you wish to run GSport in the console window, the mouse will not work"
|
||||
# echo "unless you uninstall VirtualBox Guest Additions. If you don't want to do"
|
||||
# echo "this, you can instead run GSport in an X window (e.g. by typing 'startx')."
|
||||
# echo "If you're not sure, just uninstall it now. Nothing terrible will happen."
|
||||
# echo
|
||||
# echo -n "Do you want to uninstall VirtualBox Guest Additions now? "
|
||||
# read
|
||||
# if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
# echo "Ok, on the case..."
|
||||
# sudo /etc/init.d/vboxadd-service stop 2> /dev/null
|
||||
# sudo /etc/init.d/virtualbox-guest-utils stop &> /dev/null
|
||||
# sudo rmmod vboxvideo 2> /dev/null
|
||||
# sudo rmmod vboxsf 2> /dev/null
|
||||
# sudo rmmod vboxguest 2> /dev/null
|
||||
# while { lsmod | grep -q vbox; }; do
|
||||
# sleep 1
|
||||
# sudo rmmod vboxvideo 2> /dev/null
|
||||
# sudo rmmod vboxsf 2> /dev/null
|
||||
# sudo rmmod vboxguest 2> /dev/null
|
||||
# done
|
||||
# if [ -f /opt/VBoxGuestAdditions*/uninstall.sh ]; then
|
||||
# sudo /opt/VBoxGuestAdditions*/uninstall.sh &> /dev/null
|
||||
# sudo rmdir /opt/VBoxGuestAdditions* 2> /dev/null
|
||||
# fi
|
||||
# if { dpkg -l 2> /dev/null | grep -q -i virtualbox; }; then
|
||||
# sudo apt-get -y purge $(dpkg -l 2> /dev/null | grep -i virtualbox | cut -f 3 -d ' ' | tr '\n' ' ') &> /dev/null
|
||||
# fi
|
||||
# touch /tmp/gsport-consolesetup
|
||||
# fi
|
||||
fi
|
||||
|
||||
if [[ ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/gsport-consolesetup ]] && displayOK=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing GSport for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run GSport in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/gsport-consolesetup ]]; then
|
||||
echo "GSport will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $displayOK ]]; then
|
||||
if [[ $(xdpyinfo 2> /dev/null) ]]; then
|
||||
exec gsportx
|
||||
else
|
||||
exec gsportfb
|
||||
fi
|
||||
else
|
||||
echo "GSport has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,6 +0,0 @@
|
||||
wget -qO /tmp/gsport-setup ivanx.com/a2cloud/setup/gsport-setup.txt
|
||||
if [[ $(wc -c /tmp/gsport-setup | grep '^0 ') ]]; then
|
||||
echo "Please connect to the internet to set up KEGS."
|
||||
else
|
||||
source /tmp/gsport-setup -k "$@"
|
||||
fi
|
@ -1,6 +0,0 @@
|
||||
if [[ -f /usr/local/bin/gsport-setup ]]; then
|
||||
wget -O /tmp/gsport-setup ivanx.com/a2cloud/gsport-setup.txt
|
||||
source /tmp/gsport-setup -k "$@"
|
||||
else
|
||||
gsport-setup -k "$@"
|
||||
fi
|
@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ! $DISPLAY ]]; then
|
||||
echo "Please run KEGS in an X Window."
|
||||
echo "(If you are using the console, type 'startx'.)"
|
||||
else
|
||||
if [[ -f /usr/local/lib/rom.kegs ]]; then
|
||||
if [[ ! $(grep snd-pcm-oss /etc/modules) ]]; then
|
||||
echo "Configuring KEGS sound..."
|
||||
echo "snd-pcm-oss" | sudo tee -a /etc/modules > /dev/null
|
||||
[[ ! $(lsmod | grep snd_pcm_oss) ]] && sudo modprobe snd-pcm-oss
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l xfonts-base 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring KEGS fonts..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install xfonts-base &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
exec xkegs
|
||||
else
|
||||
kegs-setup
|
||||
[[ $? -ne 0 ]] && exit 1
|
||||
exec kegs
|
||||
fi
|
||||
fi
|
@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run LinApple on the console, or in an X Window."
|
||||
else
|
||||
if [[ $(dpkg -l libsdl1.2debian libcurl3 zlib1g libzip2 2> /dev/null | grep ^ii | wc -l) -ne 4 ]]; then
|
||||
echo "Configuring LinApple libraries (this may take a moment)..."
|
||||
sudo apt-get -y update &> /dev/null
|
||||
sudo apt-get -y install libsdl1.2debian libcurl3 zlib1g libzip2 &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
linappleOk=
|
||||
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
linappleOk=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /tmp/linapple-consolesetup && ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/linapple-consolesetup ]] && linappleOk=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing LinApple for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run LinApple in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/linapple-consolesetup ]]; then
|
||||
echo "LinApple will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $linappleOk ]]; then
|
||||
cd /usr/local/linapple
|
||||
./linapple
|
||||
else
|
||||
echo "LinApple has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,160 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ID-bashByter routines
|
||||
|
||||
function binToDec ()
|
||||
{
|
||||
dec=0;
|
||||
bits=$1;
|
||||
while (( ${#bits} < 8 )); do
|
||||
bits="0$bits";
|
||||
done;
|
||||
for n in {0..7};
|
||||
do
|
||||
(( dec+=( ${bits:$n:1} * ( 2**(7-$n) ) ) ));
|
||||
done;
|
||||
echo -n $dec
|
||||
};
|
||||
|
||||
function writecharDec ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) && ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23;
|
||||
echo -n -e "\x$(printf %02X "$3")" | dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
};
|
||||
|
||||
function writecharsHex ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
p=0;
|
||||
offset=$2;
|
||||
len=${#3};
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2};
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == $(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23;
|
||||
echo -n -e "\x$outByte" | dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null;
|
||||
(( p += 3 ));
|
||||
(( offset++ ));
|
||||
done
|
||||
};
|
||||
|
||||
# mkpo
|
||||
|
||||
[[ ! -n $1 ]] && { echo "Usage: mkpo [-b totalBlocks] newImageName [PRODOS.VOL.NAME]"; exit 1; };
|
||||
|
||||
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
|
||||
[[ ! -d "$adtPath" ]] && { echo "AppleCommander not found."; exit 1; }
|
||||
|
||||
if [[ $1 == "-b" ]]; then
|
||||
totalBlocks="$2"
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
[[ -f $1 ]] && { echo "Image '$1' already exists."; exit 1; }
|
||||
|
||||
[[ $2 ]] && prodosVolName="$2" || prodosVolName="UNTITLED"
|
||||
# test ProDOS name legitimacy
|
||||
prodosVolName=$(tr [:lower:] [:upper:] <<< $prodosVolName )
|
||||
if [[ ${#prodosVolName} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $prodosVolName) ]]; then
|
||||
echo "Invalid ProDOS name: $prodosVolName"; exit 1;
|
||||
fi
|
||||
|
||||
# see if nulib2 is available; if so, acmd -convert will create image
|
||||
# with specified block size
|
||||
nulib2 &> /dev/null
|
||||
[[ $? == 2 ]] && nulib2=1 || nulib2=
|
||||
if [[ $nulib2 ]]; then
|
||||
if [[ $totalBlocks ]]; then
|
||||
imageBlocks="$totalBlocks"
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
imageBlocks=280
|
||||
else
|
||||
imageBlocks=1600
|
||||
fi
|
||||
fi
|
||||
rm /tmp/blank.shk &> /dev/null
|
||||
orig_dir="$PWD"
|
||||
cd /tmp
|
||||
rm blank.shk EMPTY &> /dev/null
|
||||
touch EMPTY
|
||||
nulib2 -a blank.shk EMPTY &> /dev/null
|
||||
cd "$orig_dir"
|
||||
acmd -convert /tmp/blank.shk "$1" $imageBlocks
|
||||
acmd -d "$1" EMPTY
|
||||
rm /tmp/blank.shk /tmp/EMPTY
|
||||
acmd -n "$1" "$prodosVolName"
|
||||
else
|
||||
# make the disk image without converting archive
|
||||
if [[ $totalBlocks || $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
acmd -pro140 "$1" $prodosVolName;
|
||||
else
|
||||
acmd -pro800 "$1" $prodosVolName;
|
||||
fi
|
||||
fi
|
||||
|
||||
# make the disk bootable
|
||||
if [ -f "$adtPath"/disks/ADTPRO*PO ]; then
|
||||
dd bs=512 count=1 of="$1" conv=notrunc < "$adtPath"/disks/ADTPRO*PO 2> /dev/null
|
||||
fi
|
||||
|
||||
# change .DSK to DOS-ordered
|
||||
if [[ ! $totalBlocks && $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
mv "$1" "$1".tmp
|
||||
for t in {0..34}; do
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
dd bs=256 count=1 if="$1".tmp of="$1" skip=$(( $t*16 + $s )) seek=$(( $t*16 + ( $s==0||$s==15 ? $s : 15-$s ) )) 2> /dev/null;
|
||||
done;
|
||||
done
|
||||
rm "$1".tmp
|
||||
fi
|
||||
|
||||
# if nulib2 isn't available, patch the disk image to use specified block size
|
||||
if [[ ! $nulib2 && $totalBlocks ]]; then
|
||||
# change total block count
|
||||
bcHex=$(printf "%04X" $totalBlocks);
|
||||
writecharsHex "$1" 1065 "${bcHex:2:2}.${bcHex:0:2}";
|
||||
|
||||
# fix FSB
|
||||
dd if=/dev/zero of="$1" bs=512 seek=280 count=$(( $totalBlocks - 280 )) 2> /dev/null;
|
||||
dd if="$1" of="$1" bs=1 skip=3073 seek=3107 count=$(( ($totalBlocks / 8) - 35 )) conv=notrunc 2> /dev/null;
|
||||
bits=$(( $totalBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
usedString="00000000";
|
||||
freeString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
freeString=$freeString"1";
|
||||
done;
|
||||
binString=$freeString${usedString:$bits};
|
||||
writecharDec "$1" $(( ( ($totalBlocks / 8) - 35) + 3107 )) $(binToDec $binString);
|
||||
fi;
|
||||
|
||||
# assign extra blocks to FSB if needed
|
||||
fsbExtraBlocks=$(( ($totalBlocks-1)/4096 ));
|
||||
if (( fsbExtraBlocks > 0 )); then
|
||||
dd if=/dev/zero of="$1" bs=1 seek=3072 count=$(( (fsbExtraBlocks > 8) + 1 )) conv=notrunc 2> /dev/null;
|
||||
(( fsbExtraBlocks-- ));
|
||||
fi;
|
||||
|
||||
bits=$(( fsbExtraBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
freeString="11111111";
|
||||
usedString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
usedString=$usedString"0";
|
||||
done;
|
||||
binString=$usedString${freeString:$bits};
|
||||
writecharDec "$1" $(( (fsbExtraBlocks>7)+3073 )) $(binToDec $binString);
|
||||
fi;
|
||||
fi
|
@ -1,16 +0,0 @@
|
||||
|
||||
Welcome to A2CLOUD!
|
||||
Instructions and help: http://appleii.ivanx.com
|
||||
|
||||
Type 'a2cloud-help' for a list of A2CLOUD commands.
|
||||
Type 'system-shutdown' to turn off your Raspberry Pi.
|
||||
|
||||
Type 'raspi-config' to configure your Raspberry Pi.
|
||||
Type 'startx' to start the Raspbian desktop.
|
||||
|
||||
Type 'lynx' or 'links' to browse the web and 'cftp' to log into FTP sites.
|
||||
Type 'a2chat' or 'a2news' to talk about Apple II stuff with others.
|
||||
Type 'ttytter' to tweet. Type 'term color' for a color terminal on a IIgs.
|
||||
|
||||
Type 'gsport' or 'kegs' to use the GSport or KEGS Apple IIgs emulators.
|
||||
Type 'linapple' to use the LinApple Apple IIe emulator.
|
@ -1 +0,0 @@
|
||||
motd-rpi.txt
|
@ -1,233 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# raspbian-update
|
||||
# updates Raspbian to latest version, including NOOBS if installed
|
||||
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1 || isRpi=
|
||||
|
||||
if [[ ! $isRpi ]]; then
|
||||
echo "This ain't a Raspberry Pi."
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
|
||||
skipRepoUpdate=
|
||||
autoYes=
|
||||
updateA2Cloud=
|
||||
updateA2Server=
|
||||
while [[ $1 ]]; do
|
||||
if [[ $1 == "-r" ]]; then
|
||||
shift
|
||||
skipRepoUpdate="-r"
|
||||
elif [[ $1 == "-y" ]]; then
|
||||
shift
|
||||
autoYes="-y"
|
||||
elif [[ $1 == "-n" ]]; then
|
||||
shift
|
||||
noobsOnly="-n"
|
||||
elif [[ $1 == "a2cloud" ]]; then
|
||||
shift
|
||||
updateA2Cloud=1
|
||||
elif [[ $1 == "a2server" ]]; then
|
||||
shift
|
||||
updateA2Server=1
|
||||
elif [[ $1 ]]; then
|
||||
echo "options:"
|
||||
echo "-y: auto-answer yes to all prompts and don't prompt for restart"
|
||||
echo "-r: don't update package repositories"
|
||||
echo "-n: update NOOBS only; don't update Raspbian"
|
||||
echo "a2cloud : update A2CLOUD when complete"
|
||||
echo "a2server: update A2SERVER when complete"
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
noobs=
|
||||
readarray -t partitions < <(sudo fdisk -l | grep '^/dev')
|
||||
if [[ \
|
||||
${partitions[0]:0:14} == "/dev/mmcblk0p1" && ${partitions[0]:57:2} == " e" &&
|
||||
${partitions[1]:0:14} == "/dev/mmcblk0p2" && ${partitions[1]:57:2} == "85" &&
|
||||
${partitions[2]:0:14} == "/dev/mmcblk0p3" && ${partitions[2]:57:2} == "83" &&
|
||||
${partitions[3]:0:14} == "/dev/mmcblk0p5" && ${partitions[3]:57:2} == " c" &&
|
||||
${partitions[4]:0:14} == "/dev/mmcblk0p6" && ${partitions[4]:57:2} == "83" ]]; then
|
||||
noobs=" and the NOOBS install manager"
|
||||
fi
|
||||
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo
|
||||
echo "You are about to update your SD card to the latest version of the"
|
||||
echo "Raspbian operating system${noobs}."
|
||||
echo
|
||||
echo "This may take an hour or more, and will require restarting when complete."
|
||||
echo "You might want a backup before continuing in case it doesn't go as planned."
|
||||
echo
|
||||
echo -n "Update Raspbian? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
origDir="$PWD"
|
||||
cd /tmp
|
||||
|
||||
if [[ ! $skipRepoUpdate ]]; then
|
||||
echo "Updating package repositories..."
|
||||
sudo apt-get -y update > /dev/null
|
||||
else
|
||||
echo "Not updating package repositories..."
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ ! $noobsOnly ]]; then
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
freeSpace=$(df / | tail -1 | awk '{ print $4 }')
|
||||
if (( $freeSpace < 400000 )); then
|
||||
if dpkg -l | grep -q wolfram-engine; then
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo "In order to create enough space on your SD card to upgrade,"
|
||||
echo "the Wolfram Language and Mathematica software packages must be removed."
|
||||
echo "If you don't know what these are, this won't affect you at all."
|
||||
echo
|
||||
echo -n "Remove Wolfram software? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||
fi
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
else
|
||||
echo "Removing Wolfram software due to space constraints..."
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
fi
|
||||
else
|
||||
echo "You don't have enough free space on your SD card to upgrade."
|
||||
echo "Sorry, man. Delete some stuff or get a bigger card."
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
dpkg -l | grep -q a2pi && sudo apt-get -y --force-yes install a2pi
|
||||
dpkg -l | grep -q apple2user && sudo apt-get -y --force-yes install apple2user gsport
|
||||
if dpkg -l | grep -q wolfram-engine; then
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
if [[ $freeSpace -lt 750000 && $(apt-get -s install wolfram-engine | grep upgraded) ]]; then
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
sudo apt-get -y install wolfram-engine
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
sudo apt-get -y install raspberrypi-ui-mods
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
|
||||
if [[ $noobs ]]; then
|
||||
echo "Updating NOOBS..."
|
||||
|
||||
# update Partition 3
|
||||
mkdir -p /tmp/p3
|
||||
sudo mount /dev/mmcblk0p3 /tmp/p3
|
||||
sudo rm -rf /tmp/p3/os/* 2> /dev/null
|
||||
if grep -q 'Raspple II' /tmp/p3/installed_os.json; then
|
||||
echo "Downloading Raspple II lite..."
|
||||
noobsUrl="ivanx.com/rasppleii/files/RasppleII_lite.zip"
|
||||
noobsOSurl="ivanx.com/rasppleii/noobs-os"
|
||||
distDir="Raspple_II"
|
||||
sudo mkdir -p /tmp/p3/os/$distDir
|
||||
sudo sed -i 's:/Raspbian:/Raspple_II:' /tmp/p3/installed_os.json
|
||||
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspple_II.png
|
||||
wget -qO- $noobsOSurl/slidesAB.tar | sudo tar -C /tmp/p3/os/$distDir -x
|
||||
else
|
||||
echo "Downloading NOOBS lite..."
|
||||
noobsRoot="downloads.raspberrypi.org/NOOBS_lite/images/"
|
||||
noobsDir=$(wget -qO- $noobsRoot | grep '^<tr><td' | tail -1 | grep -P -o 'href=".*?"' | cut -c 6- | tr -d '"')
|
||||
noobsUrl=$noobsRoot$noobsDir$(wget -qO- $noobsRoot$noobsDir | grep -P -o 'href=".*.zip"' | cut -c 6- | tr -d '"')
|
||||
noobsOSurl="downloads.raspberrypi.org/raspbian"
|
||||
distDir="Raspbian"
|
||||
sudo mkdir -p /tmp/p3/os/$distDir
|
||||
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspbian.png
|
||||
wget -qO- $noobsOSurl/marketing.tar | sudo tar -C /tmp/p3/os/$distDir -x
|
||||
fi
|
||||
sudo rm -rf /tmp/p3/cache 2> /dev/null
|
||||
releaseDate=$(wget -qO- $noobsOSurl/os.json | grep 'release_date' | cut -f 4 -d '"')
|
||||
sudo sed -i 's/"release_date".*$/"release_date" : "'$releaseDate'"/' /tmp/p3/installed_os.json
|
||||
sudo sed -i 's/keyboard_layout=gb/keyboard_layout=us/' /tmp/p3/noobs.conf
|
||||
sudo sed -i 's:/mnt/:/settings/:' /tmp/p3/installed_os.json
|
||||
sudo sed -i 's@"icon".*,@"icon" : "/settings/os/'$distDir'/icon.png",@' /tmp/p3/installed_os.json
|
||||
sudo cp /tmp/p3/icon.png /tmp/p3/os/$distDir
|
||||
sudo wget -qO /tmp/p3/os/$distDir/os.json $noobsOSurl/os.json
|
||||
sudo wget -qO /tmp/p3/os/$distDir/partition_setup.sh $noobsOSurl/partition_setup.sh
|
||||
sudo wget -qO /tmp/p3/os/$distDir/partitions.json $noobsOSurl/partitions.json
|
||||
sudo umount /tmp/p3
|
||||
rmdir /tmp/p3
|
||||
|
||||
# update Partition 1
|
||||
mkdir -p /tmp/p1
|
||||
sudo mount /dev/mmcblk0p1 /tmp/p1
|
||||
wget -qO /tmp/noobs_lite.zip $noobsUrl
|
||||
sudo rm -rf /tmp/p1/*
|
||||
sudo unzip -d /tmp/p1 /tmp/noobs_lite.zip
|
||||
sudo sed -i 's/^runinstaller //' /tmp/p1/recovery.cmdline
|
||||
sudo sed -i 's/silentinstall//' /tmp/p1/recovery.cmdline
|
||||
grep -q 'keyboard=us' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 keyboard=us/' /tmp/p1/recovery.cmdline
|
||||
grep -q 'disablesafemode' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 disablesafemode/' /tmp/p1/recovery.cmdline
|
||||
sudo umount /tmp/p1
|
||||
rmdir /tmp/p1
|
||||
|
||||
sudo sed -i 's/\(Raspple II release.*[^u]$\)/\1u/' /etc/issue
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "*** Raspbian update completed. ***"
|
||||
echo
|
||||
|
||||
cd /tmp
|
||||
|
||||
if [[ $updateA2Cloud ]]; then
|
||||
wget -qO /tmp/a2cloud-setup ivanx.com/a2cloud/setup/
|
||||
source /tmp/a2cloud-setup -y -r noSetGroups
|
||||
if acmd -g /usr/share/gsport/disks/GSport\ Internet\ Starter\ Kit.2mg SYSTEM/FONTS/SIS.4.10 &> /dev/null; then
|
||||
wget -qO /tmp/ua2.txt ivanx.com/rasppleii/files/a/ua2.txt
|
||||
source /tmp/ua2.txt
|
||||
fi
|
||||
echo
|
||||
echo "*** A2CLOUD update completed. ***"
|
||||
echo
|
||||
fi
|
||||
|
||||
cd /tmp
|
||||
|
||||
if [[ $updateA2Server ]]; then
|
||||
wget -q -O /tmp/a2server-setup ivanx.com/a2server/setup/
|
||||
if ps aux | grep -q [s]mbd; then
|
||||
source /tmp/a2server-setup -y -r -w
|
||||
else
|
||||
source /tmp/a2server-setup -y -r
|
||||
fi
|
||||
echo
|
||||
echo "*** A2SERVER update completed. ***"
|
||||
echo
|
||||
fi
|
||||
|
||||
cd "$origDir"
|
||||
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo
|
||||
echo
|
||||
echo "Your system has been updated and needs to reboot to use its new software."
|
||||
echo
|
||||
echo -n "Reboot now (recommended)? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
sudo shutdown -r now
|
||||
fi
|
||||
else
|
||||
echo "*** raspbian-update completed. ***"
|
||||
sudo shutdown -r now
|
||||
fi
|
@ -1 +0,0 @@
|
||||
v1.8.2.txt
|
@ -1,24 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
origDir="$PWD"
|
||||
[[ ! -n $1 || ! -n $2 ]] && { echo "Usage: shk2image archiveFileName imageFileName [PRODOS.DIR.NAME]"; exit 1; };
|
||||
imageFileName="$2";
|
||||
prodosDir="$3";
|
||||
[[ ! -f "$1" ]] && { echo "Archive file '$1' was not found."; exit 1; };
|
||||
[[ ! -f "$imageFileName" ]] && mkpo "$imageFileName";
|
||||
[[ -n $prodosDir ]] && dirName="$prodosDir/" || dirName=;
|
||||
IFS="";
|
||||
[[ ${1:0:1} == "/" ]] && archiveFile="$1" || archiveFile="$origDir/$1"
|
||||
mkdir -p /tmp/shk2image_temp
|
||||
cd /tmp/shk2image_temp
|
||||
shkFiles=$(nulib2 -xse "$archiveFile" | tr "\r" "~" | cut -d "~" -f 2 | cut -c 18-);
|
||||
cd "$origDir"
|
||||
while read thisFile; do
|
||||
fileName=${thisFile%%#*};
|
||||
fileType=${thisFile##*#};
|
||||
echo "extracting $fileName...";
|
||||
acmd -d "$imageFileName" $dirName$fileName &>/dev/null;
|
||||
acmd -p "$imageFileName" $dirName$fileName \$${fileType:0:2} \$${fileType:2:4} < /tmp/shk2image_temp/"$thisFile"
|
||||
rm /tmp/shk2image_temp/"$thisFile"
|
||||
done <<< $shkFiles
|
||||
rm -r /tmp/shk2image_temp
|
@ -1,46 +0,0 @@
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
force=1
|
||||
else
|
||||
force=
|
||||
fi
|
||||
|
||||
if [[ ! $1 || $1 == "--help" || $1 == "-h" ]]; then
|
||||
echo 'Usage: term [-d] mono|color|none|<terminalName>';
|
||||
echo ' -d sets default emulation for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
echo ' -f forces change even if not running on serial port (e.g. within "screen")'
|
||||
echo ' Terminal emulation: mono->VT-100, color->PC-ANSI/ANSI-BBS, none->no emulation'
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< $1) == "mono" ]]; then
|
||||
term="vt100"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "color" ]]; then
|
||||
term="pcansi"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "none" ]]; then
|
||||
term="dumb"
|
||||
else
|
||||
term="$1"
|
||||
fi
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/\(ttyAMA0 .*\) .*$/\1 $term/" /etc/inittab;
|
||||
sudo sed -i "s/\(ttyUSB.* .*\) .*$/\1 $term/g" /etc/inittab;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $force || $(tty | grep tty) ]]; then
|
||||
TERM="$term"
|
||||
else
|
||||
echo 1>&2 "Not running on serial port. No action taken. Use -f to set anyway."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tty) current emulation: $(tput bold)$TERM$(tput sgr0)"
|
||||
echo -e "default serial port emulation at login: $(tput bold)$(grep ttyUSB /etc/inittab | sed 's/^.*ttyUSB[^ ]* .* \(.*\)$/\1/')$(tput sgr0)"
|
@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# called by udev as:
|
||||
# ttyusbhandler [add|remove] ttyUSBname
|
||||
|
||||
# depending on what port ttyUSB adapter was added or removed from,
|
||||
# automatically launches or kills ADTPro as needed
|
||||
# restarts getty as needed
|
||||
|
||||
# remove:
|
||||
# kill any ADTPro for this port
|
||||
# if a getty is on this port, do nothing here, it will be killed and respawn
|
||||
# iteself
|
||||
|
||||
# add:
|
||||
# stagger adds by port number to prevent problems during simultaneous add at startup
|
||||
# if lower port, solo adapter on lower port USB hub, or lower port of any USB hub,
|
||||
# kill any ADTPro, rescan for getty if sleeping, and launch adtPro
|
||||
# if upper port, solo adapter on upper port USB hub, or higher port of any USB hub,
|
||||
# rescan for getty
|
||||
|
||||
if [[ $1 == "remove" ]]; then
|
||||
rm /tmp/udev-$2-removed &> /dev/null
|
||||
touch /tmp/udev-$2-removed
|
||||
pkill -f "$2.*ADTPro"
|
||||
elif [[ $1 == "add" ]]; then
|
||||
[[ $2 == "ttyUSBlower" ]] && sleep 1.5
|
||||
[[ ${#2} -gt 11 ]] && sleep "${2:15:2}"
|
||||
if [[ $2 == "ttyUSBlower" || \
|
||||
$2 == $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-) || \
|
||||
( ${2:0:12} == "ttyUSBlower_" && $2 != $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-) ) \
|
||||
]]; then
|
||||
rm /tmp/udev-ttyUSBlower-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBlower-added
|
||||
pkill -f "[A]DTPro"
|
||||
pkill -f "[u]sbgetty"
|
||||
exec /usr/local/adtpro/adtpro.sh headless serial
|
||||
else # ttyUSBupper
|
||||
rm /tmp/udev-ttyUSBupper-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBupper-added
|
||||
pkill -f "[g]etty.*ttyUSB"
|
||||
fi
|
||||
else
|
||||
exit 2
|
||||
fi
|
@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
ttyUSB=
|
||||
|
||||
pkill -f "sleep 86399"
|
||||
|
||||
if [[ $(grep -e '-scanttyUSB' <<< "$*") ]]; then
|
||||
# called with -scantty isntead of device name?
|
||||
# echo "-scantty mode"
|
||||
|
||||
# if upper USB port
|
||||
if [[ -c /dev/ttyUSBupper ]]; then
|
||||
ttyUSB=ttyUSBupper
|
||||
|
||||
# if hub in upper port, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
|
||||
# if hub in lower port with multiple adapters, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
|
||||
# no port found eligible for getty
|
||||
else
|
||||
# echo "scantty no devices eligible: sleeping"
|
||||
sleep 86399
|
||||
fi
|
||||
|
||||
# echo "result:$ttyUSB"
|
||||
elif [[ $(grep -o 'ttyUSB[^ ]*' <<< "$*") ]]; then
|
||||
# echo "device specified"
|
||||
# if specified USB device name is found
|
||||
ttyUSB=$(grep -o 'ttyUSB[^ ]*' <<< "$*")
|
||||
else
|
||||
# echo "specified device failed: sleeping"
|
||||
sleep 86399
|
||||
fi
|
||||
|
||||
if [[ -c /dev/$ttyUSB && ! $(ps aux | grep "[g]etty.*$ttyUSB") ]]; then
|
||||
# if adapter seems to exist and doesn't already have a getty,
|
||||
# kill all USB gettys and start the getty, otherwise do nothing
|
||||
pkill -f "/sbin/getty.*ttyUSB"
|
||||
exec /sbin/getty $(sed "s/-scanttyUSB/$ttyUSB/" <<< "$@");
|
||||
else
|
||||
# echo "getty already running or doesn't exist: sleeping"
|
||||
sleep 86399
|
||||
fi
|
File diff suppressed because it is too large
Load Diff
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
skipWarning=
|
||||
drive=
|
||||
if [[ $1 == "-1" || $1 == "-d1" ]]; then
|
||||
shift
|
||||
elif [[ $1 = "-2" || $1 == "-d2" ]]; then
|
||||
drive=2
|
||||
shift
|
||||
fi
|
||||
if [[ ! $1 ]]; then
|
||||
echo "virtual drive $(( drive ? 2 : 1 )): $(readlink /usr/local/adtpro/disks/Virtual${drive}.po)"
|
||||
else
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
skipWarning=1
|
||||
fi
|
||||
if [[ ! -f $1 ]]; then
|
||||
echo "Image file '$1' was not found."
|
||||
elif [[ -f /usr/local/adtpro/disks/Virtual${drive}.po && ! -L /usr/local/adtpro/disks/Virtual${drive}.po ]]; then
|
||||
echo "/usr/local/adtpro/disks/Virtual${drive}.po is an actual disk image"
|
||||
echo "file, not a symbolic link. Please move or rename it, and try again."
|
||||
else
|
||||
rm /usr/local/adtpro/disks/Virtual${drive}.po &>/dev/null;
|
||||
[[ ${1:0:1} != "/" ]] && pwd="$PWD/";
|
||||
ln -s "$pwd$1" /usr/local/adtpro/disks/Virtual${drive}.po
|
||||
[[ $drive ]] && VSD2="$pwd$1" || VSD1="$pwd$1"
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
if [[ ! $skipWarning ]]; then
|
||||
echo "Please make sure you're not writing to either virtual drive on your Apple II."
|
||||
echo -n " Press return when ready, or control-C to cancel..."
|
||||
read
|
||||
fi
|
||||
sudo pkill -f [A]DTPro
|
||||
while [[ $(ps aux | grep [A]DTPro) ]]; do sleep 1; done
|
||||
/usr/local/bin/adtpro-start
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
unset drive
|
||||
unset pwd
|
84
install.sh
Executable file
84
install.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# install.sh - a2cloud main installation script
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
a2cloudVersion="2.9.0" # Leave this quoted!
|
||||
|
||||
if test "x$BASH" = "x"; then
|
||||
printf "This script requires bash. Please run\nit as ./install.sh from the source\ndirectory.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find the path of our source directory
|
||||
top_src="$( dirname "${BASH_SOURCE[0]}" )"
|
||||
pushd $top_src >/dev/null
|
||||
top_src="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$top_src/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $top_src.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
noPicoPkg=
|
||||
autoAnswerYes=
|
||||
|
||||
process_args() {
|
||||
while [[ $1 ]]; do
|
||||
if [[ $1 == "-c" ]]; then
|
||||
shift
|
||||
noPicoPkg="-c"
|
||||
elif [[ $1 == "-y" ]]; then
|
||||
shift
|
||||
autoAnswerYes="-y"
|
||||
else
|
||||
shift
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
process_args "$@"
|
||||
|
||||
# FIXME: Show version, changes, config, allow reconfig, etc…
|
||||
"$top_src/scripts/show_changes"
|
||||
cat <<EOF
|
||||
|
||||
Your system will be set up for a2cloud, providing you with
|
||||
mass storage and online access for your Apple II!
|
||||
|
||||
If a2cloud is already installed, it will be upgraded to the
|
||||
latest version. It would sure be handy if we had an up to
|
||||
date website to send you to for details. You should harass
|
||||
iKarith about that if you haven't recently.
|
||||
|
||||
A full installation could take quite awhile on very low-end
|
||||
systems like the Raspberry Pi Zero.
|
||||
|
||||
Also, some actions will need to be performed as the root
|
||||
(administrator) user. We are assuming you have access to the
|
||||
sudo command for that.
|
||||
EOF
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
printf "\nContinue? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fix any mistakes we've made in previous versions
|
||||
. "$top_src/scripts/fixup"
|
||||
|
||||
# Install Archive Tools
|
||||
# FIXME: Interim refactoring
|
||||
. "$top_src/scripts/install_archive_tools" $noPicoPkg
|
||||
|
||||
# Run the legacy setup script for anything not yet ported
|
||||
if [[ -e "${top_src}/setup/ivan.sh" ]]; then
|
||||
"${top_src}/setup/ivan.sh" "$@"
|
||||
fi
|
39
scripts/fixup
Executable file
39
scripts/fixup
Executable file
@ -0,0 +1,39 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# fixup - correct any mistakes from previous versions
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# The idea behind this script is to prevent other scripts from becoming a
|
||||
# minefield of ancient and deprecated code designed to compensate for other
|
||||
# even more ancient and replaced code that is no longer needed, no longer
|
||||
# useful, and honestly complicates maintenance of that code. Everything here
|
||||
# will explain what it does, when it was put here, and it should remain clear
|
||||
# when the legacy code may be removed.
|
||||
#
|
||||
# The use of functions which get immediately called is to try and prevent the
|
||||
# long spidery conditional blocks a2cloud was originally known for.
|
||||
|
||||
# # Added 2000-00-00
|
||||
# fix_some_stupid_mistake()
|
||||
# {
|
||||
# # Needed until: Upgrades from 0.0.0 no longer supported
|
||||
# :
|
||||
# }
|
||||
# fix_some_stupid_mistake
|
||||
|
||||
# Added 2018-08-09
|
||||
fix_nulib2_version_file_location()
|
||||
{
|
||||
# Needed while: Unreleased 1f8afb6 (2018-08-05) is in use by testers
|
||||
local ras2_pkginfo="/usr/local/lib/raspple2/pkginfo"
|
||||
if [[ -f /usr/local/lib/raspple2/nulib2-version ]]; then
|
||||
sudo install -d -m 755 -o root -g root "$ras2_pkginfo"
|
||||
sudo mv /usr/local/lib/raspple2/nulib2-version "$ras2_pkginfo"
|
||||
fi
|
||||
}
|
||||
fix_nulib2_version_file_location
|
137
scripts/install_archive_tools
Executable file
137
scripts/install_archive_tools
Executable file
@ -0,0 +1,137 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# install_archive_tools - temporary script for archive tools from ivan.sh
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
nulib2Version="3.1.0"
|
||||
|
||||
a2cBinaryURL="http://blocksfree.com/downloads"
|
||||
ras2_pkginfo="/usr/local/lib/raspple2/pkginfo"
|
||||
|
||||
# Find the path of our source directory
|
||||
a2cSource="$( dirname "${BASH_SOURCE[0]}" )/.."
|
||||
pushd $a2cSource >/dev/null
|
||||
a2cSource="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$a2cSource/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $a2cSource.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure ras2_{os,arch} get set
|
||||
. "$a2cSource/scripts/system_ident" -q
|
||||
|
||||
install_nulib2() {
|
||||
nulib2installed=
|
||||
if [[ -f ${ras2_pkginfo}/nulib2-version ]]; then
|
||||
read nulib2Installed < ${ras2_pkginfo}/nulib2-version
|
||||
fi
|
||||
|
||||
if [[ $nulib2Installed != $nulib2Version ]]; then
|
||||
printf "a2cloud: Installing nulib2 %s...\n" "${nulib2Version}"
|
||||
|
||||
local nulibWork="$(mktemp -d /tmp/nulib.XXXXXXXXXXXX)"
|
||||
pushd "$nulibWork" >/dev/null
|
||||
|
||||
if [[ ! $noPicoPkg ]]; then
|
||||
### ArchiveTools: Install nulib2 binaries
|
||||
wget -q "${a2cBinaryURL}/picopkg/nulib2-${nulib2Version}_${ras2_os}_${ras2_arch}.tgz"
|
||||
if [[ -f "nulib2-${nulib2Version}_${ras2_os}_${ras2_arch}.tgz" ]]; then
|
||||
sudo tar Pzxf "nulib2-${nulib2Version}_${ras2_os}_${ras2_arch}.tgz"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -f ${ras2_pkginfo}/nulib2-version ]]; then
|
||||
read nulib2Installed < ${ras2_pkginfo}/nulib2-version
|
||||
fi
|
||||
if [[ $nulib2Installed != $nulib2Version ]]; then
|
||||
|
||||
### ArchiveTools: Install nulib2 from source
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y install zlib1g-dev
|
||||
sudo apt-get -y clean
|
||||
|
||||
# install nulib2
|
||||
wget -O nulib-${nulib2Version}.tar.gz "https://github.com/fadden/nulib2/archive/v${nulib2Version}.tar.gz"
|
||||
tar zxf nulib-${nulib2Version}.tar.gz
|
||||
cd nulib2-${nulib2Version}/nufxlib
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ../nulib2
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
sudo install -d -m 755 -o root -g root "${ras2_pkginfo}"
|
||||
echo ${nulib2Version} | sudo tee "${ras2_pkginfo}/nulib2-version" >/dev/null
|
||||
fi
|
||||
popd >/dev/null
|
||||
rm -rf "$nulibWork"
|
||||
else
|
||||
printf "a2cloud: nulib2 %s already installed.\n" "${nulib2Version}"
|
||||
fi
|
||||
}
|
||||
|
||||
install_sciibin() {
|
||||
if ! hash sciibin 2> /dev/null; then
|
||||
### ArchiveTools: Install undoit (sciibin, etc.)
|
||||
echo "A2CLOUD: Installing sciibin, unblu, unbit, unexec, usq..."
|
||||
|
||||
sudo apt-get -y install build-essential unzip
|
||||
sudo apt-get -y clean
|
||||
local undoitWork="$(mktemp -d /tmp/undoit.XXXXXXXXXXXX)"
|
||||
pushd "$undoitWork" >/dev/null
|
||||
wget -q http://web.archive.org/web/20110619163030/http://fadden.com/dl-apple2/undoit.zip
|
||||
unzip undoit.zip
|
||||
make
|
||||
sudo mv sciibin unbit unblu unexec usq /usr/local/bin
|
||||
popd >/dev/null
|
||||
rm -rf "$undoitWork"
|
||||
else
|
||||
echo "A2CLOUD: sciibin, unblu, unbit, unexec, usq are already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_shk2image() {
|
||||
echo "A2CLOUD: Setting up shk2image command..."
|
||||
### ArchiveTools: Install shk2image command
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/shk2image" /usr/local/bin/shk2image
|
||||
}
|
||||
|
||||
install_unar() {
|
||||
# Remove locally installed unar if found
|
||||
if [[ -f /usr/local/bin/unar ]]; then
|
||||
echo "Removing local unar in favor of the system package"
|
||||
sudo rm -f /usr/local/bin/lsar
|
||||
sudo rm -f /usr/local/bin/unar
|
||||
sudo rm -f /usr/local/man/man1/lsar.1
|
||||
sudo rm -f /usr/local/man/man1/unar.1
|
||||
fi
|
||||
|
||||
# http://wakaba.c3.cx/s/apps/unarchiver.html
|
||||
if ! hash unar 2> /dev/null; then
|
||||
echo "a2cloud: Installing unar (The Unarchiver)..."
|
||||
sudo apt-get -y install unar
|
||||
sudo apt-get clean
|
||||
else
|
||||
echo "a2cloud: unar has already been installed."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
noPicoPkg=
|
||||
while [[ $1 ]]; do
|
||||
if [[ $1 == -c ]]; then
|
||||
noPicoPkg=1
|
||||
fi
|
||||
shift
|
||||
done
|
||||
install_nulib2
|
||||
install_sciibin
|
||||
install_shk2image
|
||||
install_unar
|
275
scripts/install_comm_tools
Executable file
275
scripts/install_comm_tools
Executable file
@ -0,0 +1,275 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# install_comm_tools - temporary script for comm tools from ivan.sh
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# Find the path of our source directory
|
||||
a2cSource="$( dirname "${BASH_SOURCE[0]}" )/.."
|
||||
pushd $a2cSource >/dev/null
|
||||
a2cSource="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$a2cSource/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $a2cSource.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure ras2_{os,arch} get set
|
||||
. "$a2cSource/scripts/system_ident" -q
|
||||
|
||||
install_curl() {
|
||||
if ! hash curl 2> /dev/null; then
|
||||
### CommTools: Install curl
|
||||
echo "A2CLOUD: Installing curl..."
|
||||
sudo apt-get -y install curl
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: curl is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_lrzsz() {
|
||||
if ! hash sz 2> /dev/null; then
|
||||
### CommTools: Install lrzsz
|
||||
echo "A2CLOUD: Installing rzsz for X/Y/Zmodem transfers..."
|
||||
sudo apt-get -y install lrzsz
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: rzsz is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_ftp() {
|
||||
if ! hash ftp 2> /dev/null; then
|
||||
### CommTools: Install ftp
|
||||
echo "A2CLOUD: Installing ftp..."
|
||||
sudo apt-get -y install ftp
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: ftp is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_lftp() {
|
||||
if ! hash lftp 2> /dev/null; then
|
||||
echo "a2cloud: Installing lftp..."
|
||||
sudo apt-get -y install lftp
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "a2cloud: lftp is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_mc() {
|
||||
if ! hash mc 2> /dev/null; then
|
||||
echo "a2cloud: Installing mc..."
|
||||
sudo apt-get -y install mc
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "a2cloud: mc is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_lynx() {
|
||||
if ! hash lynx 2> /dev/null; then
|
||||
### CommTools: Install lynx
|
||||
echo "A2CLOUD: Installing lynx..."
|
||||
sudo apt-get -y install lynx
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: lynx is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_links() {
|
||||
if ! hash links 2> /dev/null; then
|
||||
### CommTools: Install links
|
||||
echo "A2CLOUD: Installing links..."
|
||||
sudo apt-get -y --force-yes install links
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: links is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_a2news() {
|
||||
### CommTools: Install tin + a2news script
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/a2news" /usr/local/bin/a2news
|
||||
if ! hash tin 2> /dev/null; then
|
||||
echo "A2CLOUD: Installing tin..."
|
||||
sudo apt-get -y install tin
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: tin is already installed."
|
||||
fi
|
||||
|
||||
# Leaving this here just in case, but it should not be necessary anymore.
|
||||
|
||||
# ### CommTools: Configure exim4 to use ipv4 to kill console errors
|
||||
# # have exim4 use IPv4 only to prevent log errors (IPv6 is off by default in Raspbian)
|
||||
# if [[ $(grep ' ; ::1' /etc/exim4/update-exim4.conf.conf) ]]; then
|
||||
# echo "A2CLOUD: Setting exim4 to use only IPv4 to prevent startup error messages..."
|
||||
# sudo sed -i 's/ ; ::1//' /etc/exim4/update-exim4.conf.conf
|
||||
# sudo update-exim4.conf
|
||||
# sudo rm /var/log/exim4/mainlog /var/log/exim4/paniclog &> /dev/null
|
||||
# fi
|
||||
|
||||
# restore exim4 log directory if occupied by a file put there by earlier A2CLOUD versions
|
||||
if [[ -f /var/log/exim4 ]]; then
|
||||
echo "A2CLOUD: Restoring exim4 log directory..."
|
||||
sudo rm /var/log/exim4
|
||||
sudo mkdir /var/log/exim4
|
||||
sudo chown Debian-exim:adm /var/log/exim4
|
||||
sudo chmod 2750 /var/log/exim4
|
||||
fi
|
||||
}
|
||||
|
||||
install_a2chat() {
|
||||
### CommTools: Install irssi + a2chat script
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/a2chat" /usr/local/bin/a2chat
|
||||
if ! hash irssi 2> /dev/null; then
|
||||
echo "A2CLOUD: Installing a2chat/irssi..."
|
||||
sudo apt-get -y install irssi
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: a2chat/irssi is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_telnet() {
|
||||
### CommTools: Install telnet
|
||||
if ! hash telnet 2> /dev/null; then
|
||||
echo "A2CLOUD: Installing telnet..."
|
||||
sudo apt-get -y install telnet
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
echo "A2CLOUD: telnet is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_oysttyer() {
|
||||
rm_file() {
|
||||
if [[ -f $1 ]]; then
|
||||
echo "Removing $1"
|
||||
sudo rm -f "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
try_rmdir() {
|
||||
if [[ -d $1 ]]; then
|
||||
if sudo rmdir $1 &>/dev/null; then
|
||||
echo "Removing directory $1"
|
||||
else
|
||||
echo "Cannot remove $1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
### CommTools: Install Oysttyer (formerly TTYtter)
|
||||
|
||||
# Do we need to check for the readline module here as well?
|
||||
local perlVersion=$(perl -e 'print $^V' | cut -c 2-)
|
||||
|
||||
local oysttyerWork="$(mktemp -d /tmp/oysttyer.XXXXXXXXXXXX)"
|
||||
pushd "$oysttyerWork" >/dev/null
|
||||
|
||||
# Remove old ttytter
|
||||
# Previous versions of a2cloud symlinked ttytter to oysttyer. I don't think
|
||||
# we want to do that, because Debian won't in buster when we start using
|
||||
# their oysttyer package.
|
||||
if [[ -f /usr/local/bin/ttytter || -f /usr/local/share/perl/${perlVersion}/Term/ReadLine/TTYtter.pm ]]; then
|
||||
echo "Removing ttytter in favor of oysttyer..."
|
||||
sudo rm -f /usr/local/bin/ttytter
|
||||
fi
|
||||
|
||||
# Now install the Debian's package
|
||||
echo "Installing Debian's Term::ReadKey (libterm-readline-gnu-perl)..."
|
||||
sudo apt-get -y install libterm-readline-gnu-perl
|
||||
|
||||
# Remove locally installed Term::ReadKey (libterm-readline-gnu-perl
|
||||
if [[ -f /usr/local/man/man3/Term::ReadKey.3pm ]]; then
|
||||
cat <<-EOF
|
||||
You have a locally installed Term::ReadKey from an older version of a2cloud.
|
||||
|
||||
We will try to remove it, but locally installed perl modules are rather
|
||||
difficult to completely remove. What we cannot remove will not interfere
|
||||
with a running system, but if you like a tidy system, you'll need to clean
|
||||
up a few perl files yourself.
|
||||
|
||||
EOF
|
||||
rm_file "/usr/local/man/man3/Term::ReadKey.3pm"
|
||||
|
||||
# Deleting perl modules properly is hard, next to impossible, and this
|
||||
# could be in man places. We'll do what we can.
|
||||
for ver in 5.14.2 5.20.2 $perlVersion; do
|
||||
for perlDir in perl arm-linux-gnueabihf/perl i686-linux-gnu/perl x86_64-linux-gnu/perl; do
|
||||
if [[ -f /usr/local/lib/$perlDir/$ver/Term/ReadKey.pm ]]; then
|
||||
rm_file "/usr/local/lib/$perlDir/$ver/Term/ReadKey.pm"
|
||||
try_rmdir "/usr/local/lib/$perlDir/$ver/Term"
|
||||
rm_file "/usr/local/lib/$perlDir/$ver/auto/Term/ReadKey/autosplit.ix"
|
||||
rm_file "/usr/local/lib/$perlDir/$ver/auto/Term/ReadKey/ReadKey.so"
|
||||
try_rmdir "/usr/local/lib/$perlDir/$ver/auto/Term/ReadKey"
|
||||
try_rmdir "/usr/local/lib/$perlDir/$ver/auto/Term"
|
||||
echo "Additional cleaning may be needed under:"
|
||||
echo " /usr/local/lib/$perlDir/$ver"
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
# Old TTYtter author still maintains the readline module for oysttyer
|
||||
echo "Installing Term::ReadLine::TTYtter..."
|
||||
if sudo apt-get -y install libterm-readline-ttytter-perl; then
|
||||
# We have a package now, so remove any locally installed version
|
||||
if [[ -f /usr/local/share/perl/$perlVersion/Term/ReadLine/TTYtter.pm ]]; then
|
||||
echo "Removing local Term::ReadLine::TTYtter in favor of the package we installed."
|
||||
sudo rm -f "/usr/local/share/perl/$perlVersion/Term/ReadLine/readline_ttytter.pm"
|
||||
sudo rm -f "/usr/local/share/perl/$perlVersion/Term/ReadLine/TTYtter.pm"
|
||||
fi
|
||||
else
|
||||
# We haven't got a package, install it locally
|
||||
echo "No package. That's all right, we'll install it locally..."
|
||||
|
||||
# We don't need to make anything for this, just copy the files
|
||||
wget -O Term-ReadLine-TTYtter-1.4.tar.gz http://search.cpan.org/CPAN/authors/id/C/CK/CKAISER/Term-ReadLine-TTYtter-1.4.tar.gz
|
||||
tar zxf Term-ReadLine-TTYtter-1.4.tar.gz
|
||||
cd Term-ReadLine-TTYtter-1.4
|
||||
sudo install -m 755 -o root -g root -d /usr/local/share/perl/$perlVersion/Term/ReadLine
|
||||
sudo install -m 644 -o root -g root ReadLine/readline_ttytter.pm ReadLine/TTYtter.pm /usr/local/share/perl/$perlVersion/Term/ReadLine
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Actually install oysttyer now, if needed
|
||||
echo "Installing oysttyer..."
|
||||
if sudo apt-get -y install oysttyer; then
|
||||
if [[ -f /usr/local/bin/oysttyer ]]; then
|
||||
echo "Removing local oysttyer in favor of the package we installed."
|
||||
sudo rm -f /usr/local/bin/oysttyer
|
||||
fi
|
||||
else
|
||||
echo "No package. That's all right, we'll install it locally..."
|
||||
wget -O oysttyer-2.9.1.tar.gz https://github.com/oysttyer/oysttyer/archive/2.9.1.tar.gz
|
||||
tar -zxf oysttyer-2.9.1.tar.gz
|
||||
sudo install -m 755 -o root -g root oysttyer-2.9.1/oysttyer.pl /usr/local/bin/oysttyer
|
||||
fi
|
||||
|
||||
sudo apt-get clean
|
||||
|
||||
popd >/dev/null
|
||||
rm -rf "$oysttyerWork"
|
||||
}
|
||||
|
||||
install_curl
|
||||
install_lrzsz
|
||||
install_ftp
|
||||
install_lftp
|
||||
install_mc
|
||||
install_lynx
|
||||
install_links
|
||||
install_a2news
|
||||
install_a2chat
|
||||
install_telnet
|
||||
install_oysttyer
|
242
scripts/install_emulators
Executable file
242
scripts/install_emulators
Executable file
@ -0,0 +1,242 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# install_emulators - temporary script for emulators from ivan.sh
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
a2cBinaryURL="http://blocksfree.com/downloads"
|
||||
|
||||
# Find the path of our source directory
|
||||
a2cSource="$( dirname "${BASH_SOURCE[0]}" )/.."
|
||||
pushd $a2cSource >/dev/null
|
||||
a2cSource="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$a2cSource/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $a2cSource.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure ras2_{os,arch} get set
|
||||
. "$a2cSource/scripts/system_ident" -q
|
||||
|
||||
install_gsport() {
|
||||
### Emulators: GSport
|
||||
if ! hash gsport 2> /dev/null || ! hash gsportx 2> /dev/null || ! hash gsportfb 2> /dev/null; then
|
||||
# FIXME: This is a _TERRIBLE_ name/place for this...
|
||||
gsportConfigFile='/usr/local/lib/config.txt'
|
||||
|
||||
echo "A2CLOUD: Installing GSport..."
|
||||
|
||||
local gsportWork="$(mktemp -d /tmp/gsport.XXXXXXXXXXXX)"
|
||||
pushd "$gsportWork" >/dev/null
|
||||
if [[ ! $noPicoPkg ]]; then
|
||||
### Emulators: GSport: Install pre-built binaries
|
||||
sudo apt-get -y install libpcap0.8
|
||||
sudo apt-get -y clean
|
||||
wget "${a2cBinaryURL}/picopkg/gsport-${ras2_os}_${ras2_arch}.tgz"
|
||||
if [[ -f gsport-${ras2_os}_${ras2_arch}.tgz ]]; then
|
||||
sudo tar Pzxf gsport-${ras2_os}_${ras2_arch}.tgz
|
||||
fi
|
||||
fi
|
||||
if ! hash gsport 2> /dev/null || ! hash gsportx 2> /dev/null || ! hash gsportfb 2> /dev/null; then
|
||||
### Emulators: GSport: Install from source
|
||||
echo "A2CLOUD: Building GSport from source..."
|
||||
|
||||
sudo apt-get -y install build-essential &> /dev/null
|
||||
sudo apt-get -y install libx11-dev libxext-dev xfonts-base libpcap0.8-dev
|
||||
sudo apt-get -y clean
|
||||
|
||||
wget -O gsport.tar.gz http://downloads.sourceforge.net/project/gsport/GSport-0.31/gsport_0.31.tar.gz
|
||||
tar --strip-components=1 -zxf gsport.tar.gz
|
||||
cd src
|
||||
rm -f vars
|
||||
|
||||
buildGSport=1
|
||||
cp vars_fbrpilinux vars_fb
|
||||
if [[ -n $isRpi ]]; then
|
||||
cp vars_pi vars_x
|
||||
else
|
||||
cp vars_x86linux vars_x
|
||||
case "$ras2_arch" in
|
||||
x86_64)
|
||||
sed -i 's/-march=i686/-march=x86-64/' vars_x
|
||||
sed -i 's/-march=armv6/-march=x86-64/' vars_fb
|
||||
;;
|
||||
i686)
|
||||
sed -i 's/-march=armv6/-march=i686/' vars_fb
|
||||
;;
|
||||
*)
|
||||
buildGSport=
|
||||
echo "A2CLOUD: cannot build GSport; unknown machine architecture."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
sed -i 's/^LDFLAGS =.*$/LDFLAGS = -ldl/' vars_x
|
||||
sed -i 's/^LDFLAGS =.*$/LDFLAGS = -ldl/' vars_fb
|
||||
if [[ -n $buildGSport ]]; then
|
||||
for varsFile in vars_x vars_fb; do
|
||||
rm -f vars
|
||||
cp $varsFile vars
|
||||
make clean
|
||||
make
|
||||
sudo install -o root -g root -m 755 ../gsport${varsFile:5:2} /usr/local/bin
|
||||
done
|
||||
gcc -o ../to_pro to_pro.c &> /dev/null
|
||||
gcc -o ../partls partls.c &> /dev/null
|
||||
sudo install -o root -g root -m 755 ../to_pro /usr/local/bin
|
||||
sudo install -o root -g root -m 755 ../partls /usr/local/bin
|
||||
sudo install -o root -g root -m 666 ../config.txt "$gsportConfigFile"
|
||||
cd "${gsportConfigFile%/*}"
|
||||
sudo ln -s "${gsportConfigFile##*/}" gsport_config.txt 2> /dev/null
|
||||
fi
|
||||
|
||||
cd /tmp/a2cloud-install 2> /dev/null
|
||||
rm -rf gsport 2> /dev/null
|
||||
fi
|
||||
|
||||
if [[ $slot6 ]]; then
|
||||
### Emulators: GSport: Place blank disk images in slot 6
|
||||
echo "A2CLOUD: Putting blank disks in GSport slot 6..."
|
||||
sudo sed -i 's@^s6d1.*$@s6d1 = /usr/local/share/gsdisks/slot6drive1.po@' "$gsportConfigFile"
|
||||
sudo sed -i 's@^s6d2.*$@s6d2 = /usr/local/share/gsdisks/slot6drive2.po@' "$gsportConfigFile"
|
||||
if [[ ! -f /usr/local/share/gsdisks/slot6drive1.po || ! -f /usr/local/share/gsdisks/slot6drive2.po ]]; then
|
||||
wget -qO- "${a2BinaryURL}/gsport/slot6.tgz" | sudo tar Pzx 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! grep -q '^g_appletalk_turbo' "$gsportConfigFile"; then
|
||||
### Emulators: GSport: Enable AppleTalk Turbo support
|
||||
if grep -q 'bram1[00]' "$gsportConfigFile"; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_appletalk_turbo = 1\n\n\1/' "$gsportConfigFile"
|
||||
else
|
||||
echo -e '\ng_appletalk_turbo = 1' | sudo tee -a "$gsportConfigFile" > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/^g_appletalk_turbo = 0/g_appletalk_turbo = 1/' "$gsportConfigFile"
|
||||
|
||||
if ! grep -q 'g_ethernet[^_]' "$gsportConfigFile"; then
|
||||
### Emulators: GSport: Enable Uthernet emulation
|
||||
if grep -q 'bram1[00]' "$gsportConfigFile"; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_ethernet = 1\n\n\1/' "$gsportConfigFile"
|
||||
else
|
||||
echo -e '\ng_ethernet = 1' | sudo tee -a "$gsportConfigFile" > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/g_ethernet = 0/g_ethernet = 1/' "$gsportConfigFile"
|
||||
|
||||
### Emulators: GSport: Setup groups and wrapper scripts
|
||||
echo "A2CLOUD: Updating GSport launch and setup files..."
|
||||
|
||||
sudo addgroup gsport &> /dev/null
|
||||
sudo chgrp gsport /usr/local/bin/gsportfb
|
||||
sudo chmod u+s /usr/local/bin/gsportfb
|
||||
sudo chgrp gsport /usr/local/bin/gsportx
|
||||
sudo chmod u+s /usr/local/bin/gsportx
|
||||
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/gsport" /usr/local/bin/gsport
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/gsport-setup" /usr/local/bin/gsport-setup
|
||||
|
||||
popd >/dev/null
|
||||
rm -rf "$gsportWork"
|
||||
else
|
||||
echo "A2CLOUD: GSport is already installed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_linapple() {
|
||||
### Emulators: LinApple
|
||||
if ! hash linapple 2> /dev/null; then
|
||||
echo "A2CLOUD: Installing LinApple..."
|
||||
local linappleWork="$(mktemp -d /tmp/linapple.XXXXXXXXXXXX)"
|
||||
pushd "$linappleWork" >/dev/null
|
||||
if [[ ! $noPicoPkg ]]; then
|
||||
### Emulators: LinApple: Install pre-built binaries
|
||||
wget "${a2cBinaryURL}/picopkg/linapple-${ras2_os}_${ras2_arch}.tgz"
|
||||
if [[ -f linapple-${ras2_os}_${ras2_arch}.tgz ]]; then
|
||||
sudo tar Pzxf linapple-${ras2_os}_${ras2_arch}.tgz
|
||||
fi
|
||||
fi
|
||||
if ! hash linapple 2> /dev/null; then
|
||||
### Emulators: LinApple: Install from source
|
||||
echo "A2CLOUD: Building LinApple from source..."
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y install libsdl1.2-dev libcurl4-openssl-dev zlib1g-dev libzip-dev
|
||||
sudo apt-get -y clean
|
||||
wget -q -O linapple_src-2b.tar.bz2 http://downloads.sourceforge.net/project/linapple/linapple/linapple_2b/linapple_src-2b.tar.bz2
|
||||
tar jxf linapple_src-2b.tar.bz2
|
||||
cd linapple_src-2b/src
|
||||
make
|
||||
sudo make install
|
||||
fi
|
||||
popd >/dev/null
|
||||
rm -rf "$linappleWork"
|
||||
else
|
||||
echo "A2CLOUD: LinApple is already installed."
|
||||
fi
|
||||
echo "A2CLOUD: Updating LinApple launch file..."
|
||||
sudo install -o root -g root -m 755 "$a2cSource/setup/linapple" /usr/local/bin/linapple
|
||||
}
|
||||
|
||||
install_desktop() {
|
||||
# FIXME: HACK HACK HACK! We're only messing with ~/Desktop in the least
|
||||
# because I'm not 100% sure that if we put things in the menu that you'll
|
||||
# get them. Didn't used to be the case. If that's changed, we should stop.
|
||||
mkdir -p ~/Desktop
|
||||
|
||||
sudo mkdir -p /usr/local/share/applications
|
||||
|
||||
# FIXME: Is there a reason we're running these in a lxterminal with Terminal=false
|
||||
if [[ -f /usr/local/bin/gsport ]]; then
|
||||
sudo tee /usr/local/share/applications/gsport.desktop > ~/Desktop/gsport.desktop <<-EOF
|
||||
[Desktop Entry]
|
||||
Name=GSport
|
||||
Comment=Apple IIgs Emulator
|
||||
Exec=lxterminal -e /usr/local/bin/gsport
|
||||
Icon=/usr/local/share/gsport32.ico
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=AppleII
|
||||
EOF
|
||||
if [[ ! -f /usr/local/share/gsport32.ico ]]; then
|
||||
sudo wget -O /usr/local/share/gsport32.ico https://raw.githubusercontent.com/david-schmidt/gsport/master/src/gsport32.ico
|
||||
fi
|
||||
fi
|
||||
# LinApple:
|
||||
if [[ -f /usr/local/bin/linapple ]]; then
|
||||
sudo tee /usr/local/share/applications/linapple.desktop > ~/Desktop/linapple.desktop <<-EOF
|
||||
[Desktop Entry]
|
||||
Name=LinApple
|
||||
Comment=Apple IIe Emulator
|
||||
Exec=lxterminal -e /usr/local/bin/linapple
|
||||
Icon=/usr/local/linapple/icon.bmp
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=AppleII
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
noPicoPkg=
|
||||
slot6=
|
||||
while [[ $1 ]]; do
|
||||
case $1 in
|
||||
-c)
|
||||
noPicoPkg=1
|
||||
;;
|
||||
-6)
|
||||
slot6=1
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
install_gsport
|
||||
install_linapple
|
||||
install_user_desktop
|
||||
|
||||
### Emulators: Set Groups
|
||||
sudo usermod -a -G audio,video,netdev,gsport,plugdev $USER &> /dev/null
|
70
scripts/install_java
Executable file
70
scripts/install_java
Executable file
@ -0,0 +1,70 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# install_java - make sure we have java installed
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# Find the path of our source directory
|
||||
a2cSource="$( dirname "${BASH_SOURCE[0]}" )/.."
|
||||
pushd $a2cSource >/dev/null
|
||||
a2cSource="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$a2cSource/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $a2cSource.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure ras2_{os,arch} get set
|
||||
. "$a2cSource/scripts/system_ident" -q
|
||||
|
||||
check_freespace() {
|
||||
# we use df -k because its output works on Linux and BSD/Mac
|
||||
freeSpace=$(df -k / | tail -1 | awk '{ print $4 }')
|
||||
(( $freeSpace > 360000 ))
|
||||
return $?
|
||||
}
|
||||
|
||||
install_java() {
|
||||
sudo apt-get update
|
||||
if [[ $ras2_os == rpi-* ]]; then
|
||||
sudo apt-get -y install oracle-java8-jdk
|
||||
else
|
||||
# Used to go out and find Oracle Java, but we don't need it.
|
||||
sudo apt-get -y install default-jre
|
||||
fi
|
||||
sudo apt-get clean
|
||||
}
|
||||
|
||||
if ! hash java 2>/dev/null; then
|
||||
printf "\nJava is not installed"
|
||||
if check_freespace; then
|
||||
printf ", but we can install it.\n"
|
||||
|
||||
install_java
|
||||
else
|
||||
cat <<-EOF
|
||||
amd this script cannot continue.
|
||||
|
||||
You don't seem to have enough free space to install Java, which is
|
||||
needed by several components we install (ADTPro and AppleCommander,
|
||||
for example.) On a Raspberry Pi, it is possible that you may simply
|
||||
need to expand your filesystem to fill the SD card. You can do that
|
||||
by running "sudo raspi-config" and selecting the appropriate option.
|
||||
|
||||
If that's not the cause, you might investigate to see if you happen
|
||||
to have unwanted large packages installed. Some systems come loaded
|
||||
with full desktop environments, development IDEs, or other large
|
||||
packages or package groups you don't need.
|
||||
|
||||
Failing all of that, you can figure out how to get java installed and
|
||||
into your default path and set JAVA_HOME. If we find java in your
|
||||
path this script will assume that we should simply use that. We do
|
||||
recommend Java 8 or above.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
fi
|
32
scripts/show_changes
Executable file
32
scripts/show_changes
Executable file
@ -0,0 +1,32 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# show_changes - show a2cloud version differences
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# Find the path of our source directory
|
||||
a2cSource="$( dirname "${BASH_SOURCE[0]}" )/.."
|
||||
pushd $a2cSource >/dev/null
|
||||
a2cSource="$PWD"
|
||||
popd >/dev/null
|
||||
if [[ ! -f "$a2cSource/.a2cloud_source" ]]; then
|
||||
printf "\na2cloud: cannot find a2cloud source directory in $a2cSource.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
newVersion=$(grep '^a2cloudVersion' "$a2cSource/install.sh" | cut -d '"' -f 2)
|
||||
|
||||
if [[ -f /usr/local/etc/A2CLOUD-version ]]; then
|
||||
read installedVersion </usr/local/etc/A2CLOUD-version
|
||||
if [[ $installedVersion != *.*.* ]]; then
|
||||
installedVersion="${installedVersion:0:1}.${installedVersion:1:1}.${installedVersion:2}"
|
||||
fi
|
||||
fi
|
||||
echo "a2cloud version available: $newVersion"
|
||||
echo "a2cloud version installed: ${installedVersion:-None}"
|
||||
|
||||
# FIXME: Do something useful with a changelog perhaps?
|
44
scripts/system_ident
Executable file
44
scripts/system_ident
Executable file
@ -0,0 +1,44 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# system_ident - identify your system for raspple2 if needed
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
if [[ -z $ras2_os || -z $ras2_arch ]]; then
|
||||
ras2_os="unknown"
|
||||
if hash lsb_release 2>/dev/null; then
|
||||
if [[ -f /usr/bin/raspi-config ]]; then
|
||||
ras2_os="rpi-$(lsb_release -cs)"
|
||||
else
|
||||
case "$(lsb_release -is)" in
|
||||
Debian)
|
||||
ras2_os="debian-$(lsb_release -cs)"
|
||||
;;
|
||||
*)
|
||||
printf "\nUnknown OS with lsb_release\n"
|
||||
lsb_release -a
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
uname_s="$(uname -s)"
|
||||
case "$uname_s" in
|
||||
Darwin)
|
||||
ras2_os="$uname_s"
|
||||
;;
|
||||
*)
|
||||
printf "\nUnknown OS with uname -s\n$uname_s\n"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
ras2_arch="$(uname -m)"
|
||||
export ras2_os ras2_arch
|
||||
fi
|
||||
|
||||
if [[ $1 != -q ]]; then
|
||||
printf "ras2_os=\"%s\"\nras2_arch=\"%s\"\n" "$ras2_os" "$ras2_arch"
|
||||
fi
|
72
setup/a2chat
Executable file
72
setup/a2chat
Executable file
@ -0,0 +1,72 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# a2chat - a2cloud irc client wrapper
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
if [[ ! $(dpkg -l irssi 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing irssi..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install irssi &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-n" && $2 ]]; then
|
||||
nickname=$2
|
||||
elif [[ $1 == "-n" ]]; then
|
||||
nickname="0"
|
||||
elif [[ -f ~/.irssi/a2c.nickname ]]; then
|
||||
nickname=$(cat ~/.irssi/a2c.nickname)
|
||||
else
|
||||
nickname=
|
||||
fi
|
||||
|
||||
while [[ ! $nickname || ! $(grep -i '^[a-z_\-\\^{}|`][a-z0-9_\-\\^{}|`]*$' <<< $nickname) ]]; do
|
||||
echo "Choosing a nickname"
|
||||
echo
|
||||
echo "A nickname on irc is how you are known to other people. It can"
|
||||
echo "consist of letters, numbers, and punctuation symbols such as -, _, and ^."
|
||||
echo "Some older IRC servers will cut your nickname to eight characters, but"
|
||||
echo "more modern ones like A2Central do not."
|
||||
echo
|
||||
echo "Aliases are fine on irc, but really common names like James or Mark or"
|
||||
echo "AppleIIGuy are likely to be used by someone else already. A guy named"
|
||||
echo "Joseph might use some variation of their name (such as JosephC or"
|
||||
echo "tjcarter) or come up with something else entirely."
|
||||
echo
|
||||
echo "You can change your nickname once you're online by typing a command"
|
||||
echo "like \"/nick <newnick>\", and you can rerun this script with the -n"
|
||||
echo "parameter to have this script save your choice for future use."
|
||||
echo
|
||||
echo -n "Enter a nickname (use 'a2chat -n' to change it later): "
|
||||
read
|
||||
nickname=$REPLY
|
||||
done
|
||||
|
||||
mkdir -p ~/.irssi
|
||||
echo $nickname > ~/.irssi/a2c.nickname
|
||||
|
||||
if [[ -f ~/.irssi/startup ]]; then
|
||||
mv ~/.irssi/startup ~/.irssi/startup.orig
|
||||
fi
|
||||
echo -e "/network add -autosendcmd '/join #a2c.chat' Palomino.A2\n/server add -auto -network Palomino.A2 irc.a2central.com\n" > ~/.irssi/startup
|
||||
|
||||
if [[ -f ~/.irssi/config ]]; then
|
||||
cp ~/.irssi/config ~/.irssi/config.orig
|
||||
fi
|
||||
|
||||
irssi -n $nickname
|
||||
|
||||
rm ~/.irssi/startup &> /dev/null
|
||||
if [[ -f ~/.irssi/startup.orig ]]; then
|
||||
mv ~/.irssi/startup.orig ~/.irssi/startup
|
||||
fi
|
||||
|
||||
rm ~/.irssi/config &> /dev/null
|
||||
if [[ -f ~/.irssi/config.orig ]]; then
|
||||
mv ~/.irssi/config.orig ~/.irssi/config
|
||||
fi
|
@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ! $(dpkg -l irssi 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing irssi..."
|
||||
supo apt-get -y update
|
||||
sudo apt-get -y install irssi &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-n" && $2 ]]; then
|
||||
nickname=$2
|
||||
elif [[ $1 == "-n" ]]; then
|
||||
nickname="0"
|
||||
elif [[ -f ~/.irssi/a2c.nickname ]]; then
|
||||
nickname=$(cat ~/.irssi/a2c.nickname)
|
||||
else
|
||||
nickname=
|
||||
fi
|
||||
|
||||
while [[ ! $nickname || ! $(grep -i '^[a-z_\-\\^{}|`][a-z0-9_\-\\^{}|`]*$' <<< $nickname) ]]; do
|
||||
echo -n "Enter a nickname for chat (to change later, use 'a2chat -n'): "
|
||||
read
|
||||
nickname=$REPLY
|
||||
done
|
||||
|
||||
mkdir -p ~/.irssi
|
||||
echo $nickname > ~/.irssi/a2c.nickname
|
||||
|
||||
if [[ -f ~/.irssi/startup ]]; then
|
||||
mv ~/.irssi/startup ~/.irssi/startup.orig
|
||||
fi
|
||||
echo -e "/network add -autosendcmd '/join #a2c.chat' Palomino.A2\n/server add -auto -network Palomino.A2 irc.a2central.com\n" > ~/.irssi/startup
|
||||
|
||||
if [[ -f ~/.irssi/config ]]; then
|
||||
cp ~/.irssi/config ~/.irssi/config.orig
|
||||
fi
|
||||
|
||||
irssi -n $nickname
|
||||
|
||||
rm ~/.irssi/startup &> /dev/null
|
||||
if [[ -f ~/.irssi/startup.orig ]]; then
|
||||
mv ~/.irssi/startup.orig ~/.irssi/startup
|
||||
fi
|
||||
|
||||
rm ~/.irssi/config &> /dev/null
|
||||
if [[ -f ~/.irssi/config.orig ]]; then
|
||||
mv ~/.irssi/config.orig ~/.irssi/config
|
||||
fi
|
24
setup/a2cloud-aliases.txt → setup/a2cloud-aliases
Normal file → Executable file
24
setup/a2cloud-aliases.txt → setup/a2cloud-aliases
Normal file → Executable file
@ -1,4 +1,12 @@
|
||||
# A2CLOUD aliases:
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# a2cloud-alieases - User-installed command aliases for bash
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
alias a2cloud-setup='wget -qO /tmp/a2cloud-setup ivanx.com/a2cloud/setup/; source /tmp/a2cloud-setup'
|
||||
alias a2cloud-help='(IFS=""; while read thisLine; do [[ ${#thisLine} -eq 0 ]] && echo || echo "$(tput bold)${thisLine%% *}$(tput sgr0) ${thisLine#* }"; done < /usr/local/etc/a2cloud-help.txt | more)'
|
||||
@ -8,13 +16,6 @@ alias a2cloud-update='a2cloud-setup'
|
||||
alias system-shutdown='sudo shutdown -h now'
|
||||
alias system-restart='sudo shutdown -r now'
|
||||
|
||||
|
||||
alias raspi-config='[[ -f /usr/bin/raspi-config ]] && sudo /usr/bin/raspi-config || echo "raspi-config not found. Are you using a Raspberry Pi with Raspbian?"'
|
||||
alias appleiipi-update="sudo apt-get -y update && sudo apt-get -y --force-yes install a2pi apple2user gsport"
|
||||
alias raspbian-update='wget -qO /tmp/raspbian-update ivanx.com/a2cloud/setup/raspbian-update.txt; source /tmp/raspbian-update'
|
||||
alias rasppleii-update='raspbian-update a2cloud a2server'
|
||||
|
||||
|
||||
alias welcome-message-edit='sudo nano /etc/motd'
|
||||
|
||||
alias showip='ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1'
|
||||
@ -28,11 +29,6 @@ alias adtpro-stop='sudo pkill -f [A]DTPro'
|
||||
|
||||
alias adtpro-restart='sudo pkill -f [A]DTPro; while [[ $(ps aux | grep [A]DTPro) ]]; do sleep 1; done; adtpro-start'
|
||||
|
||||
alias usblogin-off='sudo sed -i "s/^\(.*-scanttyUSB\)/#\1/" /etc/inittab; sudo init q; sudo pkill -f [g]etty'
|
||||
alias usblogin-on='sudo sed -i "s/^#\(.*-scanttyUSB\)/\1/" /etc/inittab; sudo init q'
|
||||
|
||||
|
||||
|
||||
alias term='source term'
|
||||
|
||||
|
||||
@ -79,7 +75,7 @@ GSHD=/usr/local/share/gsdisks/gsoshd.hdv
|
||||
|
||||
|
||||
|
||||
ttytter () { ( ansi=; seven=; [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]] && { seven="-seven"; [[ $TERM=="ansi" || $TERM=="pcansi" ]] && ansi="-ansi"; }; [[ -f /usr/bin/ttytter ]] && /usr/bin/ttytter -ssl $seven $ansi $@ || /usr/local/bin/ttytter -ssl $seven $ansi $@ ); }
|
||||
oysttyer () { ( ansi=; seven=; [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]] && { seven="-seven"; [[ $TERM=="ansi" || $TERM=="pcansi" ]] && ansi="-ansi"; }; [[ -f /usr/bin/oysttyer ]] && /usr/bin/oysttyer -ssl $seven $ansi $@ || /usr/local/bin/oysttyer -ssl $seven $ansi $@ ); }
|
||||
|
||||
|
||||
alias raspple-update='rasppleii-update'
|
@ -8,31 +8,19 @@ a2cloud-update : update A2CLOUD, or add features
|
||||
system-shutdown : shut down the A2CLOUD machine (or VM)
|
||||
system-restart : shut down and restart the A2CLOUD machine (or VM)
|
||||
|
||||
Raspberry Pi commands, if you're using one:
|
||||
raspi-config : configure Raspberry Pi
|
||||
appleiipi-update : update Apple II Pi and GSport
|
||||
raspbian-update : update Raspbian operating system
|
||||
rasppleii-update : update Raspbian OS, A2CLOUD, A2SERVER, Apple II Pi
|
||||
Apple II Pi: for help, visit http://schmenk.is-a-geek.com/wordpress
|
||||
|
||||
welcome-message-edit : change the welcome message
|
||||
|
||||
showip : show the current ethernet IP address of the server
|
||||
showmac : show the MAC (Ethernet hardware) address of the server
|
||||
showip-wifi : show the current wifi IP address of the server
|
||||
showmac-wifi : show the MAC (wifi hardware) address of the server
|
||||
ifreset : reset all network interfaces (requires restart)
|
||||
ifreset : reset all network interfaces (requires restart)
|
||||
|
||||
adtpro-stop : stop the ADTPro service
|
||||
adtpro-start : start the ADTPro service
|
||||
(note: autostarts on appearance of eligible USB-to-serial adapter)
|
||||
adtpro-restart : restart the ADTPro service
|
||||
|
||||
usblogin-off : disable shell login for USB-to-serial adapter
|
||||
usblogin-on : enable shell login with USB-to-serial adapter on upper
|
||||
USB port or hub attached to it, or highest-numbered port on hub
|
||||
attached to lower USB port
|
||||
|
||||
term [-d] mono : use VT-100 (mostly monochrome) emulation in serial
|
||||
shell login for ProTERM, Spectrum, Z-Link, etc. (-d sets default)
|
||||
term [-d] color : use ANSI color and PC graphic text in serial shell
|
||||
@ -45,7 +33,7 @@ vsd2 : show or set the disk image assigned to virtual drive 2
|
||||
forfloppy : move the disk image to the ADTPro disk images folder
|
||||
(/usr/local/adtpro/disks) in preparation for transfer
|
||||
vsdsync : update ADTPro server with the current virtual drive images
|
||||
|
||||
|
||||
nulib2 : create, extract, and work with NuFX (ShrinkIt) archive files
|
||||
sciibin : decode BinSCII file (they start with 'FiLeStArTfIlEsTaRt')
|
||||
unblu/usq/unbit/unexec : decode Binary II, Squeezed, Executioner,
|
||||
@ -79,7 +67,7 @@ wget : download a single URL from an FTP or web site
|
||||
irssi : IRC chat (general purpose)
|
||||
a2chat : IRC chat (automatically opens to Apple II channel)
|
||||
a2news : read and post on Usenet discussions (default Apple II topics)
|
||||
ttytter : tweet like there's no tomorrow
|
||||
oysttyer : tweet like there's no tomorrow
|
||||
|
||||
emulators:
|
||||
gsport : GSport Apple IIgs emulator
|
||||
|
44
setup/a2cloudrc
Executable file
44
setup/a2cloudrc
Executable file
@ -0,0 +1,44 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# a2cloudrc - a2cloud user environment script for bash
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
source /usr/local/etc/a2cloud-aliases
|
||||
|
||||
if [[ -f /usr/local/java/bin/java ]]; then
|
||||
export JAVA_HOME=/usr/local/java
|
||||
elif [[ -f /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/jre/bin/java ]]; then # Ubuntu 14.04 RPi2
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle-armhf/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle-armhf
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle
|
||||
fi
|
||||
[[ ! $(grep java <<< $PATH) ]] && PATH=$PATH:$JAVA_HOME/bin
|
||||
|
||||
if [[ -f /usr/local/etc/a2cloud-lang ]]; then
|
||||
lang8bit=$(cat /usr/local/etc/a2cloud-lang)
|
||||
else
|
||||
lang8bit=C
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
myTTY=$(ps hp $(ps hp $(ps hp $$ -o ppid) -o ppid) -o tty)
|
||||
else
|
||||
myTTY=$(tty)
|
||||
export ttyTERM="$TERM"
|
||||
fi
|
||||
if [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]]; then
|
||||
LANG=$lang8bit
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
TERM=$ttyTERM
|
||||
fi
|
@ -1,34 +0,0 @@
|
||||
source /usr/local/etc/a2cloud-aliases
|
||||
|
||||
if [[ -f /usr/local/java/bin/java ]]; then
|
||||
export JAVA_HOME=/usr/local/java
|
||||
elif [[ -f /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
|
||||
elif [[ -f /usr/lib/jvm/java-8-oracle/jre/bin/java ]]; then # Ubuntu 14.04 RPi2
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle-armhf/bin/java ]]; then # RPi
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle-armhf
|
||||
elif [[ -f /usr/lib/jvm/jdk-7-oracle/bin/java ]]; then # webupd8
|
||||
export JAVA_HOME=/usr/lib/jvm/jdk-7-oracle
|
||||
fi
|
||||
[[ ! $(grep java <<< $PATH) ]] && PATH=$PATH:$JAVA_HOME/bin
|
||||
|
||||
if [[ -f /usr/local/etc/a2cloud-lang ]]; then
|
||||
lang8bit=$(cat /usr/local/etc/a2cloud-lang)
|
||||
else
|
||||
lang8bit=C
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
myTTY=$(ps hp $(ps hp $(ps hp $$ -o ppid) -o ppid) -o tty)
|
||||
else
|
||||
myTTY=$(tty)
|
||||
export ttyTERM="$TERM"
|
||||
fi
|
||||
if [[ $(grep ttyUSB <<< $myTTY) || $(grep ttyAMA <<< $myTTY) ]]; then
|
||||
LANG=$lang8bit
|
||||
fi
|
||||
if [[ ${TERM:0:6} == "screen" ]]; then
|
||||
TERM=$ttyTERM
|
||||
fi
|
67
setup/a2news
Executable file
67
setup/a2news
Executable file
@ -0,0 +1,67 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# a2news - a2cloud nntp client wrapper
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
defaultNNTP="news.aioe.org"
|
||||
defaultGroups="comp.emulators.apple2:\ncomp.sys.apple2:\ncomp.sys.apple2.comm:\ncomp.sys.apple2.marketplace:\ncomp.sys.apple2.programmer:\ncomp.sys.apple2.usergroups:"
|
||||
|
||||
if [[ ! $(dpkg -l tin 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing Tin newsreader..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install tin &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-h" || $1 == "--help" ]]; then
|
||||
echo "Usage: a2news [-s nntpServerAddress] [-m postingEmailAddress] [otherTinOptions]"
|
||||
echo " note: for full options, instead use 'tin'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $1 == "-s" || $1 == "-m" ]]; do
|
||||
if [[ $1 == "-s" && $2 ]]; then
|
||||
nntpServer=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-m" && $2 ]]; then
|
||||
emailAddress=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/.tin
|
||||
|
||||
if [[ ! -f ~/.newsrc ]]; then
|
||||
IFS=''; echo -e "$defaultGroups" > ~/.newsrc
|
||||
fi
|
||||
|
||||
if [[ $nntpServer || ! -f ~/.tin/nntp.server ]]; then
|
||||
[[ ! $nntpServer ]] && nntpServer="$defaultNNTP"
|
||||
echo "$nntpServer" > ~/.tin/nntp.server
|
||||
else
|
||||
nntpServer=$(cat ~/.tin/nntp.server)
|
||||
fi
|
||||
|
||||
if [[ $emailAddress || ! -f ~/.tin/tinrc ]]; then
|
||||
while [[ ! $emailAddress || ! $(grep "@" <<< $emailAddress) || ! $(grep "\." <<< $emailAddress) ]]; do
|
||||
echo -n "Enter the email address you want to post as: "
|
||||
read
|
||||
emailAddress=$REPLY
|
||||
done
|
||||
if [[ -f ~/.tin/tinrc ]]; then
|
||||
sed -i "s/^mail_address=.*$/mail_address=$emailAddress/" ~/.tin/tinrc
|
||||
else
|
||||
echo "mail_address=$emailAddress" > ~/.tin/tinrc
|
||||
fi
|
||||
fi
|
||||
|
||||
NNTPSERVER=$nntpServer tin -r "$@"
|
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
defaultNNTP="news.aioe.org"
|
||||
defaultGroups="comp.emulators.apple2:\ncomp.sys.apple2:\ncomp.sys.apple2.comm:\ncomp.sys.apple2.marketplace:\ncomp.sys.apple2.programmer:\ncomp.sys.apple2.usergroups:"
|
||||
|
||||
if [[ ! $(dpkg -l tin 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Installing Tin newsreader..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install tin &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ $1 == "-h" || $1 == "--help" ]]; then
|
||||
echo "Usage: a2news [-s nntpServerAddress] [-m postingEmailAddress] [otherTinOptions]"
|
||||
echo " note: for full options, instead use 'tin'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $1 == "-s" || $1 == "-m" ]]; do
|
||||
if [[ $1 == "-s" && $2 ]]; then
|
||||
nntpServer=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-m" && $2 ]]; then
|
||||
emailAddress=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/.tin
|
||||
|
||||
if [[ ! -f ~/.newsrc ]]; then
|
||||
IFS=''; echo -e "$defaultGroups" > ~/.newsrc
|
||||
fi
|
||||
|
||||
if [[ $nntpServer || ! -f ~/.tin/nntp.server ]]; then
|
||||
[[ ! $nntpServer ]] && nntpServer="$defaultNNTP"
|
||||
echo "$nntpServer" > ~/.tin/nntp.server
|
||||
else
|
||||
nntpServer=$(cat ~/.tin/nntp.server)
|
||||
fi
|
||||
|
||||
if [[ $emailAddress || ! -f ~/.tin/tinrc ]]; then
|
||||
while [[ ! $emailAddress || ! $(grep "@" <<< $emailAddress) || ! $(grep "\." <<< $emailAddress) ]]; do
|
||||
echo -n "Enter the email address you want to post as: "
|
||||
read
|
||||
emailAddress=$REPLY
|
||||
done
|
||||
if [[ -f ~/.tin/tinrc ]]; then
|
||||
sed -i "s/^mail_address=.*$/mail_address=$emailAddress/" ~/.tin/tinrc
|
||||
else
|
||||
echo "mail_address=$emailAddress" > ~/.tin/tinrc
|
||||
fi
|
||||
fi
|
||||
|
||||
NNTPSERVER=$nntpServer tin -r "$@"
|
421
setup/acmd
Executable file
421
setup/acmd
Executable file
@ -0,0 +1,421 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# acmd - a2cloud command-line wrapper for Apple II file utilities
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# set default AppleCommander location if ADTPro is not installed
|
||||
defaultAcPath=$(echo -n /usr/local/bin/AppleCommander-*-ac.jar)
|
||||
|
||||
echoerr() {
|
||||
echo "$@" 1>&2;
|
||||
}
|
||||
|
||||
helpExit () {
|
||||
if [[ -s $acmdStdErr ]]; then
|
||||
if [[ $(grep CommandLineHelp $acmdStdErr) ]]; then
|
||||
grep -v ^-[pge][[:space:]] $acmdStdErr | grep -v '^ or' | grep -v 0x2000 1>&2
|
||||
echoerr "-g <imagename> <filename> [<outputFilename>] copy filename out of any"
|
||||
echoerr " disk image. Using - for outputFilename will copy to stdout."
|
||||
echoerr "-e <imagename> <filename> [<outputFilename>] like -g, with conversion"
|
||||
echoerr " to modern file format if possible."
|
||||
echoerr "-p <imagename> <filename> [[$|0x]<type>] [[$|0x]<auxtype>] copy filename"
|
||||
echoerr " into ProDOS disk image. <type> is either three-letter or numeric"
|
||||
echoerr " ProDOS file type (BIN if omitted). Will read from stdin if supplied."
|
||||
echoerr " ProDOS subdirectories in <filename> will be created if needed."
|
||||
echoerr " If an AppleDouble file or Nulib2 extended filename is detected,"
|
||||
echoerr " <type> and <auxtype> are automatically set, and resource forks are kept."
|
||||
if hash cppo &> /dev/null; then
|
||||
echoerr " (To extract these from a ProDOS image file, use cppo -ad or cppo -e.)"
|
||||
fi
|
||||
echoerr "-c <filename> <imagename> [[$|0x]<type>] [[$|0x]<auxtype>] synonym for -p"
|
||||
echoerr " with filename and imagename reversed."
|
||||
else
|
||||
cat $acmdStdErr
|
||||
fi
|
||||
if [[ $arg1 == "-h" ]]; then
|
||||
exitVal=0
|
||||
else
|
||||
exitVal=1
|
||||
fi
|
||||
else
|
||||
if [[ $vsd1_md5 && ( "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ) ]]; then
|
||||
if [[ "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ]]; then
|
||||
echoerr "One of the virtual drive image files has changed while ADTPro server is active."
|
||||
echoerr " If using VSDRIVE, type 'vsdsync' now to see changes and prevent corruption."
|
||||
fi
|
||||
fi
|
||||
exitval=0
|
||||
fi
|
||||
rm $acmdStdErr &> /dev/null
|
||||
exit $exitVal
|
||||
}
|
||||
|
||||
decToBin () {
|
||||
dec="$(( 10#$1 ))"
|
||||
bits=""
|
||||
for i in 7 6 5 4 3 2 1 0; do
|
||||
bits+=$(( (dec & (2**i)) >> i ))
|
||||
done
|
||||
echo -n "$(( 10#$bits ))"
|
||||
}
|
||||
|
||||
arg1=$1
|
||||
|
||||
acmdStdErr="/tmp/acmd_$RANDOM$RANDOM"
|
||||
|
||||
[[ -f /usr/libexec/java_home ]] && osx=1 || osx=
|
||||
|
||||
if [[ $osx ]]; then
|
||||
if ! /usr/libexec/java_home &> /dev/null; then
|
||||
echo -n "AppleCommander requires the Java JDK. Do you want to install it now? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
# install Oracle Java for OS X
|
||||
echo "Downloading Java JDK..."
|
||||
mkdir -p /tmp/jdk
|
||||
curl -L --cookie oraclelicense=accept-securebackup-cookie $(curl -L "http://www.oracle.com/"$(curl -L "http://www.oracle.com/technetwork/java/javase/downloads/" 2> /dev/null | grep -o -m 1 '/technetwork/java/javase/downloads/jdk.-downloads-[0-9]*\.html') 2> /dev/null | grep -o 'http://.*macosx-x64.dmg' | sort | tail -1) 2> /dev/null > /tmp/jdk/jdk.dmg
|
||||
echo "Installing Java JDK..."
|
||||
hdiutil attach /tmp/jdk/jdk.dmg &> /dev/null
|
||||
sudo installer -pkg /Volumes/JDK*/JDK*.pkg -target /
|
||||
diskutil unmountDisk /Volumes/JDK*
|
||||
rm -r /tmp/jdk 2> /dev/null
|
||||
if ! /usr/libexec/java_home &> /dev/null; then
|
||||
echo "The Java JDK could not be installed."
|
||||
echo "Type \"java\" and then click \"More Info...\" to download and install it manually."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else # not OS X, so presumably Linux
|
||||
if ! hash java &> /dev/null; then
|
||||
echo -n "AppleCommander requires the Java JDK. "
|
||||
if hash apt-get; then
|
||||
echo -n "Do you want to install it now? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
# from http://www.webupd8.org/2012/06/how-to-install-oracle-java-7-in-debian.html
|
||||
if { ! grep -q webupd8team /etc/apt/sources.list; }; then
|
||||
{
|
||||
echo;
|
||||
echo "# Oracle Java JDK";
|
||||
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main";
|
||||
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main";
|
||||
} | sudo tee -a /etc/apt/sources.list > /dev/null
|
||||
fi
|
||||
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
|
||||
sudo apt-get -y update
|
||||
echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
|
||||
sudo apt-get -y install oracle-java8-installer
|
||||
sudo apt-get -y clean
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if ! hash java &> /dev/null; then
|
||||
echo
|
||||
echo "Get it from http://www.oracle.com/technetwork/java/javase/downloads/"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
setAcPath () {
|
||||
acPath=$defaultAcPath
|
||||
adtPath=
|
||||
if [[ ! -f $acPath ]]; then
|
||||
if [[ -f /usr/local/adtpro/adtpro.sh ]]; then
|
||||
adtPath="/usr/local/adtpro"
|
||||
elif [[ $osx ]]; then
|
||||
adtPath=$(echo -n /Applications/ADTPro* | tr ' ' '\n' | sort | head -1);
|
||||
fi
|
||||
if [[ -d "$adtPath" ]]; then
|
||||
acPath="$adtPath"/lib/AppleCommander/AppleCommander-ac.jar
|
||||
[[ ! -f $acPath ]] && acPath=$(echo -n "$adtPath"/lib/AppleCommander/AppleCommander-*-ac.jar)
|
||||
fi
|
||||
fi
|
||||
acPath=$(echo -n $acPath)
|
||||
}
|
||||
|
||||
setAcPath
|
||||
if [[ ! -f $acPath ]]; then
|
||||
echo "Installing AppleCommander..."
|
||||
sudo mkdir -p /usr/local/bin
|
||||
acUrl="http://sourceforge.net/projects/applecommander/files/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar/download"
|
||||
if [[ $osx ]]; then
|
||||
curl -L "$acUrl" 2> /dev/null | sudo tee /usr/local/bin/AppleCommander-1.3.5.13id-ac.jar > /dev/null
|
||||
else
|
||||
sudo wget -qO /usr/local/bin/AppleCommander-1.3.5.13id-ac.jar "$acUrl"
|
||||
fi
|
||||
setAcPath
|
||||
if [[ ! -f "$acPath" ]]; then
|
||||
echo "AppleCommander couldn't be installed. Download it from"
|
||||
echo "http://applecommander.sourceforge.net and put it in /usr/local/bin."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
ac="java -Xmx128m -jar $acPath"
|
||||
|
||||
if [[ ! $2 || $arg1 == "-h" ]]; then
|
||||
java -jar "$acPath" 2> $acmdStdErr
|
||||
[[ $? -eq 127 ]] && exit 127 || helpExit $arg1
|
||||
fi
|
||||
|
||||
if [[ $arg1 != "-i" && $arg1 != "-ls" && $arg1 != "-l" && $arg1 != "-ll" && $arg1 != "-x" && $arg1 != "-g" && $arg1 != "-e" && $(ps aux | grep [A]DTPro) ]]; then
|
||||
vsd1_md5="$(md5sum /usr/local/adtpro/disks/Virtual.po)"
|
||||
vsd2_md5="$(md5sum /usr/local/adtpro/disks/Virtual2.po)"
|
||||
fi
|
||||
|
||||
if [[ ( $arg1 == "-p" || $arg1 == "-c" || $arg1 == "-g" || $arg1 == "-e" ) && $2 && $3 ]]; then
|
||||
|
||||
AD=
|
||||
EX=
|
||||
prodosArg=
|
||||
prodosArgParent=
|
||||
rFile=
|
||||
getArg=
|
||||
if [[ $arg1 == "-c" || $arg1 == "-p" ]]; then
|
||||
if [[ $arg1 == "-c" ]]; then
|
||||
prodosArg="$2"
|
||||
imageArg="$3"
|
||||
elif [[ $arg1 == "-p" ]]; then
|
||||
prodosArg="$3"
|
||||
imageArg="$2"
|
||||
fi
|
||||
[[ $prodosArg == *"/"* ]] && prodosArgParent="${prodosArg%/*}/"
|
||||
rFile="${prodosArgParent}.AppleDouble/${prodosArg##*/}"
|
||||
if [[ -f "$prodosArg" && -f "$rFile" ]]; then # AppleDouble
|
||||
AD=1
|
||||
elif [ -f "${prodosArg%#*}"#?????? ]; then # Nulib2 ext filename
|
||||
EX=1
|
||||
prodosArg=$(echo -n "${prodosArg%#*}"#??????)
|
||||
rFile="${prodosArg}"r
|
||||
fi
|
||||
if [[ $AD || $EX ]]; then
|
||||
# if target is not a ProDOS disk, ignore metadata
|
||||
if ! $ac -i "$imageArg" | grep -q '^Disk Format: ProDOS'; then
|
||||
AD=
|
||||
EX=
|
||||
fi
|
||||
fi
|
||||
elif [[ $arg1 == "-g" || $arg1 == "-e" ]]; then
|
||||
fileArg="$3"
|
||||
imageArg="$2"
|
||||
getArg="$arg1"
|
||||
else
|
||||
exit 2;
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
if [[ $getArg ]]; then # get file
|
||||
|
||||
outFile=
|
||||
[[ $3 && $3 != "-" ]] && outFile="$3"
|
||||
[[ ! $3 ]] && outFile="${2##*/}"
|
||||
$ac $getArg "$imageArg" "$fileArg" $outFile 2> $acmdStdErr
|
||||
|
||||
else # put file
|
||||
|
||||
# test ProDOS name validity
|
||||
prodosPath=$(tr [:lower:] [:upper:] <<< "${prodosArg%#*}" )
|
||||
IFS_orig="$IFS"; IFS="/";
|
||||
prodosPathParts="$prodosPath"
|
||||
for thisProdosPathPart in $prodosPathParts; do
|
||||
if [[ ${#thisProdosPathPart} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $thisProdosPathPart) ]]; then
|
||||
echoerr "Invalid ProDOS name: $prodosPath"; exit 1;
|
||||
fi
|
||||
done
|
||||
IFS="$IFS_orig"
|
||||
|
||||
# filetype to name table
|
||||
P_00=UNK; P_01=BAD; P_02=PCD; P_03=PTX; P_04=TXT; P_05=PDA; P_06=BIN; P_07=FNT; P_08=FOT; P_09=BA3; P_0a=DA3; P_0b=WPF; P_0c=SOS; P_0f=DIR; P_10=RPD; P_11=RPI; P_12=AFD; P_13=AFM; P_14=AFR; P_15=SCL; P_16=PFS; P_19=ADB; P_1a=AWP; P_1b=ASP; P_20=TDM; P_21=IPS; P_22=UPV; P_29=3SD; P_2a=8SC; P_2b=8OB; P_2c=8IC; P_2d=8LD; P_2e=P8C; P_41=OCR; P_42=FTD; P_50=GWP; P_51=GSS; P_52=GDB; P_53=DRW; P_54=GDP; P_55=HMD; P_56=EDU; P_57=STN; P_58=HLP; P_59=COM; P_5a=CFG; P_5b=ANM; P_5c=MUM; P_5d=ENT; P_5e=DVU; P_60=PRE; P_6b=BIO; P_6d=DVR; P_6e=PRE; P_6f=HDV; P_80=GEZ; P_81=GE1; P_82=GEO; P_83=GE3; P_84=GE4; P_85=GE5; P_86=GE6; P_87=GE7; P_88=GE8; P_89=GE9; P_8a=GEA; P_8b=GEB; P_8c=GEC; P_8d=GED; P_8e=GEE; P_8f=GEF; P_a0=WP_; P_ab=GSB; P_ac=TDF; P_ad=BDF; P_b0=SRC; P_b1=OBJ; P_b2=LIB; P_b3=S16; P_b4=RTL; P_b5=EXE; P_b6=STR; P_b7=TSF; P_b8=NDA; P_b9=CDA; P_ba=TOL; P_bb=DRV; P_bc=LDF; P_bd=FST; P_bf=DOC; P_c0=PNT; P_c1=PIC; P_c2=ANI; P_c3=PAL; P_c5=OOG; P_c6=SCR; P_c7=CDV; P_c8=FON; P_c9=FND; P_ca=ICN; P_d5=MUS; P_d6=INS; P_d7=MDI; P_d8=SND; P_db=DBM; P_e0=SHK; P_e2=DTS; P_ee=R16; P_ef=PAS; P_f0=CMD; P_f9=P16; P_fa=INT; P_fb=IVR; P_fc=BAS; P_fd=VAR; P_fe=REL; P_ff=SYS;
|
||||
|
||||
# process filetype
|
||||
if [[ ! $AD && ! $EX ]]; then # no resource fork or metadata
|
||||
[[ ${3:0:2} == "0x" ]] && ftArg="\$${3:2}" || ftArg="$3"
|
||||
auxType="$4"
|
||||
|
||||
# assume BIN/$2000 if filetype omitted
|
||||
if [[ ! $ftArg ]]; then
|
||||
ft="BIN"
|
||||
auxType="\$2000"
|
||||
# accept hex or decimal number for file type
|
||||
elif [[ ( ${ftArg:0:1} == '$' && ${#ftArg} -eq 3 ) || $(grep [0-9] <<< ${ftArg:0:1}) ]]; then
|
||||
if [[ ${ftArg:0:1} == '$' ]]; then
|
||||
fc=$(tr [:upper:] [:lower:] <<< ${ftArg:1:2})
|
||||
else
|
||||
fc=$(printf %02X "$ftArg" | tr [:upper:] [:lower:])
|
||||
fi
|
||||
ftVar="P_$fc";
|
||||
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc";
|
||||
else
|
||||
ft="$ftArg"
|
||||
fi
|
||||
|
||||
# set auxtype to $0801 for Applesoft programs if not specified
|
||||
[[ $ft == "BAS" && ! $auxType ]] && auxType="\$0801"
|
||||
|
||||
# test for absence of stdin [[ -t 0 ]] and if absent use ProDOS name
|
||||
if [[ -t 0 ]]; then
|
||||
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
||||
$ac -d "$imageArg" $prodosPath &> /dev/null
|
||||
$ac -p "$imageArg" $prodosPath $ft $auxType < $prodosArg 2> $acmdStdErr
|
||||
else
|
||||
$ac -d "$imageArg" $prodosPath &> /dev/null
|
||||
$ac -p "$imageArg" $prodosPath $ft $auxType 2> $acmdStdErr
|
||||
fi
|
||||
else # AppleDouble or nulib extended, get resource fork and file metadata from header file
|
||||
|
||||
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
||||
[[ $AD && ! -f $rFile ]] && { echoerr "Not an AppleDouble file: $rFile"; exit 1; }
|
||||
|
||||
if [[ $AD ]]; then
|
||||
# get metadata from AppleDouble header
|
||||
[[ $(dd if="$rFile" bs=1 count=1 skip=741 2> /dev/null | wc -c) -gt 0 ]] && isExtFile=1 || isExtFile=
|
||||
fileData=$(dd if="$rFile" bs=1 count=24 skip=637 2> /dev/null | xxd -p | tr -d '\n')
|
||||
ftVar="P_${fileData:34:2}";
|
||||
auxType="\$"${fileData:36:4}
|
||||
cDateTime=$(printf %d 0x${fileData:0:8})
|
||||
mDateTime=$(printf %d 0x${fileData:8:8})
|
||||
[[ $(printf %d 0x"${fileData:0:2}") -gt 127 ]] && (( cDateTime-=4294967296 )) # handle negative hex number
|
||||
[[ $(printf %d 0x"${fileData:8:2}") -gt 127 ]] && (( mDateTime-=4294967296 )) # handle negative hex number
|
||||
(( cDateTime+=946684800 )) # convert AD timestamp to Unix timestamp
|
||||
(( mDateTime+=946684800 )) # convert AD timestamp to Unix timestamp
|
||||
else # EX
|
||||
# get metadata from file info
|
||||
[[ -f "$rFile" ]] && isExtFile=1 || isExtFile=
|
||||
ftVar="P_${prodosArg: -6:2}"
|
||||
auxType="\$"${prodosArg: -4}
|
||||
if [[ $osx ]]; then
|
||||
mDateTime=$(stat -f "%m" "$prodosArg")
|
||||
else
|
||||
mDateTime=$(stat -c %Y "$prodosArg")
|
||||
fi
|
||||
cDateTime=$mDateTime
|
||||
fi
|
||||
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc"; # set file type
|
||||
# convert unix timestamp to ProDOS bitfield yyyyyyymmmmddddd 000hhhhh00mmmmmm
|
||||
cDateFields=($(date -d @$cDateTime +"%y %m %d %H %M" 2> /dev/null))
|
||||
[[ ! $cDateFields ]] && cDateFields=($(date -r $cDateTime +"%y %m %d %H %M")) # OS X/BSD
|
||||
mDateFields=($(date -d @$mDateTime +"%y %m %d %H %M" 2> /dev/null))
|
||||
[[ ! $mDateFields ]] && mDateFields=($(date -r $mDateTime +"%y %m %d %H %M")) # OS X/BSD
|
||||
cDateTimeHex=$(printf %08X $(( 2#$(printf %07d $(decToBin ${cDateFields[0]}))$(printf %04d $(decToBin ${cDateFields[1]}))$(printf %05d $(decToBin ${cDateFields[2]}))$(printf %08d $(decToBin ${cDateFields[3]}))$(printf %08d $(decToBin ${cDateFields[4]})) )))
|
||||
cDateTimeHex=${cDateTimeHex:2:2}${cDateTimeHex:0:2}${cDateTimeHex:6:2}${cDateTimeHex:4:2}
|
||||
mDateTimeHex=$(printf %08X $(( 2#$(printf %07d $(decToBin ${mDateFields[0]}))$(printf %04d $(decToBin ${mDateFields[1]}))$(printf %05d $(decToBin ${mDateFields[2]}))$(printf %08d $(decToBin ${mDateFields[3]}))$(printf %08d $(decToBin ${mDateFields[4]})) )))
|
||||
mDateTimeHex=${mDateTimeHex:2:2}${mDateTimeHex:0:2}${mDateTimeHex:6:2}${mDateTimeHex:4:2}
|
||||
|
||||
# create forks and file entry
|
||||
### RIGHT HERE PROBLEMS IF #000000 specified and maybe if not
|
||||
fileName="${prodosPath##*/}"
|
||||
if [[ $isExtFile ]]; then
|
||||
dfName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
||||
while [[ ! $rfName || $rfName == $dfName ]]; do
|
||||
rfName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
||||
done
|
||||
while [[ $fileName == "${prodosPath##*/}" || $rfName == $fileName || $dfName == $fileName ]]; do
|
||||
fileName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
||||
done
|
||||
$ac -d "$imageArg" "${prodosArgParent}$dfName" 2> /dev/null
|
||||
dd if="$prodosArg" 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$dfName" $00 2> $acmdStdErr
|
||||
$ac -d "$imageArg" "${prodosArgParent}$rfName" 2> /dev/null
|
||||
dd if="$rFile" bs=1 skip=$(( 0$AD ? 741 : 0 )) 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$rfName" $00 2> $acmdStdErr
|
||||
fi
|
||||
|
||||
# create file entry, then find it
|
||||
$ac -d "$imageArg" "${prodosArgParent}$fileName" 2> /dev/null
|
||||
[[ $isExtFile ]] && ddsrc="if=/dev/zero bs=512 count=1" || ddsrc="if=$prodosArg"
|
||||
dd $ddsrc 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$fileName" "$ft" "$auxType" 2> $acmdStdErr
|
||||
# thx to http://unix.stackexchange.com/a/122945/99697 for perl alternative to broken --byte-offset in grep 2.5.1 (e.g. in OS X)
|
||||
fileEntryOffset=$(perl -n0777e "print pos()-length('.$fileName') while /.$fileName/g" < "$imageArg")
|
||||
fileEntry=$(dd if="$imageArg" bs=1 count=39 skip=$fileEntryOffset 2> /dev/null | xxd -p | tr -d '\n')
|
||||
|
||||
if [[ $isExtFile ]]; then
|
||||
extKeyBlockOffset=$(( ( ( $(printf %d 0x"${fileEntry:36:2}") * 256 ) + $(printf %d 0x"${fileEntry:34:2}") * 512 ) ))
|
||||
|
||||
# find data fork, copy storage type, key block, block size, length to extended key block mini-entry
|
||||
# then mark as available/deleted
|
||||
dfOffset=$(perl -n0777e "print pos()-length('.$dfName') while /.$dfName/g" < "$imageArg")
|
||||
dfEntry=$(dd if="$imageArg" bs=1 count=39 skip=$dfOffset 2> /dev/null | xxd -p | tr -d '\n')
|
||||
dfStorageType=$(printf %02X $(( $(printf %d 0x${dfEntry:0:2}) >> 4 )) )
|
||||
dfBlocksUsed=$(( ( $(printf %d 0x${dfEntry:40:2}) * 256 ) + $(printf %d 0x${dfEntry:38:2}) ))
|
||||
dfInfo=${dfEntry:34:14}
|
||||
echo -n -e \\x"$dfStorageType"$(sed 's/../\\x&/g' <<< $dfInfo) \
|
||||
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( extKeyBlockOffset+0 )) 2> /dev/null
|
||||
# mark as deleted
|
||||
echo -n -e \\x0${dfEntry:1:1} \
|
||||
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( dfOffset+0 )) 2> /dev/null
|
||||
|
||||
# find resource fork, copy storage type, key block, block size, length to extended key block mini-entry
|
||||
# then mark as available/deleted
|
||||
rfOffset=$(perl -n0777e "print pos()-length('.$rfName') while /.$rfName/g" < "$imageArg")
|
||||
rfEntry=$(dd if="$imageArg" bs=1 count=39 skip=$rfOffset 2> /dev/null | xxd -p | tr -d '\n')
|
||||
rfStorageType=$(printf %02X $(( $(printf %d 0x${rfEntry:0:2}) >> 4 )) )
|
||||
rfBlocksUsed=$(( ( $(printf %d 0x${rfEntry:40:2}) * 256 ) + $(printf %d 0x${rfEntry:38:2}) ))
|
||||
rfInfo=${rfEntry:34:14}
|
||||
echo -n -e \\x"$rfStorageType"$(sed 's/../\\x&/g' <<< $rfInfo) \
|
||||
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( extKeyBlockOffset+256 )) 2> /dev/null
|
||||
# mark as deleted
|
||||
echo -n -e \\x0${rfEntry:1:1} \
|
||||
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( rfOffset+0 )) 2> /dev/null
|
||||
|
||||
# reduce active file count in directory by two
|
||||
parentDirKeyBlockOffset=$(( ( ( $(printf %d 0x"${fileEntry:76:2}") * 256 ) + $(printf %d 0x"${fileEntry:74:2}") * 512 ) ))
|
||||
fileCountHex=$(dd if="$imageArg" bs=1 count=2 skip=$((parentDirKeyBlockOffset+4+33)) 2> /dev/null | xxd -p)
|
||||
fileCount=$(( ( $(printf %d 0x${fileCountHex:2:2}) * 256 ) + $(printf %d 0x${fileCountHex:0:2}) ))
|
||||
fileCountHex=$(printf %04X $((fileCount - 2)))
|
||||
echo -n -e \\x${fileCountHex:2:2}\\x${fileCountHex:0:2} \
|
||||
| dd of="$imageArg" conv=notrunc bs=1 seek=$((parentDirKeyBlockOffset+4+33)) 2> /dev/null
|
||||
|
||||
# update extended file metadata
|
||||
|
||||
# storage type (5), name length, name
|
||||
name="${prodosPath##*/}"
|
||||
nameLen=${#name}
|
||||
nameHeader=$(printf %02X $((nameLen + 80)) )
|
||||
nameField=$(echo -n $name | xxd -p | tr -d '\n' | sed -e :a -e 's/^.\{1,29\}$/&00/;ta')
|
||||
|
||||
# blocks used
|
||||
blocksUsed=$(( dfBlocksUsed + rfBlocksUsed + 1 ))
|
||||
|
||||
# store updated metadata
|
||||
fileEntry=${nameHeader}${nameField}${fileEntry:32}
|
||||
fi
|
||||
|
||||
# put creation and modified date in file entry
|
||||
fileEntry=${fileEntry:0:48}${cDateTimeHex}${fileEntry:56:10}${mDateTimeHex}${fileEntry:74:4}
|
||||
|
||||
# put casemask for mixed case filename in file entry
|
||||
[[ $EX ]] && prodosArg="${prodosArg%#*}"
|
||||
if [[ "${prodosPath##*/}" != "${prodosArg##*/}" ]]; then # mixed case
|
||||
caseMaskDec=32768
|
||||
mixedName="${prodosArg##*/}"
|
||||
[[ $EX ]] && mixedName="${mixedName%#*}"
|
||||
for (( i=0; i<${#mixedName}; i++ )); do
|
||||
[[ "${mixedName:$i:1}" == $(tr [:lower:] [:upper:] <<< "${mixedName:$i:1}") ]] # $? == 0 means uppercase
|
||||
(( caseMaskDec+=$(( $? * (2**(14-i)) )) ))
|
||||
done
|
||||
caseMaskHex=$(printf %04X $caseMaskDec)
|
||||
fileEntry=${fileEntry:0:56}${caseMaskHex:2:2}${caseMaskHex:0:2}${fileEntry:60}
|
||||
fi
|
||||
|
||||
# write updated metadata to file entry
|
||||
echo -n -e $(sed 's/../\\x&/g' <<< $fileEntry) | dd of="$imageArg" bs=1 conv=notrunc seek=$fileEntryOffset 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
imageArg="$2"
|
||||
$ac "$@" 2> $acmdStdErr
|
||||
|
||||
fi
|
||||
|
||||
helpExit
|
151
setup/acmd.txt
151
setup/acmd.txt
@ -1,151 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
decToHex () {
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex value from 00-FF
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $arg1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$arg1" 2> /dev/null) == $arg1 ) \
|
||||
&& ( $arg1 -ge 0 ) && ( $arg1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
printf %02X "$arg1"
|
||||
}
|
||||
|
||||
echoerr() {
|
||||
echo "$@" 1>&2;
|
||||
}
|
||||
|
||||
helpExit () {
|
||||
if [[ -s $acmdStdErr ]]; then
|
||||
if [[ $(grep CommandLineHelp $acmdStdErr) ]]; then
|
||||
grep -v ^-[pge][[:space:]] $acmdStdErr | grep -v '^ or' | grep -v 0x2000 1>&2
|
||||
echoerr "-g <imagename> <filename> [<outputFilename>] copy filename out of any"
|
||||
echoerr " disk image. Using - for outputFilename will copy to stdout."
|
||||
echoerr "-e <imagename> <filename> [<outputFilename>] like -g, with conversion"
|
||||
echoerr " to modern file format if possible."
|
||||
echoerr "-p <imagename> <filename> [[$|0x]<type>] [[$|0x]<auxtype>] copy filename"
|
||||
echoerr " into ProDOS disk image. <type> is either three-letter or numeric"
|
||||
echoerr " ProDOS file type (BIN if omitted). Will read from stdin if supplied."
|
||||
echoerr " ProDOS subdirectories in <filename> will be created if needed."
|
||||
echoerr "-c <filename> <imagename> [[$|0x]<type>] [[$|0x]<auxtype>] synonym for -p"
|
||||
echoerr " with filename and imagename reversed."
|
||||
else
|
||||
cat $acmdStdErr
|
||||
fi
|
||||
if [[ $arg1 == "-h" ]]; then
|
||||
exitVal=0
|
||||
else
|
||||
exitVal=1
|
||||
fi
|
||||
else
|
||||
if [[ $vsd1_md5 && ( "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ) ]]; then
|
||||
if [[ "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ]]; then
|
||||
echoerr "One of the virtual drive image files has changed while ADTPro server is active."
|
||||
echoerr " If using VSDRIVE, type 'vsdsync' now to see changes and prevent corruption."
|
||||
fi
|
||||
fi
|
||||
exitval=0
|
||||
fi
|
||||
rm $acmdStdErr &> /dev/null
|
||||
exit $exitVal
|
||||
}
|
||||
|
||||
arg1=$1
|
||||
|
||||
acmdStdErr="/tmp/acmd_$RANDOM$RANDOM"
|
||||
|
||||
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
|
||||
|
||||
if [[ ! $2 || $arg1 == "-h" ]]; then
|
||||
java -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar 2> $acmdStdErr
|
||||
[[ $? -eq 127 ]] && exit 127 || helpExit $arg1
|
||||
fi
|
||||
|
||||
if [[ $arg1 != "-i" && $arg1 != "-ls" && $arg1 != "-l" && $arg1 != "-ll" && $arg1 != "-x" && $arg1 != "-g" && $arg1 != "-e" && $(ps aux | grep [A]DTPro) ]]; then
|
||||
vsd1_md5="$(md5sum /usr/local/adtpro/disks/Virtual.po)"
|
||||
vsd2_md5="$(md5sum /usr/local/adtpro/disks/Virtual2.po)"
|
||||
fi
|
||||
|
||||
if [[ ( $arg1 == "-p" || $arg1 == "-c" || $arg1 == "-g" || $arg1 == "-e" ) && $2 && $3 ]]; then
|
||||
|
||||
getArg=
|
||||
if [[ $arg1 == "-p" ]]; then
|
||||
prodosArg="$3"
|
||||
imageArg="$2"
|
||||
elif [[ $arg1 == "-c" ]]; then
|
||||
prodosArg="$2"
|
||||
imageArg="$3"
|
||||
elif [[ $arg1 == "-g" || $arg1 == "-e" ]]; then
|
||||
fileArg="$3"
|
||||
imageArg="$2"
|
||||
getArg="$arg1"
|
||||
else
|
||||
exit 2;
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
if [[ $getArg ]]; then # get file
|
||||
outFile=
|
||||
[[ $3 && $3 != "-" ]] && outFile="$3"
|
||||
[[ ! $3 ]] && outFile="${2##*/}"
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar $getArg "$imageArg" "$fileArg" $outFile 2> $acmdStdErr
|
||||
else # put file
|
||||
|
||||
# test ProDOS name legitimacy
|
||||
prodosPath=$(tr [:lower:] [:upper:] <<< $prodosArg )
|
||||
IFS_orig="$IFS"; IFS="/";
|
||||
prodosPathParts="$prodosPath"
|
||||
for thisProdosPathPart in $prodosPathParts; do
|
||||
if [[ ${#thisProdosPathPart} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $thisProdosPathPart) ]]; then
|
||||
echoerr "Invalid ProDOS name: $prodosPath"; exit 1;
|
||||
fi
|
||||
done
|
||||
IFS="$IFS_orig"
|
||||
|
||||
# process filetype
|
||||
[[ ${3:0:2} == "0x" ]] && ftArg="\$${3:2}" || ftArg="$3"
|
||||
auxType="$4"
|
||||
|
||||
# assume BIN/$2000 if filetype omitted
|
||||
if [[ ! $ftArg ]]; then
|
||||
ft="BIN"
|
||||
auxType="\$2000"
|
||||
# accept hex or decimal number for file type
|
||||
elif [[ ( ${ftArg:0:1} == '$' && ${#ftArg} -eq 3 ) || $(grep [0-9] <<< ${ftArg:0:1}) ]]; then
|
||||
if [[ ${ftArg:0:1} == '$' ]]; then
|
||||
fc=$(tr [:upper:] [:lower:] <<< ${ftArg:1:2})
|
||||
else
|
||||
fc=$(decToHex $ftArg | tr [:upper:] [:lower:])
|
||||
fi
|
||||
P_00=UNK; P_01=BAD; P_02=PCD; P_03=PTX; P_04=TXT; P_05=PDA; P_06=BIN; P_07=FNT; P_08=FOT; P_09=BA3; P_0a=DA3; P_0b=WPF; P_0c=SOS; P_0f=DIR; P_10=RPD; P_11=RPI; P_12=AFD; P_13=AFM; P_14=AFR; P_15=SCL; P_16=PFS; P_19=ADB; P_1a=AWP; P_1b=ASP; P_20=TDM; P_21=IPS; P_22=UPV; P_29=3SD; P_2a=8SC; P_2b=8OB; P_2c=8IC; P_2d=8LD; P_2e=P8C; P_41=OCR; P_42=FTD; P_50=GWP; P_51=GSS; P_52=GDB; P_53=DRW; P_54=GDP; P_55=HMD; P_56=EDU; P_57=STN; P_58=HLP; P_59=COM; P_5a=CFG; P_5b=ANM; P_5c=MUM; P_5d=ENT; P_5e=DVU; P_60=PRE; P_6b=BIO; P_6d=DVR; P_6e=PRE; P_6f=HDV; P_80=GEZ; P_81=GE1; P_82=GEO; P_83=GE3; P_84=GE4; P_85=GE5; P_86=GE6; P_87=GE7; P_88=GE8; P_89=GE9; P_8a=GEA; P_8b=GEB; P_8c=GEC; P_8d=GED; P_8e=GEE; P_8f=GEF; P_a0=WP_; P_ab=GSB; P_ac=TDF; P_ad=BDF; P_b0=SRC; P_b1=OBJ; P_b2=LIB; P_b3=S16; P_b4=RTL; P_b5=EXE; P_b6=STR; P_b7=TSF; P_b8=NDA; P_b9=CDA; P_ba=TOL; P_bb=DRV; P_bc=LDF; P_bd=FST; P_bf=DOC; P_c0=PNT; P_c1=PIC; P_c2=ANI; P_c3=PAL; P_c5=OOG; P_c6=SCR; P_c7=CDV; P_c8=FON; P_c9=FND; P_ca=ICN; P_d5=MUS; P_d6=INS; P_d7=MDI; P_d8=SND; P_db=DBM; P_e0=SHK; P_e2=DTS; P_ee=R16; P_ef=PAS; P_f0=CMD; P_f9=P16; P_fa=INT; P_fb=IVR; P_fc=BAS; P_fd=VAR; P_fe=REL; P_ff=SYS;
|
||||
ftVar="P_$fc";
|
||||
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc";
|
||||
else
|
||||
ft="$ftArg"
|
||||
fi
|
||||
|
||||
# set auxtype to $0801 for Applesoft programs if not specified
|
||||
[[ $ft == "BAS" && ! $auxType ]] && auxType="\$0801"
|
||||
|
||||
# test for absence of stdin [[ -t 0 ]] and if absent use ProDOS name
|
||||
if [[ -t 0 ]]; then
|
||||
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType < $prodosArg 2> $acmdStdErr
|
||||
else
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType 2> $acmdStdErr
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
imageArg="$2"
|
||||
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar "$@" 2> $acmdStdErr
|
||||
|
||||
fi
|
||||
|
||||
helpExit
|
41
setup/adtpro-start
Executable file
41
setup/adtpro-start
Executable file
@ -0,0 +1,41 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# adtpro-start - script to start ADTPro "as a headless daemon", ish
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# don't do anything if ADTPro is already running
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
|
||||
1&>2 echo "ADTPro server is already running."
|
||||
|
||||
else
|
||||
|
||||
# look for eligible USB-to-serial adapter
|
||||
ttyUSB=
|
||||
# if lower USB port
|
||||
if [[ -c /dev/ttyUSBlower ]]; then
|
||||
ttyUSB=ttyUSBlower
|
||||
# if hub in lower port, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
# if hub in upper port with multiple adapters, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
fi
|
||||
|
||||
if [[ $ttyUSB ]]; then
|
||||
echo -n "Please wait..."
|
||||
sudo nohup adtpro.sh headless serial &> /dev/null
|
||||
echo "ok."
|
||||
else
|
||||
1>&2 echo "No USB-to-serial adapter found in the lower USB port, or"
|
||||
1>&2 echo " a hub on the lower USB port, or the lowest-numbered port"
|
||||
1>&2 echo " of a hub on the upper USB port. Not starting ADTPro server."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# don't do anything if ADTPro is already running
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
|
||||
1&>2 echo "ADTPro server is already running."
|
||||
|
||||
else
|
||||
|
||||
# look for eligible USB-to-serial adapter
|
||||
ttyUSB=
|
||||
# if lower USB port
|
||||
if [[ -c /dev/ttyUSBlower ]]; then
|
||||
ttyUSB=ttyUSBlower
|
||||
# if hub in lower port, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
# if hub in upper port with multiple adapters, use lowest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | head -1 | cut -c 6-)
|
||||
fi
|
||||
|
||||
if [[ $ttyUSB ]]; then
|
||||
echo -n "Please wait..."
|
||||
sudo nohup adtpro.sh headless serial &> /dev/null
|
||||
echo "ok."
|
||||
else
|
||||
1>&2 echo "No USB-to-serial adapter found in the lower USB port, or"
|
||||
1>&2 echo " a hub on the lower USB port, or the lowest-numbered port"
|
||||
1>&2 echo " of a hub on the upper USB port. Not starting ADTPro server."
|
||||
fi
|
||||
|
||||
fi
|
155
setup/adtpro.sh
Executable file
155
setup/adtpro.sh
Executable file
@ -0,0 +1,155 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# adtpro.sh - a2cloud wrapper for adtpro
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# This script may have some common history with the similar script found in
|
||||
# ADTPro's source tree. The original may have been written by David Schmidt,
|
||||
# and we should check on that.
|
||||
|
||||
# ADTPro - *nix startup shell script
|
||||
#
|
||||
# Note:
|
||||
# Invoke with the name of the communications button to push
|
||||
# in order to start with that mode active (i.e. './adtpro.sh ethernet')
|
||||
#
|
||||
# You can set two variables here:
|
||||
# 1. $MY_JAVA_HOME - to pick a particular java to run under
|
||||
# 2. $ADTPRO_HOME - to say where you installed ADTPro
|
||||
#
|
||||
# Set default ADTPRO_HOME to be the fully qualified
|
||||
# current working directory.
|
||||
#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.
|
||||
# NOTE: be sure to include a trailing slash on MY_JAVA_HOME,
|
||||
# but not on ADTPRO_HOME.
|
||||
#
|
||||
# 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 -m`
|
||||
|
||||
[[ $1 == "headless" ]] && { headless=1; shift; } || headless=
|
||||
|
||||
if [[ $1 && ( $1 != "serial" && $1 != "ethernet" && $1 != "audio" && $1 != "localhost" ) ]]; then
|
||||
usageExit
|
||||
fi
|
||||
|
||||
# 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/' /usr/local/adtpro/disks/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-2.2pre2-local/arm
|
||||
elif [ "$OS_ARCH" = "i686" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
if [ "$OS_ARCH" = "i386" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/x86_64-unknown-linux-gnu
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# For OSX, use this:
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
if [ "$OS_ARCH" = "powerpc" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.1-7-bins-r2/Mac_OS_X
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/mac-10.5
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Solaris, use this:
|
||||
if [ "$OS" = "SunOS" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/sparc-sun-solaris2.10-32
|
||||
fi
|
||||
|
||||
# Set up the library location.
|
||||
export TWEAK1="-Djava.library.path="
|
||||
export TWEAK=$TWEAK1$ADTPRO_HOME/$RXTXLIB
|
||||
|
||||
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 "Headless operation requires a communication mode (e.g. serial)."
|
||||
usageExit
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
HEADLESS="xvfb-run --auto-servernum "
|
||||
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.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
|
||||
if [ -t 0 ]; then
|
||||
sleep 30
|
||||
fi
|
@ -1,141 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ADTPro - *nix startup shell script
|
||||
#
|
||||
# Note:
|
||||
# Invoke with the name of the communications button to push
|
||||
# in order to start with that mode active (i.e. './adtpro.sh ethernet')
|
||||
#
|
||||
# You can set two variables here:
|
||||
# 1. $MY_JAVA_HOME - to pick a particular java to run under
|
||||
# 2. $ADTPRO_HOME - to say where you installed ADTPro
|
||||
#
|
||||
# Set default ADTPRO_HOME to be the fully qualified
|
||||
# current working directory.
|
||||
#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.
|
||||
# NOTE: be sure to include a trailing slash on MY_JAVA_HOME,
|
||||
# but not on ADTPRO_HOME.
|
||||
#
|
||||
# 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 -m`
|
||||
|
||||
[[ $1 == "headless" ]] && { headless=1; shift; } || headless=
|
||||
|
||||
if [[ $1 && ( $1 != "serial" && $1 != "ethernet" && $1 != "audio" && $1 != "localhost" ) ]]; then
|
||||
usageExit
|
||||
fi
|
||||
|
||||
# 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-2.2pre2-local/arm
|
||||
elif [ "$OS_ARCH" = "i686" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
if [ "$OS_ARCH" = "i386" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/i686-pc-linux-gnu
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/x86_64-unknown-linux-gnu
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# For OSX, use this:
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
if [ "$OS_ARCH" = "powerpc" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.1-7-bins-r2/Mac_OS_X
|
||||
else
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/mac-10.5
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Solaris, use this:
|
||||
if [ "$OS" = "SunOS" ]; then
|
||||
export RXTXLIB=lib/rxtx/rxtx-2.2pre2-local/sparc-sun-solaris2.10-32
|
||||
fi
|
||||
|
||||
# Set up the library location.
|
||||
export TWEAK1="-Djava.library.path="
|
||||
export TWEAK=$TWEAK1$ADTPRO_HOME/$RXTXLIB
|
||||
|
||||
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 "Headless operation requires a communication mode (e.g. serial)."
|
||||
usageExit
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
HEADLESS="xvfb-run --auto-servernum "
|
||||
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.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
|
46
setup/baud
Executable file
46
setup/baud
Executable file
@ -0,0 +1,46 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# baud - user command to change baudrate of current terminal
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
isSystemd=
|
||||
isSysVInit=
|
||||
# If you really want something else, *you* maintain it!
|
||||
if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
|
||||
gettyFile="/etc/systemd/system/getty.target.wants/usbgetty@.service"
|
||||
elif [[ -f /etc/inittab ]]; then
|
||||
gettyFile="/etc/inittab"
|
||||
fi
|
||||
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 -ne 300 && $1 -ne 1200 && $1 -ne 2400 && $1 -ne 4800 && $1 -ne 9600 && $1 -ne 19200 && $1 -ne 38400 && $1 -ne 57600 && $1 -ne 115200 ]]; then
|
||||
echo 'Usage: baud [-d] 300|1200|2400|4800|9600|19200|38400|57600|115200';
|
||||
echo ' -d sets default speed for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
else
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/ttyAMA0 .* /ttyAMA0 $1 /" $gettyFile;
|
||||
sudo sed -i "s/ttyAMA0,[0-9]*/ttyAMA0,$1/g" /boot/cmdline.txt;
|
||||
sudo sed -i "s/\(ttyUSB.*\) .* /\1 $1 /g" $gettyFile;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $(tty | grep tty) ]]; then
|
||||
stty -F $(tty) $1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tput bold)$(tty) current $(stty -a -F $(tty) | grep -o 'speed .* baud')$(tput sgr0)"
|
||||
echo -e "$(tput bold)default speed at login: $(grep scanttyUSB $gettyFile | sed 's/^.*scanttyUSB[^ ]* \(.*\) .*$/\1/') baud$(tput sgr0)"
|
@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 -ne 300 && $1 -ne 1200 && $1 -ne 2400 && $1 -ne 4800 && $1 -ne 9600 && $1 -ne 19200 && $1 -ne 38400 && $1 -ne 57600 && $1 -ne 115200 ]]; then
|
||||
echo 'Usage: baud [-d] 300|1200|2400|4800|9600|19200|38400|57600|115200';
|
||||
echo ' -d sets default speed for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
else
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/ttyAMA0 .* /ttyAMA0 $1 /" /etc/inittab;
|
||||
sudo sed -i "s/ttyAMA0,[0-9]*/ttyAMA0,$1/g" /boot/cmdline.txt;
|
||||
sudo sed -i "s/\(ttyUSB.*\) .* /\1 $1 /g" /etc/inittab;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $(tty | grep tty) ]]; then
|
||||
stty -F $(tty) $1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tput bold)$(tty) current $(stty -a -F $(tty) | grep -o 'speed .* baud')$(tput sgr0)"
|
||||
echo -e "$(tput bold)default speed at login: $(grep ttyUSB /etc/inittab | sed 's/^.*ttyUSB[^ ]* \(.*\) .*$/\1/') baud$(tput sgr0)"
|
1385
setup/cppo
Executable file
1385
setup/cppo
Executable file
File diff suppressed because it is too large
Load Diff
882
setup/cppo.txt
882
setup/cppo.txt
@ -1,882 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""cppo: Copy or catalog one or all files from a ProDOS raw disk image.
|
||||
|
||||
copy all files:
|
||||
cppo [-ad|-e] imagefile target_directory
|
||||
copy one file:
|
||||
cppo [-ad|-e] imagefile /FULL/PRODOS/FILE/PATH target_path
|
||||
catalog image:
|
||||
cppo -cat imagefile
|
||||
|
||||
-ad : Create AppleDouble header files and preserve resource forks.
|
||||
-e : Append ProDOS type and auxtype to filenames, and copy resource
|
||||
forks, for adding to ShrinkIt archives with Nulib2
|
||||
using its -e option.
|
||||
|
||||
Wildcard matching/globbing (*) is not supported.
|
||||
No verification or validation of the disk image is performed.
|
||||
|
||||
(Compatible with Python 2.6 and later, including 3.x.)
|
||||
"""
|
||||
|
||||
# cppo by Ivan X, ivan@ivanx.com, ivanx.com/appleii
|
||||
|
||||
# If anyone's looking at this, and feels it's not sufficiently Pythonic,
|
||||
# I know that. It's pretty much a line-for-line conversion of the original
|
||||
# Bash script. I did start a beautiful from-the-ground-up object-oriented
|
||||
# version, then realized it would be faster to translate it ugly and quick.
|
||||
|
||||
# imports for python 3 code compatibility
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
|
||||
# Intentially fails on pre-2.6 so user can see what's wrong
|
||||
b'ERROR: cppo requires Python 2.6 or later, including 3.x.'
|
||||
|
||||
class Globals(object):
|
||||
pass
|
||||
|
||||
g = Globals()
|
||||
|
||||
g.imageData = b''
|
||||
g.outFileData = bytearray(b'')
|
||||
g.adFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
|
||||
g.activeDirBlock = None
|
||||
g.activeFileName = None
|
||||
g.activeFileSize = None
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
|
||||
g.PDOSPATH = []
|
||||
g.PDOSPATH_INDEX = 0
|
||||
g.PDOSPATH_SEGMENT = None
|
||||
g.DIRPATH = ""
|
||||
|
||||
g.targetName = None
|
||||
g.targetDir = ""
|
||||
g.ADdir = None
|
||||
g.imageFile = None
|
||||
|
||||
g.AD = 0
|
||||
g.EX = 0
|
||||
g.DIR = 0
|
||||
g.silent = 0
|
||||
|
||||
# functions
|
||||
|
||||
def pdosDateToUnixDate(arg1):
|
||||
# input: ProDOS date/time bit sequence string in format:
|
||||
# "yyyyyyymmmmddddd000hhhhh00mmmmmm" (ustr)
|
||||
# output: seconds since Unix epoch (1-Jan-1970),
|
||||
# or current date/time if no ProDOS date
|
||||
year = (binToDec(slyce(arg1,0,7)) + 1900)
|
||||
if (year < 1940): year += 100
|
||||
month = binToDec(slyce(arg1,7,4))
|
||||
day = binToDec(slyce(arg1,11,5))
|
||||
hour = binToDec(slyce(arg1,19,5))
|
||||
minute = binToDec(slyce(arg1,26,6))
|
||||
# print(year, month, day, hour, minute)
|
||||
td = (datetime.datetime(year, month, day, hour, minute) -
|
||||
datetime.datetime(1970,1,1))
|
||||
unixDate_naive = (td.days*24*60*60 + td.seconds)
|
||||
td2 = (datetime.datetime.fromtimestamp(unixDate_naive) -
|
||||
datetime.datetime.utcfromtimestamp(unixDate_naive))
|
||||
utcoffset = (td2.days*24*60*60 + td2.seconds)
|
||||
# print(unixDate_naive - utcoffset)
|
||||
return (unixDate_naive - utcoffset) # local time zone with DST
|
||||
|
||||
def unixDateToADDate(arg1):
|
||||
# input: seconds since Unix epoch (1-Jan-1970 00:00:00 GMT)
|
||||
# output: seconds since Netatalk epoch (1-Jan-2000 00:00:00 GMT),
|
||||
# in hex-ustr (big endian)
|
||||
adDate = (arg1 - 946684800)
|
||||
if (adDate < 0 ):
|
||||
adDate += 4294967296 # to get negative hex number
|
||||
adDateHex = to_hex(adDate).zfill(8).upper()
|
||||
# print(arg1, adDate, adDateHex)
|
||||
return adDateHex
|
||||
|
||||
# cppo support routines:
|
||||
# arg1: directory block
|
||||
# arg2: file index (if applicable)
|
||||
# arg3: directory chunk # (if applicable)
|
||||
|
||||
#most of these not tested yet in Python
|
||||
# returns byte position in disk image file
|
||||
def getStartPos(arg1, arg2):
|
||||
return ( (arg1 * 512) +
|
||||
(39 * ((arg2 + (arg2 > 11)) % 13)) +
|
||||
(4 if (arg2 > 11) else 43) )
|
||||
|
||||
def getStorageType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
return (firstByte//16)
|
||||
|
||||
def getFileName(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+1, nameLength)
|
||||
|
||||
def getFileType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return readcharHex(g.imageData, start+16)
|
||||
|
||||
def getKeyPointer(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+17) +
|
||||
readcharDec(g.imageData, start+18)*256)
|
||||
|
||||
def getFileLength(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+21) +
|
||||
readcharDec(g.imageData, start+22)*256 +
|
||||
readcharDec(g.imageData, start+23)*65536)
|
||||
|
||||
def getAuxType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharHex(g.imageData, start+32) +
|
||||
readcharHex(g.imageData, start+31))
|
||||
|
||||
def getCreationDate(arg1, arg2):
|
||||
#outputs prodos creation date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+25)) +
|
||||
hexToBin(readcharHex(g.imageData, start+24)) +
|
||||
hexToBin(readcharHex(g.imageData, start+27)) +
|
||||
hexToBin(readcharHex(g.imageData, start+26)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getModifiedDate(arg1, arg2):
|
||||
#outputs prodos modified date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+34)) +
|
||||
hexToBin(readcharHex(g.imageData, start+33)) +
|
||||
hexToBin(readcharHex(g.imageData, start+36)) +
|
||||
hexToBin(readcharHex(g.imageData, start+35)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getVolumeName():
|
||||
return getWorkingDirName(2)
|
||||
|
||||
def getWorkingDirName(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
firstByte = readcharDec(g.imageData, start+4)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+5, nameLength)
|
||||
|
||||
def getDirEntryCount(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+37) +
|
||||
readcharDec(g.imageData, start+38)*256)
|
||||
|
||||
def getDirNextChunkPointer(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+2) +
|
||||
readcharDec(g.imageData, start+3)*256)
|
||||
|
||||
# -- script begins in earnest here
|
||||
|
||||
def copyFile(arg1, arg2):
|
||||
g.outFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
g.activeFileBytesCopied = 0
|
||||
storageType = getStorageType(arg1, arg2)
|
||||
keyPointer = getKeyPointer(arg1, arg2)
|
||||
fileLen = getFileLength(arg1, arg2)
|
||||
if (storageType == 1): #seedling
|
||||
copyBlock(keyPointer, fileLen)
|
||||
elif (storageType == 2): #sapling
|
||||
processIndexBlock(keyPointer)
|
||||
elif (storageType == 3): #tree
|
||||
processMasterIndexBlock(keyPointer)
|
||||
elif (storageType == 5): #extended (forked)
|
||||
processForkedFile(keyPointer)
|
||||
|
||||
def copyBlock(arg1, arg2):
|
||||
#arg1: block to copy
|
||||
#arg2: bytes to write (should be 512,
|
||||
# unless final block with less than 512 bytes)
|
||||
#print(arg1 + " " + arg2 + " " + g.activeFileBytesCopied)
|
||||
if (arg1 == 0):
|
||||
outBytes = (b'\x00' * arg2)
|
||||
else:
|
||||
outBytes = slyce(g.imageData, arg1*512, arg2)
|
||||
if (g.resourceFork > 0):
|
||||
if g.AD:
|
||||
g.adFileData[g.activeFileBytesCopied+741:
|
||||
(g.activeFileBytesCopied+741 + arg2)] = outBytes
|
||||
if g.EX:
|
||||
g.exFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
else:
|
||||
g.outFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
g.activeFileBytesCopied += arg2
|
||||
|
||||
def processDir(arg1, arg2=None, arg3=None, arg4=None, arg5=None):
|
||||
# arg1: dirBlock
|
||||
# arg2/3/4/5: for non-key chunks: entryCount, entry#,
|
||||
# workingDirName, processedEntryCount
|
||||
|
||||
entryCount = None
|
||||
e = None
|
||||
pe = None
|
||||
workingDirName = None
|
||||
|
||||
if arg2:
|
||||
entryCount = arg2
|
||||
e = arg3
|
||||
workingDirName = arg4
|
||||
pe = arg5
|
||||
else:
|
||||
e = 0
|
||||
pe = 0
|
||||
entryCount = getDirEntryCount(arg1)
|
||||
workingDirName = getWorkingDirName(arg1).decode("L1")
|
||||
g.DIRPATH = (g.DIRPATH + "/" + workingDirName)
|
||||
if g.PDOSPATH_INDEX:
|
||||
if (g.PDOSPATH_INDEX == 1):
|
||||
if (("/" + g.PDOSPATH_SEGMENT) != g.DIRPATH):
|
||||
print("ProDOS volume name does not match disk image.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
else:
|
||||
print(g.DIRPATH)
|
||||
while (pe < entryCount):
|
||||
if (getStorageType(arg1, e) > 0):
|
||||
processEntry(arg1, e)
|
||||
pe += 1
|
||||
e += 1
|
||||
if not ((e + ( e>11 ) ) % 13):
|
||||
processDir(getDirNextChunkPointer(arg1),
|
||||
entryCount,
|
||||
e,
|
||||
workingDirName,
|
||||
pe)
|
||||
break
|
||||
|
||||
def processEntry(arg1, arg2):
|
||||
'''
|
||||
print(getFileName(arg1, arg2), getStorageType(arg1, arg2),
|
||||
getFileType(arg1, arg2), getKeyPointer(arg1, arg2),
|
||||
getFileLength(arg1, arg2), getAuxType(arg1, arg2),
|
||||
getCreationDate(arg1, arg2), getModifiedDate(arg1, arg2))
|
||||
'''
|
||||
g.activeFileName = getFileName(arg1 ,arg2).decode("L1")
|
||||
g.activeFileSize = getFileLength(arg1, arg2)
|
||||
|
||||
if ((not g.PDOSPATH_INDEX) or (g.activeFileName == g.PDOSPATH_SEGMENT)):
|
||||
|
||||
if (getStorageType(arg1, arg2) == 13): # if ProDOS directory
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = (g.targetDir + "/" + g.activeFileName)
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not (g.DIR or os.path.isdir(g.targetDir)):
|
||||
makedirs(g.targetDir)
|
||||
if not (g.DIR or (not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
processDir(getKeyPointer(arg1, arg2))
|
||||
g.DIRPATH = g.DIRPATH.rsplit("/", 1)[0]
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = g.targetDir.rsplit("/", 1)[0]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
else: # if ProDOS file
|
||||
if not g.PDOSPATH_INDEX:
|
||||
print(" " + g.activeFileName)
|
||||
if g.DIR:
|
||||
return
|
||||
if not g.targetName:
|
||||
g.targetName = g.activeFileName
|
||||
if g.EX:
|
||||
eTargetName = (g.targetName + "#" +
|
||||
getFileType(arg1, arg2).lower() +
|
||||
getAuxType(arg1, arg2).lower())
|
||||
touch(g.targetDir + "/" + g.targetName)
|
||||
if g.AD: makeADfile()
|
||||
copyFile(arg1, arg2)
|
||||
saveFile((g.targetDir + "/" + g.targetName), g.outFileData)
|
||||
creationDate = getCreationDate(arg1, arg2)
|
||||
modifiedDate = getModifiedDate(arg1, arg2)
|
||||
if (creationDate is None and modifiedDate is not None):
|
||||
creationDate = modifiedDate
|
||||
elif (creationDate is not None and modifiedDate is None):
|
||||
modifiedDate = creationDate
|
||||
elif (creationDate is None and modifiedDate is None):
|
||||
creationDate = (datetime.datetime.today() -
|
||||
datetime.datetime(1970,1,1)).days*24*60*60
|
||||
modifiedDate = creationDate
|
||||
if g.AD: # AppleDouble
|
||||
# set dates
|
||||
ADfilePath = (g.ADdir + "/" + g.targetName)
|
||||
writecharsHex(g.adFileData,
|
||||
637,
|
||||
(unixDateToADDate(creationDate) +
|
||||
unixDateToADDate(modifiedDate)))
|
||||
writecharHex(g.adFileData, 645, "80")
|
||||
writecharHex(g.adFileData, 649, "80")
|
||||
#set type/creator
|
||||
writechars(g.adFileData, 653, b'p')
|
||||
writecharsHex(g.adFileData,
|
||||
654,
|
||||
(getFileType(arg1, arg2) +
|
||||
getAuxType(arg1, arg2)))
|
||||
writechars(g.adFileData, 657, b'pdos')
|
||||
saveFile(ADfilePath, g.adFileData)
|
||||
touch((g.targetDir + "/" + g.targetName), modifiedDate)
|
||||
if g.EX: # extended name
|
||||
os.rename((g.targetDir + "/" + g.targetName),
|
||||
(g.targetDir + "/" + eTargetName))
|
||||
if (len(g.exFileData) > 0):
|
||||
saveFile((g.targetDir + "/" + eTargetName + "r"),
|
||||
g.exFileData)
|
||||
touch((g.targetDir + "/" + eTargetName + "r"),
|
||||
modifiedDate)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
syncExit()
|
||||
g.targetName = None
|
||||
|
||||
#else:
|
||||
#print(g.activeFileName + " doesn't match " + g.PDOSPATH_SEGMENT)
|
||||
|
||||
def processForkedFile(arg1):
|
||||
# finder info except type/creator
|
||||
fInfoA_entryType = readcharDec(g.imageData, 9)
|
||||
fInfoB_entryType = readcharDec(g.imageData, 27)
|
||||
if (fInfoA_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 18, 8))
|
||||
elif (fInfoA_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 10, 16))
|
||||
if (fInfoB_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 36, 8))
|
||||
elif (fInfoB_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 28, 16))
|
||||
|
||||
for f in [0, 256]:
|
||||
g.resourceFork = f
|
||||
g.activeFileBytesCopied = 0
|
||||
forkStart = (arg1 * 512) # start of Forked File key block
|
||||
# print("--" + forkStart)
|
||||
forkStorageType = readcharDec(g.imageData, forkStart+f+0)
|
||||
forkKeyPointer = (readcharDec(g.imageData, forkStart+f+1) +
|
||||
readcharDec(g.imageData, forkStart+f+2)*256)
|
||||
forkFileLen = (readcharDec(g.imageData, forkStart+f+5) +
|
||||
readcharDec(g.imageData, forkStart+f+6)*256 +
|
||||
readcharDec(g.imageData, forkStart+f+7)*256*256)
|
||||
g.activeFileSize = forkFileLen
|
||||
if (g.resourceFork > 0):
|
||||
rsrcForkLenHex = (readcharHex(g.imageData, forkStart+f+7) +
|
||||
readcharHex(g.imageData, forkStart+f+6) +
|
||||
readcharHex(g.imageData, forkStart+f+5))
|
||||
# print(">>>" + rsrcForkLenHex)
|
||||
print(" [resource fork]")
|
||||
if g.AD:
|
||||
writecharsHex(g.adFileData, 35, rsrcForkLenHex)
|
||||
else:
|
||||
print(" [data fork]")
|
||||
if (forkStorageType == 1): #seedling
|
||||
copyBlock(forkKeyPointer, forkFileLen)
|
||||
elif (forkStorageType == 2): #sapling
|
||||
processIndexBlock(forkKeyPointer)
|
||||
elif (forkStorageType == 3): #tree
|
||||
processMasterIndexBlock(forkKeyPointer)
|
||||
# print()
|
||||
g.resourceFork = 0
|
||||
|
||||
def processMasterIndexBlock(arg1):
|
||||
processIndexBlock(arg1, True)
|
||||
|
||||
def processIndexBlock(arg1, arg2=False):
|
||||
#arg1: indexBlock
|
||||
#arg2: if True, it's a Master Index Block
|
||||
pos = 0
|
||||
bytesRemaining = g.activeFileSize
|
||||
while (g.activeFileBytesCopied < g.activeFileSize):
|
||||
targetBlock = (readcharDec(g.imageData, arg1*512+pos) +
|
||||
readcharDec(g.imageData, arg1*512+(pos+256))*256)
|
||||
if arg2:
|
||||
processIndexBlock(targetBlock)
|
||||
else:
|
||||
bytesRemaining = (g.activeFileSize - g.activeFileBytesCopied)
|
||||
bs = (bytesRemaining if (bytesRemaining < 512) else 512)
|
||||
copyBlock(targetBlock, bs)
|
||||
pos += 1
|
||||
if (pos > 255):
|
||||
break # go to next entry in Master Index Block (tree)
|
||||
|
||||
def makeADfile():
|
||||
if not g.AD: return
|
||||
touch(g.ADdir + "/" + g.targetName)
|
||||
g.adFileData = bytearray(b'\x00' * 741)
|
||||
# ADv2 header
|
||||
writecharsHex(g.adFileData, hexToDec("00"), "0005160700020000")
|
||||
# number of entries
|
||||
writecharsHex(g.adFileData, hexToDec("18"), "000D")
|
||||
# Resource Fork
|
||||
writecharsHex(g.adFileData, hexToDec("1A"), "00000002000002E500000000")
|
||||
# Real Name
|
||||
writecharsHex(g.adFileData, hexToDec("26"), "00000003000000B600000000")
|
||||
# Comment
|
||||
writecharsHex(g.adFileData, hexToDec("32"), "00000004000001B500000000")
|
||||
# Dates Info
|
||||
writecharsHex(g.adFileData, hexToDec("3E"), "000000080000027D00000010")
|
||||
# Finder Info
|
||||
writecharsHex(g.adFileData, hexToDec("4A"), "000000090000028D00000020")
|
||||
# ProDOS file info
|
||||
writecharsHex(g.adFileData, hexToDec("56"), "0000000B000002C100000008")
|
||||
# AFP short name
|
||||
writecharsHex(g.adFileData, hexToDec("62"), "0000000D000002B500000000")
|
||||
# AFP File Info
|
||||
writecharsHex(g.adFileData, hexToDec("6E"), "0000000E000002B100000004")
|
||||
# AFP Directory ID
|
||||
writecharsHex(g.adFileData, hexToDec("7A"), "0000000F000002AD00000004")
|
||||
# dbd (second time) will create DEV, INO, SYN, SV~
|
||||
|
||||
def syncExit():
|
||||
if (not g.silent and g.AD and os.path.isdir("/usr/local/etc/netatalk")):
|
||||
print("File(s) have been copied to the target directory. " +
|
||||
"If the directory")
|
||||
print("is shared by Netatalk, please type 'afpsync' now.")
|
||||
# saveFile(g.imageFile, g.imageData)
|
||||
sys.exit(0)
|
||||
|
||||
def usage():
|
||||
print(sys.modules[__name__].__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
# --- ID bashbyter functions (adapted)
|
||||
|
||||
def decToHex(arg1):
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex string from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def hexToDec(arg1):
|
||||
# converts single-byte hexadecimal value to decimal equivalent
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: decimal value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def hexToBin(arg1):
|
||||
# converts single-byte hexadecimal value to binary string
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: binary string value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bin(arg1).zfill(8)
|
||||
|
||||
def binToDec(arg1):
|
||||
# converts single-byte binary string (8 bits) value to decimal
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: decimal value
|
||||
return to_dec([arg1])
|
||||
|
||||
def binToHex(arg1):
|
||||
# converts single-byte binary string (8 bits) value to hex
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: hex value
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def charToDec(arg1):
|
||||
# converts single char (of type bytes) to corresponding decimal value
|
||||
# arg: one char (of type bytes)
|
||||
# out: decimal value from 0-255
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def charToHex(arg1):
|
||||
# converts single char (of type bytes) to corresponding hex value
|
||||
# arg: one char (of type bytes)
|
||||
# out: hexadecimal value from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def decToChar(arg1):
|
||||
# converts single-byte decimal value to equivalent char (of type bytes)
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_bytes(arg1)
|
||||
|
||||
def hexToChar(arg1):
|
||||
# converts single-byte hex value to corresponding char (of type bytes)
|
||||
# arg: two-digit hexadecimal number from 00-FF
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bytes(arg1)
|
||||
|
||||
def readchars(arg1, arg2=0, arg3=0):
|
||||
# read one or more characters from a bytes variable
|
||||
# arg1: bytes or bytearray variable
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is to end of bytes var)
|
||||
# out: sequence of characters (bytes or bytearray)
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if (arg3<0): sys.exit(23)
|
||||
if (arg3 == 0):
|
||||
arg3 = len(arg1)
|
||||
return slyce(arg1, arg2, arg3)
|
||||
|
||||
def readcharDec(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to equivalent dec value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_dec(slyce(arg1, arg2, 1))
|
||||
|
||||
def readcharHex(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to corresponding hex value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_hex(slyce(arg1, arg2, 1))
|
||||
|
||||
def writechars(arg1, arg2, arg3):
|
||||
# write one or more characters (bytes) to bytearray
|
||||
# arg1: bytearray variable
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: sequence of bytes (or bytearray)
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not (isinstance(arg3, bytes) or isinstance(arg3, bytearray)):
|
||||
sys.exit(23)
|
||||
arg1[arg2:arg2+len(arg3)] = arg3
|
||||
|
||||
def writecharDec(arg1, arg2, arg3):
|
||||
# write corresponding char of single-byte decimal value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: decimal number from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
# out: nothing
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isnumber(arg3): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharHex(arg1, arg2, arg3):
|
||||
# write corresponding character of single-byte hex value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: two-digit hexadecimal number from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharsHex(arg1, arg2, arg3):
|
||||
# write corresponding characters of hex values into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+len(to_bytes(arg3))] = to_bytes(arg3)
|
||||
|
||||
#---- IvanX general purpose functions ----#
|
||||
|
||||
def slyce(val, start_pos=0, length=1, reverse=False):
|
||||
"""returns slice of object (but not a slice object)
|
||||
allows specifying length, and 3.x "bytes" consistency"""
|
||||
the_slyce = val[start_pos:start_pos+length]
|
||||
return (the_slyce[::-1] if reverse else the_slyce)
|
||||
|
||||
def to_hex(val):
|
||||
"""convert bytes, decimal number, or [bin-ustr] to two-digit hex values
|
||||
unlike hex(), accepts bytes; has no leading 0x or trailing L"""
|
||||
from binascii import b2a_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = int(val[0], 2)
|
||||
if isinstance(val, bytes): # bytes
|
||||
return b2a_hex(val).decode("L1")
|
||||
elif isnumber(val):
|
||||
# .encode().decode() always returns unicode in both P2 and P3
|
||||
return (hex(val)[2:].split("L")[0]).encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_hex() requires bytes, int/long, or [bin-ustr]")
|
||||
|
||||
def hex_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce as hex-ustr"""
|
||||
return to_hex(slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def dec_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to decimal int/long"""
|
||||
return to_dec(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def bin_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to bin-ustr"""
|
||||
return to_bin(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def to_dec(val):
|
||||
"""convert bytes, hex-ustr or [bin-ustr] to decimal int/long"""
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
return int(val[0], 2)
|
||||
elif isinstance(val, bytes): # bytes
|
||||
return int(to_hex(val), 16)
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return int(val, 16)
|
||||
else:
|
||||
raise Exception("to_dec() requires bytes, hex-ustr or [bin-ustr]")
|
||||
|
||||
def to_bin(val):
|
||||
"""convert bytes, hex-ustr, or int/long to bin-ustr"""
|
||||
if isinstance(val, bytes): # bytes
|
||||
return (bin(to_dec(to_hex(val))))[2:].encode("L1").decode("L1")
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return (bin(int(val, 16)))[2:].encode("L1").decode("L1")
|
||||
elif isnumber(val): # int/long
|
||||
return (bin(val))[2:].encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_bin() requires bytes, hex-ustr, or int/long")
|
||||
|
||||
def to_bytes(val):
|
||||
"""converts hex-ustr, int/long, or [bin-ustr] to bytes"""
|
||||
from binascii import a2b_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = to_hex(val[0])
|
||||
if isnumber(val): # int/long
|
||||
val = to_hex(val)
|
||||
if isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return a2b_hex(bytes(val.encode("L1"))) # works on both P2 and P3
|
||||
else:
|
||||
raise Exception(
|
||||
"to_bytes() requires hex-ustr, int/long, or [bin-ustr]")
|
||||
|
||||
def shift(items):
|
||||
"""Shift list items to left, losing the first item.
|
||||
|
||||
in : list
|
||||
out: list
|
||||
"""
|
||||
for i in range(0, (len(items)-1)):
|
||||
items[i] = items[i+1]
|
||||
del items[-1]
|
||||
return items
|
||||
|
||||
def s(string):
|
||||
"""Perform local variable substution, e.g. 'total: {num} items'"""
|
||||
# http://stackoverflow.com/questions/2960772/
|
||||
# putting-a-variable-inside-a-string-python
|
||||
# http://stackoverflow.com/questions/6618795/
|
||||
# get-locals-from-calling-namespace-in-python
|
||||
import inspect
|
||||
frame = inspect.currentframe()
|
||||
try:
|
||||
rVal = string.format(**frame.f_back.f_locals)
|
||||
finally:
|
||||
del frame
|
||||
return rVal
|
||||
|
||||
def get_object_names(cls, include_subclasses=True):
|
||||
object_names = []
|
||||
for (this_object_name, this_object_id) in list(globals().items()):
|
||||
if include_subclasses:
|
||||
if isinstance(this_object_id, cls):
|
||||
object_names.append(this_object_name)
|
||||
else:
|
||||
if type(this_object_id) is cls:
|
||||
object_names.append(this_object_name)
|
||||
return object_names
|
||||
|
||||
def touch(filePath, modTime=None):
|
||||
# http://stackoverflow.com/questions/1158076/implement-touch-using-python
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "ab"):
|
||||
os.utime(filePath, (None if (modTime is None) else (modTime, modTime)))
|
||||
|
||||
def mkdir(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.mkdir(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def makedirs(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.makedirs(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def loadFile(filePath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "rb") as imageHandle:
|
||||
return imageHandle.read()
|
||||
|
||||
def saveFile(filePath, fileData):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "wb") as imageHandle:
|
||||
imageHandle.write(fileData)
|
||||
|
||||
def isnumber(number):
|
||||
try: # make sure it's not a string
|
||||
len(number)
|
||||
return False
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
int(number)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
#---- end IvanX general purpose functions ----#
|
||||
|
||||
|
||||
# --- start
|
||||
|
||||
args = sys.argv
|
||||
if (len(args) == 1):
|
||||
usage()
|
||||
|
||||
if (args[1] == "-s"):
|
||||
g.silent=1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-ad"):
|
||||
g.AD = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-e"):
|
||||
if g.AD: usage()
|
||||
g.EX = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-cat"):
|
||||
g.DIR = 1
|
||||
args = args[1:]
|
||||
|
||||
if not ((g.DIR and len(args) >= 2) or (len(args) >= 3)):
|
||||
usage()
|
||||
if ((len(args) == 4) and
|
||||
(slyce(args[2],0,1) != "/") and
|
||||
(slyce(args[2],0,1) != ":")):
|
||||
usage()
|
||||
|
||||
g.imageFile = args[1]
|
||||
if not os.path.isfile(g.imageFile):
|
||||
print("Source " + g.imageFile + " was not found.")
|
||||
sys.exit(2)
|
||||
g.imageData = loadFile(g.imageFile)
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = args[2].upper()
|
||||
targetPath = args[3]
|
||||
if os.path.isdir(targetPath):
|
||||
g.targetDir = targetPath
|
||||
else:
|
||||
g.targetDir = targetPath.rsplit("/", 1)[0]
|
||||
g.targetName = targetPath.rsplit("/", 1)[1]
|
||||
if not os.path.isdir(g.targetDir):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
if not os.path.isdir(args[2]):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
|
||||
g.activeDirBlock = 0
|
||||
g.activeFileName = ""
|
||||
g.activeFileSize = 0
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
g.PDOSPATH_INDEX = 0
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = g.PDOSPATH.replace(':', '/').split('/')
|
||||
if not g.PDOSPATH[0]:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
mkdir(g.ADdir)
|
||||
processDir(2)
|
||||
print("ProDOS file not found within image file.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
# print(args[0], args[1], args[2])
|
||||
g.targetDir = (args[2] + "/" + getVolumeName().decode("L1"))
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not os.path.isdir(g.targetDir):
|
||||
makedirs(g.targetDir)
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
processDir(2)
|
||||
if not g.DIR:
|
||||
syncExit()
|
||||
|
88
setup/dopo
Executable file
88
setup/dopo
Executable file
@ -0,0 +1,88 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# dopo - Swap sectors on Apple II disk image between DOS and ProDOS ordering
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# follows gzip syntax -- acts in place if filename provided, outputs to
|
||||
# stdout with -c, accepts stdin and outputs to stdout if filename is - or absent
|
||||
|
||||
# output to stdout?
|
||||
if [[ "$1" == "-c" ]]; then
|
||||
shift;
|
||||
stdout=1;
|
||||
else
|
||||
stdout=
|
||||
fi
|
||||
|
||||
# use stdin?
|
||||
if [[ ! $1 || "$1" == "-" ]]; then
|
||||
stdin=1
|
||||
stdout=1
|
||||
elif [[ $1 && ! -f "$1" ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename] 1>&2";
|
||||
exit 1;
|
||||
else
|
||||
stdin=
|
||||
fi
|
||||
|
||||
if [[ ! $stdout ]]; then
|
||||
#get filename extension, in lowercase
|
||||
f="$(tr [:upper:] [:lower:] <<< ${1##*.})";
|
||||
|
||||
#if it's dsk/do/po, get name without extension
|
||||
[[ "$f" == "dsk" || "$f" == "do" || "$f" == "po" ]] && of="${1%.*}" || of="$1";
|
||||
|
||||
#if name had .po extension, append .dsk to outfile name, otherwise append .po
|
||||
[[ "$f" == "po" ]] && of="$of.dsk" || of="$of.po"
|
||||
|
||||
# set outfile param for dd
|
||||
ofile="$of"
|
||||
else
|
||||
ofile="/tmp/$$.dopo_out"
|
||||
fi
|
||||
|
||||
if [[ ! $stdin ]]; then
|
||||
# set infile param for dd
|
||||
ifile="$1"
|
||||
elif [[ -t 0 ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename]" 1>&2; exit 1;
|
||||
else
|
||||
ifile="/tmp/$$.dopo_in"
|
||||
cat > "$ifile"
|
||||
fi
|
||||
|
||||
# verify file is 140K by successfully reading 140K'th byte, and failing to read the one past
|
||||
[[ $(dd if="$ifile" of=/dev/null bs=1 skip=143359 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 1 || $(dd if="$ifile" of=/dev/null bs=1 skip=143360 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 0 ]] && badInput=1 || badInput=
|
||||
|
||||
if [[ $badInput ]]; then
|
||||
if [[ ! $stdin ]]; then
|
||||
echo -n "$1 doesn't appear to be a 140K image. Continue? " 1>&2;
|
||||
read
|
||||
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]] || exit 1;
|
||||
else
|
||||
echo "warning: Input file doesn't appear to be a 140K image." 1>&2
|
||||
echo " Output file is likely to be useless." 1>&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# for each track
|
||||
for t in {0..34}; do
|
||||
# read each sector in the right sequence to make (or unmake)
|
||||
# valid ProDOS blocks (sector pairs)
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
# copy the sector from the old file to the new one
|
||||
dd if="$ifile" of="$ofile" bs=256 count=1 skip=$(( t*16 + s )) seek=$(( t*16 + (s==0 || s==15 ? s : 15-s) )) 2> /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
# remove the old one
|
||||
[[ ! $stdin && ! $stdout ]] && rm "$1" &> /dev/null
|
||||
|
||||
# dump to stdout if -c or stdin used
|
||||
[[ $stdout ]] && { cat $ofile; rm $ofile &> /dev/null; }
|
||||
[[ $stdin ]] && rm $ifile &> /dev/null;
|
@ -1,80 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# follows gzip syntax -- acts in place if filename provided, outputs to
|
||||
# stdout with -c, accepts stdin and outputs to stdout if filename is - or absent
|
||||
|
||||
# output to stdout?
|
||||
if [[ "$1" == "-c" ]]; then
|
||||
shift;
|
||||
stdout=1;
|
||||
else
|
||||
stdout=
|
||||
fi
|
||||
|
||||
# use stdin?
|
||||
if [[ ! $1 || "$1" == "-" ]]; then
|
||||
stdin=1
|
||||
stdout=1
|
||||
elif [[ $1 && ! -f "$1" ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename] 1>&2";
|
||||
exit 1;
|
||||
else
|
||||
stdin=
|
||||
fi
|
||||
|
||||
if [[ ! $stdout ]]; then
|
||||
#get filename extension, in lowercase
|
||||
f="$(tr [:upper:] [:lower:] <<< ${1##*.})";
|
||||
|
||||
#if it's dsk/do/po, get name without extension
|
||||
[[ "$f" == "dsk" || "$f" == "do" || "$f" == "po" ]] && of="${1%.*}" || of="$1";
|
||||
|
||||
#if name had .po extension, append .dsk to outfile name, otherwise append .po
|
||||
[[ "$f" == "po" ]] && of="$of.dsk" || of="$of.po"
|
||||
|
||||
# set outfile param for dd
|
||||
ofile="$of"
|
||||
else
|
||||
ofile="/tmp/$$.dopo_out"
|
||||
fi
|
||||
|
||||
if [[ ! $stdin ]]; then
|
||||
# set infile param for dd
|
||||
ifile="$1"
|
||||
elif [[ -t 0 ]]; then
|
||||
echo "usage: dopo [-c] [-|140KdiskImageFilename]" 1>&2; exit 1;
|
||||
else
|
||||
ifile="/tmp/$$.dopo_in"
|
||||
cat > "$ifile"
|
||||
fi
|
||||
|
||||
# verify file is 140K by successfully reading 140K'th byte, and failing to read the one past
|
||||
[[ $(dd if="$ifile" of=/dev/null bs=1 skip=143359 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 1 || $(dd if="$ifile" of=/dev/null bs=1 skip=143360 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 0 ]] && badInput=1 || badInput=
|
||||
|
||||
if [[ $badInput ]]; then
|
||||
if [[ ! $stdin ]]; then
|
||||
echo -n "$1 doesn't appear to be a 140K image. Continue? " 1>&2;
|
||||
read
|
||||
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]] || exit 1;
|
||||
else
|
||||
echo "warning: Input file doesn't appear to be a 140K image." 1>&2
|
||||
echo " Output file is likely to be useless." 1>&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# for each track
|
||||
for t in {0..34}; do
|
||||
# read each sector in the right sequence to make (or unmake)
|
||||
# valid ProDOS blocks (sector pairs)
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
# copy the sector from the old file to the new one
|
||||
dd if="$ifile" of="$ofile" bs=256 count=1 skip=$(( t*16 + s )) seek=$(( t*16 + (s==0 || s==15 ? s : 15-s) )) 2> /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
# remove the old one
|
||||
[[ ! $stdin && ! $stdout ]] && rm "$1" &> /dev/null
|
||||
|
||||
# dump to stdout if -c or stdin used
|
||||
[[ $stdout ]] && { cat $ofile; rm $ofile &> /dev/null; }
|
||||
[[ $stdin ]] && rm $ifile &> /dev/null;
|
132
setup/dos2pro
Executable file
132
setup/dos2pro
Executable file
@ -0,0 +1,132 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# dos2pro - extract files from DOS 3.3 image and convert to ProDOS
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
readcharDec () {
|
||||
# read one character from file & convert to equivalent decimal value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
### start
|
||||
|
||||
usage () {
|
||||
echo "Usage:"
|
||||
echo "all files: dos2pro dosImageName"
|
||||
echo "one file : dos2pro dosImageName DOSFILE"
|
||||
echo "notes:"
|
||||
echo " Wildcard matching (*) is not supported."
|
||||
echo " Illegal prodos characters will be made into periods, and names"
|
||||
echo " will be truncated at 15 characters and possibly overwrite"
|
||||
echo " other files if they match a previous name conversion."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $1 == "-h" || $1 == "--help" || ! $1 || ! -f "$1" ]] && usage
|
||||
|
||||
dosImage="$1"
|
||||
fileName="$2"
|
||||
|
||||
dosImageBasename=$(basename "$dosImage")
|
||||
proImage="${dosImageBasename%.*}_prodos.po"
|
||||
|
||||
if [[ ! -f "$proImage" ]]; then
|
||||
echo "Creating $proImage..."
|
||||
mkpo -b 280 "$proImage"
|
||||
else
|
||||
echo "Found $proImage..."
|
||||
fi
|
||||
|
||||
if [[ ! $(acmd -i "$dosImage" 2> /dev/null | grep "Disk Format: DOS 3.3") ]]; then
|
||||
echo "The file '$dosImage' doesn't appear to be a DOS 3.3 disk image."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dosLines=$(acmd -ll "$dosImage")
|
||||
|
||||
IFS=''
|
||||
while read thisLine; do
|
||||
if [[ ${thisLine:0:2} == "* " || ${thisLine:0:2} == " " ]]; then
|
||||
dosName=$(cut -c 5- <<< $thisLine | rev | sed 's/^[^ ]* [^ ]* [^ ]* [^ ]* [^ ]* \(.*$\)/\1/' | rev)
|
||||
if [[ ! $fileName || "$fileName" == "$dosName" ]]; then
|
||||
|
||||
dosType=$(cut -c 3 <<< $thisLine)
|
||||
if [[ $dosType == "A" ]]; then
|
||||
proType="BAS"
|
||||
binAddr="0801"
|
||||
elif [[ $dosType == "I" ]]; then
|
||||
proType="INT"
|
||||
elif [[ $dosType == "T" ]]; then
|
||||
proType="TXT"
|
||||
elif [[ $dosType == "B" ]]; then
|
||||
proType="BIN"
|
||||
sector=$(rev <<< $thisLine | cut -f2 -d ' ' | rev | cut -c 2-)
|
||||
track=$(rev <<< $thisLine | cut -f3 -d ' ' | rev | cut -c 2-)
|
||||
offset=$(( (track * 16 + sector) * 256 + 12 ))
|
||||
track=$(readcharDec "$dosImage" $offset)
|
||||
sector=$(readcharDec "$dosImage" $((offset+1)))
|
||||
offset=$(( (track * 16 + sector) * 256 ))
|
||||
binAddr=$(readcharHex "$dosImage" $((offset+1)))$(readcharHex "$dosImage" $offset)
|
||||
else
|
||||
echo "Error: Unknown DOS 3.3 file type."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
proName=$(sed 's/^[^A-Za-z]/A/' <<< $dosName | sed 's/[^A-Za-z0-9\.]/./g')
|
||||
|
||||
auxType=
|
||||
[[ $binAddr ]] && auxType="\$$binAddr"
|
||||
echo "Copying '$dosName' to '$proName'"
|
||||
acmd -g "$dosImage" "$dosName" - | acmd -p "$proImage" "$proName" "$proType" "$auxType"
|
||||
filesCopied=1
|
||||
fi
|
||||
fi
|
||||
done <<< $dosLines
|
||||
|
||||
if [[ ! $filesCopied ]]; then
|
||||
if [[ $fileName ]]; then
|
||||
echo "File '$fileName' not found on DOS 3.3 disk image."
|
||||
else
|
||||
echo "No files copied."
|
||||
fi
|
||||
fi
|
@ -1,124 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
readcharDec () {
|
||||
# read one character from file & convert to equivalent decimal value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
### start
|
||||
|
||||
usage () {
|
||||
echo "Usage:"
|
||||
echo "all files: dos2pro dosImageName"
|
||||
echo "one file : dos2pro dosImageName DOSFILE"
|
||||
echo "notes:"
|
||||
echo " Wildcard matching (*) is not supported."
|
||||
echo " Illegal prodos characters will be made into periods, and names"
|
||||
echo " will be truncated at 15 characters and possibly overwrite"
|
||||
echo " other files if they match a previous name conversion."
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $1 == "-h" || $1 == "--help" || ! $1 || ! -f "$1" ]] && usage
|
||||
|
||||
dosImage="$1"
|
||||
fileName="$2"
|
||||
|
||||
dosImageBasename=$(basename "$dosImage")
|
||||
proImage="${dosImageBasename%.*}_prodos.po"
|
||||
|
||||
if [[ ! -f "$proImage" ]]; then
|
||||
echo "Creating $proImage..."
|
||||
mkpo -b 280 "$proImage"
|
||||
else
|
||||
echo "Found $proImage..."
|
||||
fi
|
||||
|
||||
if [[ ! $(acmd -i "$dosImage" 2> /dev/null | grep "Disk Format: DOS 3.3") ]]; then
|
||||
echo "The file '$dosImage' doesn't appear to be a DOS 3.3 disk image."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dosLines=$(acmd -ll "$dosImage")
|
||||
|
||||
IFS=''
|
||||
while read thisLine; do
|
||||
if [[ ${thisLine:0:2} == "* " || ${thisLine:0:2} == " " ]]; then
|
||||
dosName=$(cut -c 5- <<< $thisLine | rev | sed 's/^[^ ]* [^ ]* [^ ]* [^ ]* [^ ]* \(.*$\)/\1/' | rev)
|
||||
if [[ ! $fileName || "$fileName" == "$dosName" ]]; then
|
||||
|
||||
dosType=$(cut -c 3 <<< $thisLine)
|
||||
if [[ $dosType == "A" ]]; then
|
||||
proType="BAS"
|
||||
binAddr="0801"
|
||||
elif [[ $dosType == "I" ]]; then
|
||||
proType="INT"
|
||||
elif [[ $dosType == "T" ]]; then
|
||||
proType="TXT"
|
||||
elif [[ $dosType == "B" ]]; then
|
||||
proType="BIN"
|
||||
sector=$(rev <<< $thisLine | cut -f2 -d ' ' | rev | cut -c 2-)
|
||||
track=$(rev <<< $thisLine | cut -f3 -d ' ' | rev | cut -c 2-)
|
||||
offset=$(( (track * 16 + sector) * 256 + 12 ))
|
||||
track=$(readcharDec "$dosImage" $offset)
|
||||
sector=$(readcharDec "$dosImage" $((offset+1)))
|
||||
offset=$(( (track * 16 + sector) * 256 ))
|
||||
binAddr=$(readcharHex "$dosImage" $((offset+1)))$(readcharHex "$dosImage" $offset)
|
||||
else
|
||||
echo "Error: Unknown DOS 3.3 file type."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
proName=$(sed 's/^[^A-Za-z]/A/' <<< $dosName | sed 's/[^A-Za-z0-9\.]/./g')
|
||||
|
||||
auxType=
|
||||
[[ $binAddr ]] && auxType="\$$binAddr"
|
||||
echo "Copying '$dosName' to '$proName'"
|
||||
acmd -g "$dosImage" "$dosName" - | acmd -p "$proImage" "$proName" "$proType" "$auxType"
|
||||
filesCopied=1
|
||||
fi
|
||||
fi
|
||||
done <<< $dosLines
|
||||
|
||||
if [[ ! $filesCopied ]]; then
|
||||
if [[ $fileName ]]; then
|
||||
echo "File '$fileName' not found on DOS 3.3 disk image."
|
||||
else
|
||||
echo "No files copied."
|
||||
fi
|
||||
fi
|
112
setup/gsport
Executable file
112
setup/gsport
Executable file
@ -0,0 +1,112 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# gsport - a2cloud wrapper for the GSPort emulator
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
if [[ -f /tmp/no-gsport ]]; then
|
||||
echo
|
||||
echo "Your system needs to be rebooted before you can use GSport."
|
||||
echo -n "Do you want to reboot now? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
sudo shutdown -r now
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run GSport on the console, or in an X Window."
|
||||
else
|
||||
|
||||
if [[ -f /usr/local/lib/ROM ]]; then
|
||||
if [[ ! $(grep snd-pcm-oss /etc/modules) ]]; then
|
||||
echo "Configuring GSport sound..."
|
||||
echo "snd-pcm-oss" | sudo tee -a /etc/modules > /dev/null
|
||||
[[ ! $(lsmod | grep snd_pcm_oss) ]] && sudo modprobe snd-pcm-oss
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l xfonts-base 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport fonts..."
|
||||
sudo apt-get -y update
|
||||
touch /tmp/updated
|
||||
sudo apt-get -y install xfonts-base &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l libpcap0.8-dev 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport networking..."
|
||||
[[ ! -f /tmp/updated ]] && sudo apt-get -y update
|
||||
sudo apt-get -y install libpcap0.8-dev &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
rm /tmp/updated &> /dev/null
|
||||
else
|
||||
gsport-setup
|
||||
[[ $? -ne 0 ]] && exit 1
|
||||
fi
|
||||
|
||||
displayOK=
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
displayOK=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /usr/local/etc/gsportconsolewarningoff ]] && { dpkg -l | grep -q -i virtualbox; }; then
|
||||
echo
|
||||
echo "If you have difficulties moving the mouse in GS/OS, choose"
|
||||
echo "'Disable Mouse Integration' from the Machine menu. To free the mouse"
|
||||
echo "from the virtual machine, press the Host key (shown in the lower right"
|
||||
echo "corner of the virtual machine window)."
|
||||
echo
|
||||
echo "Press alt-F4 to exit GSport."
|
||||
echo
|
||||
echo "Press return to continue,"
|
||||
echo -n " or type 'OK' if you want to stop seeing this message: "
|
||||
read
|
||||
if [[ $REPLY == "ok" || $REPLY == "ok" || $REPLY == "Ok" ]]; then
|
||||
sudo touch /usr/local/etc/gsportconsolewarningoff
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/gsport-consolesetup ]] && displayOK=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing GSport for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run GSport in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/gsport-consolesetup ]]; then
|
||||
echo "GSport will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $displayOK ]]; then
|
||||
if [[ $(xdpyinfo 2> /dev/null) ]]; then
|
||||
exec /usr/local/bin/gsportx
|
||||
else
|
||||
exec /usr/local/bin/gsportfb
|
||||
fi
|
||||
else
|
||||
echo "GSport has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
730
setup/gsport-setup
Executable file
730
setup/gsport-setup
Executable file
@ -0,0 +1,730 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# gsport-setup - a2cloud script to download/configure assets for GSPort
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# to do: replace Spectrum Deluxe (2.5.3) with Spectrum Gold (2.5.4)
|
||||
|
||||
# from system_ident
|
||||
if [[ -z $ras2_os || -z $ras2_arch ]]; then
|
||||
ras2_os="unknown"
|
||||
if hash lsb_release 2>/dev/null; then
|
||||
if [[ -f /usr/bin/raspi-config ]]; then
|
||||
ras2_os="rpi-$(lsb_release -cs)"
|
||||
else
|
||||
case "$(lsb_release -is)" in
|
||||
Debian)
|
||||
ras2_os="debian-$(lsb_release -cs)"
|
||||
;;
|
||||
*)
|
||||
printf "\nUnknown OS with lsb_release\n"
|
||||
lsb_release -a
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
uname_s="$(uname -s)"
|
||||
case "$uname_s" in
|
||||
Darwin)
|
||||
ras2_os="$uname_s"
|
||||
;;
|
||||
*)
|
||||
printf "\nUnknown OS with uname -s\n$uname_s\n"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
ras2_arch="$(uname -m)"
|
||||
export ras2_os ras2_arch
|
||||
fi
|
||||
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n') | tr [A-Z] [a-z]
|
||||
}
|
||||
|
||||
readchars () {
|
||||
# read one or more characters from a file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is until end of file)
|
||||
# out: sequence of characters
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11
|
||||
[[ $4 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
[[ $3 ]] && { [[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) ]] || return 23; }
|
||||
# args are valid
|
||||
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
||||
2> /dev/null
|
||||
}
|
||||
|
||||
writecharsHex () {
|
||||
# write corresponding characters of hex values into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF, period delimited (not checked!)
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
p=0
|
||||
offset=$2
|
||||
len=${#3}
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2}
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == \
|
||||
$(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$outByte" | \
|
||||
dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null
|
||||
(( p += 3 ))
|
||||
(( offset++ ))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
### start
|
||||
|
||||
a2cScriptURL="https://raw.githubusercontent.com/RasppleII/a2cloud/master"
|
||||
a2cBinaryURL="http://blocksfree.com/downloads"
|
||||
|
||||
[[ $A2CLOUD_NO_EXTERNAL ]] && useExternalURL=
|
||||
|
||||
debianVersion=$(cat /etc/debian_version 2> /dev/null)
|
||||
isRpi=
|
||||
isDebian=
|
||||
arch=
|
||||
if [[ -f /usr/bin/raspi-config ]]; then
|
||||
isRpi=1
|
||||
arch='rpi'
|
||||
me="Pi"
|
||||
fullme="Raspberry Pi"
|
||||
elif lsb_release -a 2> /dev/null | grep -q 'Distributor ID:.Debian' && [[ $(cut -d . -f 1 <<< $debianVersion) -ge "7" ]]; then
|
||||
isDebian=1
|
||||
uname_m="$(uname -m)"
|
||||
if [[ $uname_m == "i686" ]]; then
|
||||
arch='debian_x86'
|
||||
elif [[ $uname_m == "x86_64" ]]; then
|
||||
arch='debian_x64'
|
||||
fi
|
||||
me="computer"
|
||||
fullme="computer"
|
||||
fi
|
||||
|
||||
debianName=
|
||||
if [[ $debianVersion ]]; then
|
||||
debianMajor=$(cut -d . -f 1 <<< $debianVersion)
|
||||
if [[ $debianMajor == "8" ]]; then
|
||||
debianName="jessie"
|
||||
elif [[ $debianMajor == "7" ]]; then
|
||||
debianName="wheezy"
|
||||
else
|
||||
debianName="unknown"
|
||||
fi
|
||||
fi
|
||||
|
||||
isSystemd=
|
||||
isSysVInit=
|
||||
# If you really want something else, *you* maintain it!
|
||||
if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
|
||||
isSystemd=1
|
||||
elif [[ -f /etc/inittab ]]; then
|
||||
isSysVInit=1
|
||||
fi
|
||||
|
||||
emulatorName="GSport"
|
||||
emulatorStart="gsport"
|
||||
emulatorSetup="gsport-setup"
|
||||
romFileName="ROM"
|
||||
configFileName="config.txt"
|
||||
|
||||
imagesDir="/usr/local/share/gsdisks"
|
||||
gsosHD="gsoshd.hdv"
|
||||
gsosHDvolName="GSOS.HD"
|
||||
tempDir="/tmp/gs"
|
||||
|
||||
rom=ROM3
|
||||
slot6=
|
||||
autoAnswerYes=
|
||||
noDisks=
|
||||
gisk=
|
||||
installDisks=
|
||||
kegs=
|
||||
|
||||
acmdOK=
|
||||
if hash acmd 2> /dev/null; then
|
||||
acmdOK=1
|
||||
fi
|
||||
|
||||
while { [[ $1 ]] || (( (0 + $gisk + $noDisks + $installDisks + 0) > 1 )); }; do
|
||||
arg=$(tr -d '-' <<< ${1,,})
|
||||
if [[ $arg == "6" ]]; then
|
||||
slot6=1
|
||||
shift
|
||||
elif [[ $arg == "rom1" ]]; then
|
||||
rom=ROM1
|
||||
shift
|
||||
elif [[ $arg == "rom3" ]]; then
|
||||
rom=ROM3
|
||||
shift
|
||||
elif [[ $arg == "n" ]]; then
|
||||
noDisks=1
|
||||
shift
|
||||
elif [[ $arg == "g" ]]; then
|
||||
gisk=1
|
||||
shift
|
||||
elif [[ $arg == "i" ]]; then
|
||||
installDisks=1
|
||||
shift
|
||||
elif [[ $arg == "y" ]]; then
|
||||
autoAnswerYes=1
|
||||
shift
|
||||
else
|
||||
echo "Usage: $emulatorSetup [rom1|rom3] [-6] [-y [-g|-i|-n]]"
|
||||
echo "rom1: use GS ROM 01"
|
||||
echo "rom3: use GS ROM 3"
|
||||
echo "-6: put blank disks in slot 6"
|
||||
echo "-y: auto-answer yes (no prompting)"
|
||||
echo "-i: use GS/OS and Spectrum installer disk images (use with -y)"
|
||||
echo "-g: use GSport Internet Starter Kit disk image (use with -y)"
|
||||
echo "-n: don't provide any disk images (use with -y)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
if [[ ! -f /usr/local/lib/$romFileName ]]; then
|
||||
echo "$emulatorName needs to be set up. This may take several minutes."
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Do you want to set up $emulatorName now? ";
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Ok, let's go!"
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
noDisks=
|
||||
gisk=
|
||||
while true; do
|
||||
option1=0
|
||||
option2=0
|
||||
echo
|
||||
echo "Do you want to:"
|
||||
echo
|
||||
if [[ $acmdOK ]]; then
|
||||
[[ $kegs ]] && andSpectrum= || andSpectrum="and Spectrum "
|
||||
echo "1) install GS/OS ${andSpectrum}from the installer disk images"
|
||||
option1=1
|
||||
fi
|
||||
if [[ ! $kegs ]]; then
|
||||
echo "2) use the premade GSport Internet Starter Kit hard drive image"
|
||||
option2=2
|
||||
fi
|
||||
echo "3) prepare $emulatorName for use but don't provide any disk images"
|
||||
echo "4) do nothing and quit"
|
||||
echo
|
||||
echo -n "Your choice: "
|
||||
read
|
||||
noDisks=
|
||||
if [[ ${REPLY} == "4" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
elif [[ ${REPLY} == "3" ]]; then
|
||||
noDisks=1; break
|
||||
elif [[ ${REPLY} == $option2 ]]; then
|
||||
gisk=1; break
|
||||
elif [[ ${REPLY} == $option1 ]]; then
|
||||
gisk=; break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$imagesDir"
|
||||
sudo chmod ugo+rw "$imagesDir"
|
||||
mkdir -p "$tempDir"
|
||||
cd "$tempDir"
|
||||
|
||||
echo "Updating package lists..."
|
||||
sudo apt-get -y update > /dev/null
|
||||
|
||||
# http://wakaba.c3.cx/s/apps/unarchiver.html
|
||||
if ! hash unar 2> /dev/null; then
|
||||
|
||||
### ArchiveTools: Install unar package
|
||||
echo "A2CLOUD: Installing The Unarchiver..."
|
||||
|
||||
# jessie and later: Just use the unar package
|
||||
if [[ $debianMajor -ge 8 ]]; then
|
||||
sudo apt-get -y install unar
|
||||
sudo apt-get clean
|
||||
fi
|
||||
|
||||
# If all else fails, compile from source.
|
||||
|
||||
if ! hash unar 2> /dev/null; then
|
||||
# Dependencies: build-deps for unar
|
||||
sudo apt-get -y install build-essential libgnustep-base-dev libz-dev libbz2-dev libssl-dev libicu-dev unzip
|
||||
sudo apt-get clean
|
||||
|
||||
rm -rf $tempDir/unar &> /dev/null
|
||||
mkdir $tempDir/unar
|
||||
cd $tempDir/unar
|
||||
if [[ $useExternalURL ]]; then
|
||||
wget -O unar-1.8.1.zip https://github.com/incbee/Unarchiver/archive/unar-1.8.1.zip
|
||||
unzip -o unar-1.8.1.zip &> /dev/null
|
||||
fi
|
||||
if [ ! -d *Unarchiver*/XADMaster ]; then # need single bracket for glob
|
||||
wget -O unar-1.8.1.zip "${a2cBinaryURL}/source/unar-1.8.1.zip"
|
||||
unzip -o unar-1.8.1.zip &> /dev/null
|
||||
fi
|
||||
cd *Unarchiver*/XADMaster
|
||||
make -f Makefile.linux
|
||||
sudo mv lsar unar /usr/local/bin
|
||||
cd ../Extra
|
||||
sudo mkdir -p /usr/local/man/man1
|
||||
sudo mv lsar.1 unar.1 /usr/local/man/man1
|
||||
cd
|
||||
rm -rf $tempDir/unar
|
||||
fi
|
||||
sudo mandb &> /dev/null
|
||||
fi
|
||||
else
|
||||
echo "A2CLOUD: The Unarchiver has already been installed."
|
||||
fi
|
||||
cd $tempDir
|
||||
|
||||
echo "A2CLOUD: Setting up mkpo command..."
|
||||
sudo wget -qO /usr/local/bin/mkpo ${a2cScriptURL}/setup/mkpo.txt
|
||||
sudo chmod ugo+x /usr/local/bin/mkpo
|
||||
|
||||
if ! hash nulib2 2> /dev/null; then
|
||||
|
||||
echo "A2CLOUD: Installing nulib2..."
|
||||
|
||||
cd $tempDir
|
||||
if [[ $downloadBinaries ]]; then
|
||||
### ArchiveTools: Install nulib2 binaries
|
||||
wget -q "${a2cBinaryURL}/picopkg/nulib2-${ras2_os}_${ras2_arch}.tgz"
|
||||
if [[ -f "nulib2-${ras2_os}_${ras2_arch}.tgz" ]]; then
|
||||
sudo tar Pzxf "nulib2-${ras2_os}_${ras2_arch}.tgz"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! hash nulib2 2> /dev/null; then
|
||||
### ArchiveTools: Install nulib2 from source
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y install zlib1g-dev
|
||||
sudo apt-get -y clean
|
||||
|
||||
# install nulib2
|
||||
rm -rf nulib &> /dev/null
|
||||
mkdir -p nulib
|
||||
cd nulib
|
||||
wget -qO nulib.tgz http://web.archive.org/web/20131031160750/http://www.nulib.com/downloads/nulibdist.tar.gz
|
||||
tar zxf nulib.tgz
|
||||
cd nufxlib*
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ../nulib2*
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd $tempDir
|
||||
rm -rf nulib
|
||||
fi
|
||||
else
|
||||
echo "A2CLOUD: nulib2 is already installed."
|
||||
fi
|
||||
cd $tempDir
|
||||
|
||||
if ! hash sciibin 2> /dev/null; then
|
||||
### ArchiveTools: Install undoit (sciibin, etc.)
|
||||
echo "A2CLOUD: Installing sciibin, unblu, unbit, unexec, usq..."
|
||||
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y clean
|
||||
rm -rf undoit &> /dev/null
|
||||
mkdir -p undoit
|
||||
cd undoit
|
||||
wget -q http://web.archive.org/web/20110619163030/http://fadden.com/dl-apple2/undoit.zip
|
||||
unzip undoit.zip
|
||||
make
|
||||
sudo mv sciibin unbit unblu unexec usq /usr/local/bin
|
||||
cd $tempDir
|
||||
rm -rf undoit
|
||||
else
|
||||
echo "A2CLOUD: sciibin, unblu, unbit, unexec, usq are already installed."
|
||||
fi
|
||||
cd $tempDir
|
||||
|
||||
if [[ ! -f $imagesDir/ROM1 ]]; then
|
||||
echo "Getting GS ROM 01..."
|
||||
wget -qO ROM1.zip http://web.archive.org/web/20130216031247/http://www.whatisthe2gs.apple2.org.za/files/rom1.zip
|
||||
unzip ROM1.zip &> /dev/null
|
||||
mv APPLE2GS.ROM $imagesDir/ROM1
|
||||
chmod ugo-w $imagesDir/ROM1
|
||||
fi
|
||||
|
||||
if [[ ! -f $imagesDir/ROM3 ]]; then
|
||||
echo "Getting GS ROM 3..."
|
||||
wget -qO ROM3.zip http://web.archive.org/web/20130216031247/http://www.whatisthe2gs.apple2.org.za/files/rom3.zip
|
||||
unzip ROM3.zip &> /dev/null
|
||||
mv APPLE2GS.ROM2 $imagesDir/ROM3
|
||||
chmod ugo-w $imagesDir/ROM3
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/lib/$romFileName || $arg ]]; then
|
||||
echo "Setting $emulatorName to use $rom..."
|
||||
echo " (to change, use '$emulatorSetup rom1' or '$emulatorSetup rom3')"
|
||||
sudo rm /usr/local/lib/$romFileName &> /dev/null
|
||||
sudo ln -s $imagesDir/$rom /usr/local/lib/$romFileName &> /dev/null
|
||||
sudo ln -s $romFileName /usr/local/lib/ROM &> /dev/null
|
||||
fi
|
||||
|
||||
if [[ $slot6 ]]; then
|
||||
echo "Putting blank disks in slot 6..."
|
||||
sudo sed -i 's@^s6d1.*$@s6d1 = $imagesDir/slot6drive1.po@' /usr/local/lib/$configFileName
|
||||
sudo sed -i 's@^s6d2.*$@s6d2 = $imagesDir/slot6drive2.po@' /usr/local/lib/$configFileName
|
||||
if [[ ! -f $imagesDir/slot6drive1.po || ! -f $imagesDir/slot6drive2.po ]]; then
|
||||
wget -qO- "${a2BinaryURL}/gsport/slot6.tgz" | sudo tar Pzx 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# set AppleTalk to turbo (works more reliably than Normal)
|
||||
echo "Setting AppleTalk to turbo..."
|
||||
if ! grep -q 'g_appletalk_turbo' /usr/local/lib/$configFileName; then
|
||||
if grep -q 'bram1\[00\]' /usr/local/lib/$configFileName; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_appletalk_turbo = 1\n\n\1/' /usr/local/lib/$configFileName
|
||||
else
|
||||
echo -e '\ng_appletalk_turbo = 1' | sudo tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/g_appletalk_turbo = 0/g_appletalk_turbo = 1/' /usr/local/lib/$configFileName
|
||||
|
||||
# enable Uthernet
|
||||
echo "Enabling Uthernet card emulation..."
|
||||
if ! grep -q 'g_ethernet[^_]' /usr/local/lib/$configFileName; then
|
||||
if grep -q 'bram1\[00\]' /usr/local/lib/$configFileName; then
|
||||
sudo sed -i 's/^\(bram1\[00\]\)/g_ethernet = 1\n\n\1/' /usr/local/lib/$configFileName
|
||||
else
|
||||
echo -e '\ng_ethernet = 1' | sudo tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
sudo sed -i 's/g_ethernet = 0/g_ethernet = 1/' /usr/local/lib/$configFileName
|
||||
|
||||
# GISK
|
||||
if [[ $gisk ]]; then
|
||||
echo "Getting GSport Internet Starter Kit..."
|
||||
wget -O $tempDir/GSport_Internet_Starter_Kit.zip http://sourceforge.net/projects/gsport/files/Emulator%20Software%20Images/GSport_Internet_Starter_Kit.zip
|
||||
unzip -d $tempDir $tempDir/GSport_Internet_Starter_Kit.zip "GSport Internet Starter Kit/GSport Internet Starter Kit.2mg"
|
||||
sudo mv "$tempDir/GSport Internet Starter Kit/GSport Internet Starter Kit.2mg" $imagesDir
|
||||
rm -r $tempDir/GSport*
|
||||
if [[ $(grep ^s7d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d1.*$:s7d1 = $imagesDir/GSport Internet Starter Kit.2mg:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d1 = $imagesDir/GSport Internet Starter Kit.2mg" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
noDisks=1
|
||||
fi
|
||||
if [[ $noDisks ]]; then
|
||||
echo
|
||||
echo
|
||||
echo "Setup complete. You can now start $emulatorName."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Press return to continue..."
|
||||
read
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# non-GISK; get installer disks
|
||||
if [[ ! -f $imagesDir/INSTALL.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEM.DISK.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEMTOOLS1.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYSTEMTOOLS2.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/FONTS.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/SYNTHLAB.HDV ]] \
|
||||
|| [[ ! -f $imagesDir/"$gsosHD" ]] \
|
||||
|| [[ ! $kegs && ! -f $imagesDir/spectrum.hdv ]]; then
|
||||
|
||||
REPLY="y"
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo
|
||||
activeDisk=0
|
||||
for diskname in Install System.Disk SystemTools1 SystemTools2 Fonts synthLAB; do
|
||||
(( activeDisk++ ))
|
||||
outfile="$imagesDir/$(tr [:lower:] [:upper:] <<< $diskname).HDV"
|
||||
if [[ ! -f "$outfile" ]]; then
|
||||
echo "Getting GS/OS disk ${activeDisk} of 6: $diskname"
|
||||
wget -qO "Disk_${activeDisk}_of_7-$diskname.sea.bin" "http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FApple_II%2FApple_IIGS_System_6.0.1%2FDisk_${activeDisk}_of_7-$diskname.sea.bin"
|
||||
unar -k skip "Disk_${activeDisk}_of_7-$diskname.sea.bin" &> /dev/null
|
||||
truncate -s 819284 "Disk ${activeDisk} of 7-${diskname}.sea"
|
||||
dd if="Disk ${activeDisk} of 7-${diskname}.sea" of=${outfile} bs=84 skip=1 &> /dev/null
|
||||
chmod ugo-w "$outfile"
|
||||
if [[ $activeDisk -eq 1 ]]; then
|
||||
if [[ $(grep ^s5d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s5d1.*$:s5d1 = $imagesDir/INSTALL.HDV:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s5d1 = $imagesDir/INSTALL.HDV" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
else
|
||||
if [[ $(grep ^s7d$activeDisk /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d$activeDisk.*$:s7d$activeDisk = $outfile:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d$activeDisk = $outfile" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "GS/OS disk ${activeDisk} of 6: $diskname has already been downloaded."
|
||||
fi
|
||||
done
|
||||
rm *.sea* &> /dev/null
|
||||
|
||||
if [[ ! -f $imagesDir/"$gsosHD" ]]; then
|
||||
echo "Creating 32 MB blank image at $imagesDir/$gsosHD..."
|
||||
if [[ -f /usr/local/bin/acmd ]]; then
|
||||
# if acmd exists, make a ProDOS disk with GS-ShrinkIt and Teach
|
||||
|
||||
if [[ ! -f /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar ]]; then
|
||||
echo "Installing AppleCommander-1.3.5.13id..."
|
||||
sudo mkdir -p /usr/local/adtpro/lib/AppleCommander
|
||||
wget -qO /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar http://downloads.sourceforge.net/project/applecommander/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar
|
||||
rm /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar &> /dev/null
|
||||
ln -s AppleCommander-1.3.5.13id-ac.jar /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar
|
||||
fi
|
||||
|
||||
echo "Copying ProDOS..."
|
||||
acmd -g "$imagesDir/INSTALL.HDV" PRODOS "PRODOS#ff0000"
|
||||
wget -qO- ${a2cBinaryURL}/gsport/splash/${emulatorName}SPLASH.SYS | dd of="PRODOS#ff0000" conv=notrunc &> /dev/null
|
||||
echo "Copying Teach..."
|
||||
cppo -uc -e $imagesDir/SYSTEMTOOLS2.HDV /SYSTEMTOOLS2/TEACH . &> /dev/null
|
||||
echo "Downloading GS-ShrinkIt..."
|
||||
wget -qO- http://web.archive.org/web/20131031160750/http://nulib.com/library/gshk11.sea | nulib2 -x -e - GSHK &> /dev/null
|
||||
echo 1
|
||||
nulib2 -a -e $gsosHD.shk "PRODOS#"* "GSHK#"* "TEACH#"* &> /dev/null
|
||||
echo 2
|
||||
acmd -convert $gsosHD.shk $imagesDir/"$gsosHD" 65535
|
||||
echo 3
|
||||
rm "PRODOS#"* "GSHK#"* "TEACH#"* $gsosHD.shk &> /dev/null
|
||||
|
||||
acmd -n $imagesDir/"$gsosHD" $gsosHDvolName
|
||||
dd bs=512 count=1 conv=notrunc if="$imagesDir/INSTALL.HDV" of="$imagesDir/$gsosHD" 2> /dev/null
|
||||
sudo chmod ugo+rw $imagesDir/"$gsosHD"
|
||||
fi
|
||||
echo 4
|
||||
if [[ $(grep ^s7d1 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d1.*$:s7d1 = $imagesDir/$gsosHD:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d1 = $imagesDir/$gsosHD" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $(grep ^g_limit_speed /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^g_limit_speed.*$:g_limit_speed = 0:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "g_limit_speed = 0" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
|
||||
if [[ -f /usr/local/bin/acmd && ! $(acmd -ls $imagesDir/$gsosHD | grep 'GSHK') ]]; then
|
||||
echo
|
||||
echo "Downloading GS-ShrinkIt..."
|
||||
wget -qO- http://web.archive.org/web/20131031160750/http://nulib.com/library/gshk11.sea | acmd -p $imagesDir/$gsosHD GS.SHRINKIT.SEA S16
|
||||
fi
|
||||
|
||||
|
||||
# Spectrum starts here
|
||||
|
||||
if [[ ! $kegs ]]; then
|
||||
|
||||
mkdir -p $tempDir/spectrum
|
||||
cd $tempDir/spectrum
|
||||
|
||||
imageName="$tempDir/spectrum/spectrum.dmg"
|
||||
hfsName="$tempDir/spectrum/spectrumH.dmg"
|
||||
ullName="$tempDir/spectrum/uthernet.bxy"
|
||||
|
||||
if [[ ! -f /usr/bin/hcopy || ! -f /usr/bin/macsave ]]; then
|
||||
echo "Installing HFS utilities..."
|
||||
sudo apt-get -y install hfsutils macutils &> /dev/null
|
||||
else
|
||||
echo "HFS utilities are already installed."
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar ]]; then
|
||||
echo "Installing AppleCommander..."
|
||||
sudo mkdir -p /usr/local/adtpro/lib/AppleCommander
|
||||
wget -qO /usr/local/adtpro/lib/AppleCommander/AppleCommander-1.3.5.13id-ac.jar http://downloads.sourceforge.net/project/applecommander/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar
|
||||
rm /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar &> /dev/null
|
||||
ln -s AppleCommander-1.3.5.13id-ac.jar /usr/local/adtpro/lib/AppleCommander/AppleCommander-ac.jar
|
||||
fi
|
||||
|
||||
if [[ ! -f "$imageName" ]]; then
|
||||
echo "Downloading Spectrum Deluxe..."
|
||||
wget -qO spectrum.dmg http://www.wannop.info/speccie/software/spectrum_2.5.3_deluxe.dmg
|
||||
else
|
||||
echo "Spectrum Deluxe has already been downloaded."
|
||||
fi
|
||||
|
||||
mkdir -p mnt
|
||||
mkdir -p extract
|
||||
mkdir -p shkstage
|
||||
cp "$imageName" "$hfsName"
|
||||
sudo mount -r -t hfs "$imageName" mnt
|
||||
hmount "$hfsName"
|
||||
|
||||
IFS=''
|
||||
cd $tempDir/spectrum/mnt
|
||||
find Spectrum.2.5.3 -type d | while read thisDirPath; do
|
||||
mkdir -p $tempDir/spectrum/shkstage/"$thisDirPath"
|
||||
hcd
|
||||
IFS='/'
|
||||
for thisDir in $thisDirPath; do
|
||||
hcd $thisDir
|
||||
done
|
||||
echo " Copying: $(hpwd)"
|
||||
IFS=''
|
||||
cd $tempDir/spectrum/extract
|
||||
hls -1 | while read thisFile; do
|
||||
hcopy -m "$thisFile" - 2> /dev/null | macsave -f 2> /dev/null
|
||||
if [[ -f "$thisFile".info ]]; then
|
||||
if [[ $(readcharHex "$thisFile".info 65) == "70" ]]; then
|
||||
fileType=$(readcharHex "$thisFile".info 66)
|
||||
auxType=$(readcharHex "$thisFile".info 67)$(readcharHex "$thisFile".info 68)
|
||||
else
|
||||
auxType="0000"
|
||||
fMac=$(readchars "$thisFile".info 65 4)
|
||||
if [[ "$fMac" == "PS16" ]]; then
|
||||
fileType="b3";
|
||||
elif [[ "$fMac" == "PSYS" ]]; then
|
||||
fileType="ff";
|
||||
elif [[ "$fMac" == "BINA" ]]; then
|
||||
fileType="00";
|
||||
elif [[ "$fMac" == "TEXT" ]]; then
|
||||
fileType="04";
|
||||
elif [[ "$fMac" == "MIDI" ]]; then
|
||||
fileType="D7";
|
||||
elif [[ "$fMac" == "AIFF" || "$fMac" == "AIFC" ]]; then
|
||||
fileType="D8";
|
||||
elif [[ "$fMac" == "dImg" ]]; then
|
||||
fileType="E0";
|
||||
else
|
||||
echo "WARNING: unknown file type '$fMac' found for file $thisFile"
|
||||
fi
|
||||
fi
|
||||
[[ -f "$thisFile".rsrc ]] && mv "$thisFile".rsrc $tempDir/spectrum/shkstage/"$thisDirPath"/"${thisFile}#${fileType}${auxType}r"
|
||||
[[ -f "$thisFile".data ]] && mv "$thisFile".data $tempDir/spectrum/shkstage/"$thisDirPath"/"${thisFile}#${fileType}${auxType}"
|
||||
rm "$thisFile".info 2> /dev/null
|
||||
fi
|
||||
done
|
||||
cd $tempDir/spectrum/mnt
|
||||
done
|
||||
|
||||
cd $tempDir/spectrum/shkstage/Spectrum*
|
||||
humount
|
||||
sudo umount $tempDir/spectrum/mnt
|
||||
|
||||
mkdir -p Marinetti/Uthernet
|
||||
cp SAFE2.Archive/Link.Layers/"Uthernet#bc4083" Marinetti/Uthernet
|
||||
echo -n "After installing Marinetti, put Uthernet in the TCPIP folder of your System folder, and restart GS/OS. Then open Control Panels, choose TCP/IP, and choose Setup Connection. Choose Uthernet for the link layer. Under Primary Domain Name Server, enter 8.8.8.8, then click Configure and select Slot 3 and DHCP. Then click Save." > Marinetti/Uthernet/"Uthernet.README#040000"
|
||||
|
||||
echo "Making archive for conversion to disk image..."
|
||||
rm $tempDir/spectrum/spectrum.shk 2> /dev/null
|
||||
nulib2 -a -r -0 -e $tempDir/spectrum/spectrum.shk * &> /dev/null
|
||||
echo "Converting archive to disk image..."
|
||||
acmd -convert $tempDir/spectrum/spectrum.shk $imagesDir/spectrum.hdv 20480
|
||||
acmd -n $imagesDir/spectrum.hdv SPECTRUM.DELUXE
|
||||
|
||||
if [[ $(grep ^s7d7 /usr/local/lib/$configFileName) ]]; then
|
||||
sudo sed -i "s:^s7d7.*$:s7d7 = $imagesDir/spectrum.hdv:" /usr/local/lib/$configFileName
|
||||
else
|
||||
echo "s7d7 = $imagesDir/spectrum.hdv" | tee -a /usr/local/lib/$configFileName > /dev/null
|
||||
fi
|
||||
|
||||
cd $tempDir
|
||||
|
||||
rm -rf $tempDir/spectrum/extract $tempDir/spectrum/shkstage $tempDir/spectrum/spectrum.shk $tempDir/spectrum/mnt &> /dev/null
|
||||
fi
|
||||
# Spectrum ends here
|
||||
fi
|
||||
fi
|
||||
|
||||
cd
|
||||
rm -r "$tempDir"
|
||||
|
||||
echo
|
||||
echo
|
||||
if [[ -f "$imagesDir/$gsosHD" ]]; then
|
||||
echo
|
||||
echo "You can now start $emulatorName."
|
||||
echo "When the installer boots, you can click Easy Update or Customize"
|
||||
echo "to install GS/OS, if you downloaded the installer disks aobve."
|
||||
else
|
||||
# if no acmd, create unformatted disk
|
||||
# requires that the disk first be formatted with Advanced Disk Utility
|
||||
dd bs=512 count=65535 if=/dev/zero of=$imagesDir/"$gsosHD" 2> /dev/null
|
||||
writecharsHex $imagesDir/"$gsosHD" 0 "00.4C.00.C5.00"
|
||||
echo
|
||||
echo "You can now start $emulatorName."
|
||||
echo
|
||||
echo "If you downloaded the installer disks above:"
|
||||
echo "When the installer boots, quit it, change to the SystemTools1 disk,"
|
||||
echo "run Advanced Disk Utility, click Disk until a hard drive icon appears"
|
||||
echo "that says Uninitialized, and initialize it. Then quit Advanced Disk"
|
||||
echo "Utility, change to the Install Disk, and run Installer. When it loads,"
|
||||
echo "click Easy Update or Customize to install GS/OS."
|
||||
echo
|
||||
fi
|
||||
echo "When it's done, reboot."
|
||||
echo "(Use Shut Down, ctrl-F12, or ctrl-solidapple-equals.)"
|
||||
if [[ -f "$imagesDir/spectrum.hdv" ]]; then
|
||||
echo
|
||||
echo "Then on the Spectrum disk, optionally install:"
|
||||
echo "Marinetti (plus update): TCP/IP driver for GS/OS"
|
||||
echo "Uthernet: Ethernet driver for Marinetti"
|
||||
echo "Spectrum: serial and telnet communications"
|
||||
echo "SAFE: FTP client"
|
||||
echo "SNAP: Usenet newsgroups (NNTP) client"
|
||||
echo "SAM2: Email (POP) client"
|
||||
fi
|
||||
echo
|
||||
echo "After installing, press F4 and choose 'Disk Configuration' to"
|
||||
echo "eject all disks other than slot 7 drive 1."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Press return to continue..."
|
||||
read
|
||||
fi
|
9
setup/gsport-setup-shell
Executable file
9
setup/gsport-setup-shell
Executable file
@ -0,0 +1,9 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
wget -qO /tmp/gsport-setup https://raw.githubusercontent.com/RasppleII/a2cloud/master/setup/gsport-setup
|
||||
if [[ $(wc -c /tmp/gsport-setup | grep '^0 ') ]]; then
|
||||
echo "Please connect to the internet to set up GSport."
|
||||
else
|
||||
source /tmp/gsport-setup "$@"
|
||||
fi
|
@ -1,6 +0,0 @@
|
||||
wget -qO /tmp/gsport-setup appleii.ivanx.com/a2cloud/setup/gsport-setup.txt
|
||||
if [[ $(wc -c /tmp/gsport-setup | grep '^0 ') ]]; then
|
||||
echo "Please connect to the internet to set up GSport."
|
||||
else
|
||||
source /tmp/gsport-setup "$@"
|
||||
fi
|
122
setup/gsport.txt
122
setup/gsport.txt
@ -1,122 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run GSport on the console, or in an X Window."
|
||||
else
|
||||
|
||||
if [[ -f /usr/local/lib/ROM ]]; then
|
||||
if [[ ! $(grep snd-pcm-oss /etc/modules) ]]; then
|
||||
echo "Configuring GSport sound..."
|
||||
echo "snd-pcm-oss" | sudo tee -a /etc/modules > /dev/null
|
||||
[[ ! $(lsmod | grep snd_pcm_oss) ]] && sudo modprobe snd-pcm-oss
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l xfonts-base 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport fonts..."
|
||||
sudo apt-get -y update
|
||||
touch /tmp/updated
|
||||
sudo apt-get -y install xfonts-base &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l libpcap0.8-dev 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring GSport networking..."
|
||||
[[ ! -f /tmp/updated ]] && sudo apt-get -y update
|
||||
sudo apt-get -y install libpcap0.8-dev &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
rm /tmp/updated &> /dev/null
|
||||
else
|
||||
gsport-setup
|
||||
[[ $? -ne 0 ]] && exit 1
|
||||
fi
|
||||
|
||||
displayOK=
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
displayOK=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /usr/local/etc/gsportconsolewarningoff ]] && { dpkg -l | grep -q -i virtualbox; }; then
|
||||
echo
|
||||
echo "If you have difficulties moving the mouse in GS/OS, choose"
|
||||
echo "'Disable Mouse Integration' from the Machine menu. To free the mouse"
|
||||
echo "from the virtual machine, press the Host key (shown in the lower right"
|
||||
echo "corner of the virtual machine window)."
|
||||
echo
|
||||
echo "Press alt-F4 to exit GSport."
|
||||
echo
|
||||
echo "Press return to continue,"
|
||||
echo -n " or type 'OK' if you want to stop seeing this message: "
|
||||
read
|
||||
if [[ $REPLY == "ok" || $REPLY == "ok" || $REPLY == "Ok" ]]; then
|
||||
sudo touch /usr/local/etc/gsportconsolewarningoff
|
||||
fi
|
||||
# echo "If you wish to run GSport in the console window, the mouse will not work"
|
||||
# echo "unless you uninstall VirtualBox Guest Additions. If you don't want to do"
|
||||
# echo "this, you can instead run GSport in an X window (e.g. by typing 'startx')."
|
||||
# echo "If you're not sure, just uninstall it now. Nothing terrible will happen."
|
||||
# echo
|
||||
# echo -n "Do you want to uninstall VirtualBox Guest Additions now? "
|
||||
# read
|
||||
# if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
# echo "Ok, on the case..."
|
||||
# sudo /etc/init.d/vboxadd-service stop 2> /dev/null
|
||||
# sudo /etc/init.d/virtualbox-guest-utils stop &> /dev/null
|
||||
# sudo rmmod vboxvideo 2> /dev/null
|
||||
# sudo rmmod vboxsf 2> /dev/null
|
||||
# sudo rmmod vboxguest 2> /dev/null
|
||||
# while { lsmod | grep -q vbox; }; do
|
||||
# sleep 1
|
||||
# sudo rmmod vboxvideo 2> /dev/null
|
||||
# sudo rmmod vboxsf 2> /dev/null
|
||||
# sudo rmmod vboxguest 2> /dev/null
|
||||
# done
|
||||
# if [ -f /opt/VBoxGuestAdditions*/uninstall.sh ]; then
|
||||
# sudo /opt/VBoxGuestAdditions*/uninstall.sh &> /dev/null
|
||||
# sudo rmdir /opt/VBoxGuestAdditions* 2> /dev/null
|
||||
# fi
|
||||
# if { dpkg -l 2> /dev/null | grep -q -i virtualbox; }; then
|
||||
# sudo apt-get -y purge $(dpkg -l 2> /dev/null | grep -i virtualbox | cut -f 3 -d ' ' | tr '\n' ' ') &> /dev/null
|
||||
# fi
|
||||
# touch /tmp/gsport-consolesetup
|
||||
# fi
|
||||
fi
|
||||
|
||||
if [[ ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/gsport-consolesetup ]] && displayOK=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing GSport for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/gsport-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run GSport in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/gsport-consolesetup ]]; then
|
||||
echo "GSport will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $displayOK ]]; then
|
||||
if [[ $(xdpyinfo 2> /dev/null) ]]; then
|
||||
exec gsportx
|
||||
else
|
||||
exec gsportfb
|
||||
fi
|
||||
else
|
||||
echo "GSport has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
1005
setup/ivan.sh
Executable file
1005
setup/ivan.sh
Executable file
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
wget -qO /tmp/gsport-setup ivanx.com/a2cloud/setup/gsport-setup.txt
|
||||
if [[ $(wc -c /tmp/gsport-setup | grep '^0 ') ]]; then
|
||||
echo "Please connect to the internet to set up KEGS."
|
||||
else
|
||||
source /tmp/gsport-setup -k "$@"
|
||||
fi
|
@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ! $DISPLAY ]]; then
|
||||
echo "Please run KEGS in an X Window."
|
||||
echo "(If you are using the console, type 'startx'.)"
|
||||
else
|
||||
if [[ -f /usr/local/lib/rom.kegs ]]; then
|
||||
if [[ ! $(grep snd-pcm-oss /etc/modules) ]]; then
|
||||
echo "Configuring KEGS sound..."
|
||||
echo "snd-pcm-oss" | sudo tee -a /etc/modules > /dev/null
|
||||
[[ ! $(lsmod | grep snd_pcm_oss) ]] && sudo modprobe snd-pcm-oss
|
||||
fi
|
||||
|
||||
if [[ ! $(dpkg -l xfonts-base 2> /dev/null | grep '^ii') ]]; then
|
||||
echo "Configuring KEGS fonts..."
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install xfonts-base &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
exec xkegs
|
||||
else
|
||||
kegs-setup
|
||||
[[ $? -ne 0 ]] && exit 1
|
||||
exec kegs
|
||||
fi
|
||||
fi
|
60
setup/linapple
Executable file
60
setup/linapple
Executable file
@ -0,0 +1,60 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# linapple - a2cloud wrapper script for LinApple (to be removed)
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run LinApple on the console, or in an X Window."
|
||||
else
|
||||
if [[ $(dpkg -l libsdl1.2debian libcurl3 zlib1g libzip2 2> /dev/null | grep ^ii | wc -l) -ne 4 ]]; then
|
||||
echo "Configuring LinApple libraries (this may take a moment)..."
|
||||
sudo apt-get -y update &> /dev/null
|
||||
sudo apt-get -y install libsdl1.2debian libcurl3 zlib1g libzip2 &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
linappleOk=
|
||||
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
linappleOk=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /tmp/linapple-consolesetup && ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/linapple-consolesetup ]] && linappleOk=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing LinApple for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run LinApple in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/linapple-consolesetup ]]; then
|
||||
echo "LinApple will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $linappleOk ]]; then
|
||||
cd /usr/local/linapple
|
||||
./linapple
|
||||
else
|
||||
echo "LinApple has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ( $(grep USB <<< $myTTY) || $(grep AMA <<< $myTTY) || $SSH_CLIENT || $REMOTEHOST ) && ! $DISPLAY ]]; then
|
||||
echo "Please run LinApple on the console, or in an X Window."
|
||||
else
|
||||
if [[ $(dpkg -l libsdl1.2debian libcurl3 zlib1g libzip2 2> /dev/null | grep ^ii | wc -l) -ne 4 ]]; then
|
||||
echo "Configuring LinApple libraries (this may take a moment)..."
|
||||
sudo apt-get -y update &> /dev/null
|
||||
sudo apt-get -y install libsdl1.2debian libcurl3 zlib1g libzip2 &> /dev/null
|
||||
sudo apt-get -y clean
|
||||
fi
|
||||
|
||||
linappleOk=
|
||||
|
||||
if [[ $DISPLAY ]]; then # X Window
|
||||
linappleOk=1
|
||||
else # console/framebuffer
|
||||
if [[ ! -f /tmp/linapple-consolesetup && ! $(grep 'input' <<< $(groups) ) ]]; then
|
||||
sudo groupadd input &> /dev/null
|
||||
sudo usermod -a -G input $USER
|
||||
echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules > /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
|
||||
if [[ -c /dev/fb0 ]]; then
|
||||
[[ ! -f /tmp/linapple-consolesetup ]] && linappleOk=1
|
||||
else
|
||||
if [[ -f /etc/default/grub ]]; then
|
||||
if [[ ! $(grep 'GRUB_GFXPAYLOAD_LINUX' /etc/default/grub) ]]; then
|
||||
echo "Preparing LinApple for console use..."
|
||||
sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=.*\)$/\1\nGRUB_GFXPAYLOAD_LINUX=640x480/' /etc/default/grub
|
||||
sudo update-grub &> /dev/null
|
||||
touch /tmp/linapple-consolesetup
|
||||
fi
|
||||
else
|
||||
echo "No framebuffer available. Please run LinApple in an X window."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $DISPLAY && -f /tmp/linapple-consolesetup ]]; then
|
||||
echo "LinApple will be ready for console use after you restart your system."
|
||||
echo "You can restart now by typing 'system-restart'."
|
||||
elif [[ $linappleOk ]]; then
|
||||
cd /usr/local/linapple
|
||||
./linapple
|
||||
else
|
||||
echo "LinApple has a problem. Please try updating A2CLOUD by"
|
||||
echo "typing 'a2cloud-setup'."
|
||||
fi
|
||||
|
||||
fi
|
168
setup/mkpo
Executable file
168
setup/mkpo
Executable file
@ -0,0 +1,168 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# mkpo - create ProDOS disk image
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# ID-bashByter routines
|
||||
|
||||
function binToDec ()
|
||||
{
|
||||
dec=0;
|
||||
bits=$1;
|
||||
while (( ${#bits} < 8 )); do
|
||||
bits="0$bits";
|
||||
done;
|
||||
for n in {0..7};
|
||||
do
|
||||
(( dec+=( ${bits:$n:1} * ( 2**(7-$n) ) ) ));
|
||||
done;
|
||||
echo -n $dec
|
||||
};
|
||||
|
||||
function writecharDec ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) && ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23;
|
||||
echo -n -e "\x$(printf %02X "$3")" | dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
};
|
||||
|
||||
function writecharsHex ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
p=0;
|
||||
offset=$2;
|
||||
len=${#3};
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2};
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == $(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23;
|
||||
echo -n -e "\x$outByte" | dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null;
|
||||
(( p += 3 ));
|
||||
(( offset++ ));
|
||||
done
|
||||
};
|
||||
|
||||
# mkpo
|
||||
|
||||
[[ ! -n $1 ]] && { echo "Usage: mkpo [-b totalBlocks] newImageName [PRODOS.VOL.NAME]"; exit 1; };
|
||||
|
||||
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
|
||||
[[ ! -d "$adtPath" ]] && { echo "AppleCommander not found."; exit 1; }
|
||||
|
||||
if [[ $1 == "-b" ]]; then
|
||||
totalBlocks="$2"
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
[[ -f $1 ]] && { echo "Image '$1' already exists."; exit 1; }
|
||||
|
||||
[[ $2 ]] && prodosVolName="$2" || prodosVolName="UNTITLED"
|
||||
# test ProDOS name legitimacy
|
||||
prodosVolName=$(tr [:lower:] [:upper:] <<< $prodosVolName )
|
||||
if [[ ${#prodosVolName} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $prodosVolName) ]]; then
|
||||
echo "Invalid ProDOS name: $prodosVolName"; exit 1;
|
||||
fi
|
||||
|
||||
# see if nulib2 is available; if so, acmd -convert will create image
|
||||
# with specified block size
|
||||
nulib2 &> /dev/null
|
||||
[[ $? == 2 ]] && nulib2=1 || nulib2=
|
||||
if [[ $nulib2 ]]; then
|
||||
if [[ $totalBlocks ]]; then
|
||||
imageBlocks="$totalBlocks"
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
imageBlocks=280
|
||||
else
|
||||
imageBlocks=1600
|
||||
fi
|
||||
fi
|
||||
rm /tmp/blank.shk &> /dev/null
|
||||
orig_dir="$PWD"
|
||||
cd /tmp
|
||||
rm blank.shk EMPTY &> /dev/null
|
||||
touch EMPTY
|
||||
nulib2 -a blank.shk EMPTY &> /dev/null
|
||||
cd "$orig_dir"
|
||||
acmd -convert /tmp/blank.shk "$1" $imageBlocks
|
||||
acmd -d "$1" EMPTY
|
||||
rm /tmp/blank.shk /tmp/EMPTY
|
||||
acmd -n "$1" "$prodosVolName"
|
||||
else
|
||||
# make the disk image without converting archive
|
||||
if [[ $totalBlocks || $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
acmd -pro140 "$1" $prodosVolName;
|
||||
else
|
||||
acmd -pro800 "$1" $prodosVolName;
|
||||
fi
|
||||
fi
|
||||
|
||||
# make the disk bootable
|
||||
if [ -f "$adtPath"/disks/ADTPRO*PO ]; then
|
||||
dd bs=512 count=1 of="$1" conv=notrunc < "$adtPath"/disks/ADTPRO*PO 2> /dev/null
|
||||
fi
|
||||
|
||||
# change .DSK to DOS-ordered
|
||||
if [[ ! $totalBlocks && $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
mv "$1" "$1".tmp
|
||||
for t in {0..34}; do
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
dd bs=256 count=1 if="$1".tmp of="$1" skip=$(( $t*16 + $s )) seek=$(( $t*16 + ( $s==0||$s==15 ? $s : 15-$s ) )) 2> /dev/null;
|
||||
done;
|
||||
done
|
||||
rm "$1".tmp
|
||||
fi
|
||||
|
||||
# if nulib2 isn't available, patch the disk image to use specified block size
|
||||
if [[ ! $nulib2 && $totalBlocks ]]; then
|
||||
# change total block count
|
||||
bcHex=$(printf "%04X" $totalBlocks);
|
||||
writecharsHex "$1" 1065 "${bcHex:2:2}.${bcHex:0:2}";
|
||||
|
||||
# fix FSB
|
||||
dd if=/dev/zero of="$1" bs=512 seek=280 count=$(( $totalBlocks - 280 )) 2> /dev/null;
|
||||
dd if="$1" of="$1" bs=1 skip=3073 seek=3107 count=$(( ($totalBlocks / 8) - 35 )) conv=notrunc 2> /dev/null;
|
||||
bits=$(( $totalBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
usedString="00000000";
|
||||
freeString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
freeString=$freeString"1";
|
||||
done;
|
||||
binString=$freeString${usedString:$bits};
|
||||
writecharDec "$1" $(( ( ($totalBlocks / 8) - 35) + 3107 )) $(binToDec $binString);
|
||||
fi;
|
||||
|
||||
# assign extra blocks to FSB if needed
|
||||
fsbExtraBlocks=$(( ($totalBlocks-1)/4096 ));
|
||||
if (( fsbExtraBlocks > 0 )); then
|
||||
dd if=/dev/zero of="$1" bs=1 seek=3072 count=$(( (fsbExtraBlocks > 8) + 1 )) conv=notrunc 2> /dev/null;
|
||||
(( fsbExtraBlocks-- ));
|
||||
fi;
|
||||
|
||||
bits=$(( fsbExtraBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
freeString="11111111";
|
||||
usedString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
usedString=$usedString"0";
|
||||
done;
|
||||
binString=$usedString${freeString:$bits};
|
||||
writecharDec "$1" $(( (fsbExtraBlocks>7)+3073 )) $(binToDec $binString);
|
||||
fi;
|
||||
fi
|
160
setup/mkpo.txt
160
setup/mkpo.txt
@ -1,160 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ID-bashByter routines
|
||||
|
||||
function binToDec ()
|
||||
{
|
||||
dec=0;
|
||||
bits=$1;
|
||||
while (( ${#bits} < 8 )); do
|
||||
bits="0$bits";
|
||||
done;
|
||||
for n in {0..7};
|
||||
do
|
||||
(( dec+=( ${bits:$n:1} * ( 2**(7-$n) ) ) ));
|
||||
done;
|
||||
echo -n $dec
|
||||
};
|
||||
|
||||
function writecharDec ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) && ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23;
|
||||
echo -n -e "\x$(printf %02X "$3")" | dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
};
|
||||
|
||||
function writecharsHex ()
|
||||
{
|
||||
[[ -n $1 ]] || return 11;
|
||||
[[ -n $2 ]] || return 12;
|
||||
[[ -n $3 ]] || return 13;
|
||||
[[ -n $4 ]] && return 8;
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
|
||||
p=0;
|
||||
offset=$2;
|
||||
len=${#3};
|
||||
while (( p < len )); do
|
||||
outByte=${3:$p:2};
|
||||
[[ $(printf %02X "0x$outByte" 2> /dev/null) == $(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23;
|
||||
echo -n -e "\x$outByte" | dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null;
|
||||
(( p += 3 ));
|
||||
(( offset++ ));
|
||||
done
|
||||
};
|
||||
|
||||
# mkpo
|
||||
|
||||
[[ ! -n $1 ]] && { echo "Usage: mkpo [-b totalBlocks] newImageName [PRODOS.VOL.NAME]"; exit 1; };
|
||||
|
||||
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
|
||||
[[ ! -d "$adtPath" ]] && { echo "AppleCommander not found."; exit 1; }
|
||||
|
||||
if [[ $1 == "-b" ]]; then
|
||||
totalBlocks="$2"
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
[[ -f $1 ]] && { echo "Image '$1' already exists."; exit 1; }
|
||||
|
||||
[[ $2 ]] && prodosVolName="$2" || prodosVolName="UNTITLED"
|
||||
# test ProDOS name legitimacy
|
||||
prodosVolName=$(tr [:lower:] [:upper:] <<< $prodosVolName )
|
||||
if [[ ${#prodosVolName} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $prodosVolName) ]]; then
|
||||
echo "Invalid ProDOS name: $prodosVolName"; exit 1;
|
||||
fi
|
||||
|
||||
# see if nulib2 is available; if so, acmd -convert will create image
|
||||
# with specified block size
|
||||
nulib2 &> /dev/null
|
||||
[[ $? == 2 ]] && nulib2=1 || nulib2=
|
||||
if [[ $nulib2 ]]; then
|
||||
if [[ $totalBlocks ]]; then
|
||||
imageBlocks="$totalBlocks"
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
imageBlocks=280
|
||||
else
|
||||
imageBlocks=1600
|
||||
fi
|
||||
fi
|
||||
rm /tmp/blank.shk &> /dev/null
|
||||
orig_dir="$PWD"
|
||||
cd /tmp
|
||||
rm blank.shk EMPTY &> /dev/null
|
||||
touch EMPTY
|
||||
nulib2 -a blank.shk EMPTY &> /dev/null
|
||||
cd "$orig_dir"
|
||||
acmd -convert /tmp/blank.shk "$1" $imageBlocks
|
||||
acmd -d "$1" EMPTY
|
||||
rm /tmp/blank.shk /tmp/EMPTY
|
||||
acmd -n "$1" "$prodosVolName"
|
||||
else
|
||||
# make the disk image without converting archive
|
||||
if [[ $totalBlocks || $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
acmd -pro140 "$1" $prodosVolName;
|
||||
else
|
||||
acmd -pro800 "$1" $prodosVolName;
|
||||
fi
|
||||
fi
|
||||
|
||||
# make the disk bootable
|
||||
if [ -f "$adtPath"/disks/ADTPRO*PO ]; then
|
||||
dd bs=512 count=1 of="$1" conv=notrunc < "$adtPath"/disks/ADTPRO*PO 2> /dev/null
|
||||
fi
|
||||
|
||||
# change .DSK to DOS-ordered
|
||||
if [[ ! $totalBlocks && $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
|
||||
mv "$1" "$1".tmp
|
||||
for t in {0..34}; do
|
||||
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
|
||||
dd bs=256 count=1 if="$1".tmp of="$1" skip=$(( $t*16 + $s )) seek=$(( $t*16 + ( $s==0||$s==15 ? $s : 15-$s ) )) 2> /dev/null;
|
||||
done;
|
||||
done
|
||||
rm "$1".tmp
|
||||
fi
|
||||
|
||||
# if nulib2 isn't available, patch the disk image to use specified block size
|
||||
if [[ ! $nulib2 && $totalBlocks ]]; then
|
||||
# change total block count
|
||||
bcHex=$(printf "%04X" $totalBlocks);
|
||||
writecharsHex "$1" 1065 "${bcHex:2:2}.${bcHex:0:2}";
|
||||
|
||||
# fix FSB
|
||||
dd if=/dev/zero of="$1" bs=512 seek=280 count=$(( $totalBlocks - 280 )) 2> /dev/null;
|
||||
dd if="$1" of="$1" bs=1 skip=3073 seek=3107 count=$(( ($totalBlocks / 8) - 35 )) conv=notrunc 2> /dev/null;
|
||||
bits=$(( $totalBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
usedString="00000000";
|
||||
freeString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
freeString=$freeString"1";
|
||||
done;
|
||||
binString=$freeString${usedString:$bits};
|
||||
writecharDec "$1" $(( ( ($totalBlocks / 8) - 35) + 3107 )) $(binToDec $binString);
|
||||
fi;
|
||||
|
||||
# assign extra blocks to FSB if needed
|
||||
fsbExtraBlocks=$(( ($totalBlocks-1)/4096 ));
|
||||
if (( fsbExtraBlocks > 0 )); then
|
||||
dd if=/dev/zero of="$1" bs=1 seek=3072 count=$(( (fsbExtraBlocks > 8) + 1 )) conv=notrunc 2> /dev/null;
|
||||
(( fsbExtraBlocks-- ));
|
||||
fi;
|
||||
|
||||
bits=$(( fsbExtraBlocks % 8 ));
|
||||
if (( bits > 0 )); then
|
||||
freeString="11111111";
|
||||
usedString=;
|
||||
for ((b=0; b<$bits; b++))
|
||||
do
|
||||
usedString=$usedString"0";
|
||||
done;
|
||||
binString=$usedString${freeString:$bits};
|
||||
writecharDec "$1" $(( (fsbExtraBlocks>7)+3073 )) $(binToDec $binString);
|
||||
fi;
|
||||
fi
|
@ -1,16 +0,0 @@
|
||||
|
||||
Welcome to A2CLOUD!
|
||||
Instructions and help: http://appleii.ivanx.com
|
||||
|
||||
Type 'a2cloud-help' for a list of A2CLOUD commands.
|
||||
Type 'system-shutdown' to turn off your Raspberry Pi.
|
||||
|
||||
Type 'raspi-config' to configure your Raspberry Pi.
|
||||
Type 'startx' to start the Raspbian desktop.
|
||||
|
||||
Type 'lynx' or 'links' to browse the web and 'cftp' to log into FTP sites.
|
||||
Type 'a2chat' or 'a2news' to talk about Apple II stuff with others.
|
||||
Type 'ttytter' to tweet. Type 'term color' for a color terminal on a IIgs.
|
||||
|
||||
Type 'gsport' or 'kegs' to use the GSport or KEGS Apple IIgs emulators.
|
||||
Type 'linapple' to use the LinApple Apple IIe emulator.
|
@ -1,12 +1,13 @@
|
||||
|
||||
Welcome to A2CLOUD!
|
||||
Welcome to A2SERVER & A2CLOUD!
|
||||
A2CLOUD : virtual hard disk and internet access for any Apple II
|
||||
A2SERVER: network file storage and network boot for Apple IIgs and IIe
|
||||
|
||||
Instructions and help: http://appleii.ivanx.com
|
||||
Type 'a2cloud-help' or 'a2server-help' to see A2CLOUD and A2SERVER commands.
|
||||
|
||||
Type 'a2cloud-help' for a list of A2CLOUD commands.
|
||||
Type 'system-shutdown' to turn off your Raspberry Pi.
|
||||
|
||||
Type 'raspi-config' to configure your Raspberry Pi.
|
||||
Type 'startx' to start the Raspbian desktop.
|
||||
Type 'startx' for the LXDE desktop.
|
||||
Type 'system-shutdown' to turn off your computer or virtual machine.
|
||||
|
||||
Type 'lynx' or 'links' to browse the web and 'cftp' to log into FTP sites.
|
||||
Type 'a2chat' or 'a2news' to talk about Apple II stuff with others.
|
@ -1 +0,0 @@
|
||||
motd-rpi.txt
|
16
setup/motd.txt
Normal file
16
setup/motd.txt
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Welcome to A2CLOUD!
|
||||
Instructions and help: http://appleii.ivanx.com
|
||||
|
||||
Type 'a2cloud-help' for a list of A2CLOUD commands.
|
||||
Type 'system-shutdown' to turn off your Raspberry Pi.
|
||||
|
||||
Type 'raspi-config' to configure your Raspberry Pi.
|
||||
Type 'startx' to start the Raspbian desktop.
|
||||
|
||||
Type 'lynx' or 'links' to browse the web and 'cftp' to log into FTP sites.
|
||||
Type 'a2chat' or 'a2news' to talk about Apple II stuff with others.
|
||||
Type 'ttytter' to tweet. Type 'term color' for a color terminal on a IIgs.
|
||||
|
||||
Type 'gsport' or 'kegs' to use the GSport or KEGS Apple IIgs emulators.
|
||||
Type 'linapple' to use the LinApple Apple IIe emulator.
|
@ -1,233 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# raspbian-update
|
||||
# updates Raspbian to latest version, including NOOBS if installed
|
||||
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1 || isRpi=
|
||||
|
||||
if [[ ! $isRpi ]]; then
|
||||
echo "This ain't a Raspberry Pi."
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
|
||||
skipRepoUpdate=
|
||||
autoYes=
|
||||
updateA2Cloud=
|
||||
updateA2Server=
|
||||
while [[ $1 ]]; do
|
||||
if [[ $1 == "-r" ]]; then
|
||||
shift
|
||||
skipRepoUpdate="-r"
|
||||
elif [[ $1 == "-y" ]]; then
|
||||
shift
|
||||
autoYes="-y"
|
||||
elif [[ $1 == "-n" ]]; then
|
||||
shift
|
||||
noobsOnly="-n"
|
||||
elif [[ $1 == "a2cloud" ]]; then
|
||||
shift
|
||||
updateA2Cloud=1
|
||||
elif [[ $1 == "a2server" ]]; then
|
||||
shift
|
||||
updateA2Server=1
|
||||
elif [[ $1 ]]; then
|
||||
echo "options:"
|
||||
echo "-y: auto-answer yes to all prompts and don't prompt for restart"
|
||||
echo "-r: don't update package repositories"
|
||||
echo "-n: update NOOBS only; don't update Raspbian"
|
||||
echo "a2cloud : update A2CLOUD when complete"
|
||||
echo "a2server: update A2SERVER when complete"
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
noobs=
|
||||
readarray -t partitions < <(sudo fdisk -l | grep '^/dev')
|
||||
if [[ \
|
||||
${partitions[0]:0:14} == "/dev/mmcblk0p1" && ${partitions[0]:57:2} == " e" &&
|
||||
${partitions[1]:0:14} == "/dev/mmcblk0p2" && ${partitions[1]:57:2} == "85" &&
|
||||
${partitions[2]:0:14} == "/dev/mmcblk0p3" && ${partitions[2]:57:2} == "83" &&
|
||||
${partitions[3]:0:14} == "/dev/mmcblk0p5" && ${partitions[3]:57:2} == " c" &&
|
||||
${partitions[4]:0:14} == "/dev/mmcblk0p6" && ${partitions[4]:57:2} == "83" ]]; then
|
||||
noobs=" and the NOOBS install manager"
|
||||
fi
|
||||
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo
|
||||
echo "You are about to update your SD card to the latest version of the"
|
||||
echo "Raspbian operating system${noobs}."
|
||||
echo
|
||||
echo "This may take an hour or more, and will require restarting when complete."
|
||||
echo "You might want a backup before continuing in case it doesn't go as planned."
|
||||
echo
|
||||
echo -n "Update Raspbian? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
origDir="$PWD"
|
||||
cd /tmp
|
||||
|
||||
if [[ ! $skipRepoUpdate ]]; then
|
||||
echo "Updating package repositories..."
|
||||
sudo apt-get -y update > /dev/null
|
||||
else
|
||||
echo "Not updating package repositories..."
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ ! $noobsOnly ]]; then
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
freeSpace=$(df / | tail -1 | awk '{ print $4 }')
|
||||
if (( $freeSpace < 400000 )); then
|
||||
if dpkg -l | grep -q wolfram-engine; then
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo "In order to create enough space on your SD card to upgrade,"
|
||||
echo "the Wolfram Language and Mathematica software packages must be removed."
|
||||
echo "If you don't know what these are, this won't affect you at all."
|
||||
echo
|
||||
echo -n "Remove Wolfram software? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||
fi
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
else
|
||||
echo "Removing Wolfram software due to space constraints..."
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
fi
|
||||
else
|
||||
echo "You don't have enough free space on your SD card to upgrade."
|
||||
echo "Sorry, man. Delete some stuff or get a bigger card."
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
dpkg -l | grep -q a2pi && sudo apt-get -y --force-yes install a2pi
|
||||
dpkg -l | grep -q apple2user && sudo apt-get -y --force-yes install apple2user gsport
|
||||
if dpkg -l | grep -q wolfram-engine; then
|
||||
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||
if [[ $freeSpace -lt 750000 && $(apt-get -s install wolfram-engine | grep upgraded) ]]; then
|
||||
sudo apt-get -y purge wolfram-engine
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
sudo apt-get -y install wolfram-engine
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
sudo apt-get -y install raspberrypi-ui-mods
|
||||
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||
fi
|
||||
|
||||
if [[ $noobs ]]; then
|
||||
echo "Updating NOOBS..."
|
||||
|
||||
# update Partition 3
|
||||
mkdir -p /tmp/p3
|
||||
sudo mount /dev/mmcblk0p3 /tmp/p3
|
||||
sudo rm -rf /tmp/p3/os/* 2> /dev/null
|
||||
if grep -q 'Raspple II' /tmp/p3/installed_os.json; then
|
||||
echo "Downloading Raspple II lite..."
|
||||
noobsUrl="ivanx.com/rasppleii/files/RasppleII_lite.zip"
|
||||
noobsOSurl="ivanx.com/rasppleii/noobs-os"
|
||||
distDir="Raspple_II"
|
||||
sudo mkdir -p /tmp/p3/os/$distDir
|
||||
sudo sed -i 's:/Raspbian:/Raspple_II:' /tmp/p3/installed_os.json
|
||||
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspple_II.png
|
||||
wget -qO- $noobsOSurl/slidesAB.tar | sudo tar -C /tmp/p3/os/$distDir -x
|
||||
else
|
||||
echo "Downloading NOOBS lite..."
|
||||
noobsRoot="downloads.raspberrypi.org/NOOBS_lite/images/"
|
||||
noobsDir=$(wget -qO- $noobsRoot | grep '^<tr><td' | tail -1 | grep -P -o 'href=".*?"' | cut -c 6- | tr -d '"')
|
||||
noobsUrl=$noobsRoot$noobsDir$(wget -qO- $noobsRoot$noobsDir | grep -P -o 'href=".*.zip"' | cut -c 6- | tr -d '"')
|
||||
noobsOSurl="downloads.raspberrypi.org/raspbian"
|
||||
distDir="Raspbian"
|
||||
sudo mkdir -p /tmp/p3/os/$distDir
|
||||
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspbian.png
|
||||
wget -qO- $noobsOSurl/marketing.tar | sudo tar -C /tmp/p3/os/$distDir -x
|
||||
fi
|
||||
sudo rm -rf /tmp/p3/cache 2> /dev/null
|
||||
releaseDate=$(wget -qO- $noobsOSurl/os.json | grep 'release_date' | cut -f 4 -d '"')
|
||||
sudo sed -i 's/"release_date".*$/"release_date" : "'$releaseDate'"/' /tmp/p3/installed_os.json
|
||||
sudo sed -i 's/keyboard_layout=gb/keyboard_layout=us/' /tmp/p3/noobs.conf
|
||||
sudo sed -i 's:/mnt/:/settings/:' /tmp/p3/installed_os.json
|
||||
sudo sed -i 's@"icon".*,@"icon" : "/settings/os/'$distDir'/icon.png",@' /tmp/p3/installed_os.json
|
||||
sudo cp /tmp/p3/icon.png /tmp/p3/os/$distDir
|
||||
sudo wget -qO /tmp/p3/os/$distDir/os.json $noobsOSurl/os.json
|
||||
sudo wget -qO /tmp/p3/os/$distDir/partition_setup.sh $noobsOSurl/partition_setup.sh
|
||||
sudo wget -qO /tmp/p3/os/$distDir/partitions.json $noobsOSurl/partitions.json
|
||||
sudo umount /tmp/p3
|
||||
rmdir /tmp/p3
|
||||
|
||||
# update Partition 1
|
||||
mkdir -p /tmp/p1
|
||||
sudo mount /dev/mmcblk0p1 /tmp/p1
|
||||
wget -qO /tmp/noobs_lite.zip $noobsUrl
|
||||
sudo rm -rf /tmp/p1/*
|
||||
sudo unzip -d /tmp/p1 /tmp/noobs_lite.zip
|
||||
sudo sed -i 's/^runinstaller //' /tmp/p1/recovery.cmdline
|
||||
sudo sed -i 's/silentinstall//' /tmp/p1/recovery.cmdline
|
||||
grep -q 'keyboard=us' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 keyboard=us/' /tmp/p1/recovery.cmdline
|
||||
grep -q 'disablesafemode' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 disablesafemode/' /tmp/p1/recovery.cmdline
|
||||
sudo umount /tmp/p1
|
||||
rmdir /tmp/p1
|
||||
|
||||
sudo sed -i 's/\(Raspple II release.*[^u]$\)/\1u/' /etc/issue
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "*** Raspbian update completed. ***"
|
||||
echo
|
||||
|
||||
cd /tmp
|
||||
|
||||
if [[ $updateA2Cloud ]]; then
|
||||
wget -qO /tmp/a2cloud-setup ivanx.com/a2cloud/setup/
|
||||
source /tmp/a2cloud-setup -y -r noSetGroups
|
||||
if acmd -g /usr/share/gsport/disks/GSport\ Internet\ Starter\ Kit.2mg SYSTEM/FONTS/SIS.4.10 &> /dev/null; then
|
||||
wget -qO /tmp/ua2.txt ivanx.com/rasppleii/files/a/ua2.txt
|
||||
source /tmp/ua2.txt
|
||||
fi
|
||||
echo
|
||||
echo "*** A2CLOUD update completed. ***"
|
||||
echo
|
||||
fi
|
||||
|
||||
cd /tmp
|
||||
|
||||
if [[ $updateA2Server ]]; then
|
||||
wget -q -O /tmp/a2server-setup ivanx.com/a2server/setup/
|
||||
if ps aux | grep -q [s]mbd; then
|
||||
source /tmp/a2server-setup -y -r -w
|
||||
else
|
||||
source /tmp/a2server-setup -y -r
|
||||
fi
|
||||
echo
|
||||
echo "*** A2SERVER update completed. ***"
|
||||
echo
|
||||
fi
|
||||
|
||||
cd "$origDir"
|
||||
|
||||
if [[ ! $autoYes ]]; then
|
||||
echo
|
||||
echo
|
||||
echo "Your system has been updated and needs to reboot to use its new software."
|
||||
echo
|
||||
echo -n "Reboot now (recommended)? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
sudo shutdown -r now
|
||||
fi
|
||||
else
|
||||
echo "*** raspbian-update completed. ***"
|
||||
sudo shutdown -r now
|
||||
fi
|
2042
setup/setup.txt
Normal file → Executable file
2042
setup/setup.txt
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
32
setup/shk2image
Executable file
32
setup/shk2image
Executable file
@ -0,0 +1,32 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# shk2image - Extract .shk files to Apple II disk images
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
origDir="$PWD"
|
||||
[[ ! -n $1 || ! -n $2 ]] && { echo "Usage: shk2image archiveFileName imageFileName [PRODOS.DIR.NAME]"; exit 1; };
|
||||
imageFileName="$2";
|
||||
prodosDir="$3";
|
||||
[[ ! -f "$1" ]] && { echo "Archive file '$1' was not found."; exit 1; };
|
||||
[[ ! -f "$imageFileName" ]] && mkpo "$imageFileName";
|
||||
[[ -n $prodosDir ]] && dirName="$prodosDir/" || dirName=;
|
||||
IFS="";
|
||||
[[ ${1:0:1} == "/" ]] && archiveFile="$1" || archiveFile="$origDir/$1"
|
||||
mkdir -p /tmp/shk2image_temp
|
||||
cd /tmp/shk2image_temp
|
||||
shkFiles=$(nulib2 -xse "$archiveFile" | tr "\r" "~" | cut -d "~" -f 2 | cut -c 18-);
|
||||
cd "$origDir"
|
||||
while read thisFile; do
|
||||
fileName=${thisFile%%#*};
|
||||
fileType=${thisFile##*#};
|
||||
echo "extracting $fileName...";
|
||||
acmd -d "$imageFileName" $dirName$fileName &>/dev/null;
|
||||
acmd -p "$imageFileName" $dirName$fileName \$${fileType:0:2} \$${fileType:2:4} < /tmp/shk2image_temp/"$thisFile"
|
||||
rm /tmp/shk2image_temp/"$thisFile"
|
||||
done <<< $shkFiles
|
||||
rm -r /tmp/shk2image_temp
|
@ -1,24 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
origDir="$PWD"
|
||||
[[ ! -n $1 || ! -n $2 ]] && { echo "Usage: shk2image archiveFileName imageFileName [PRODOS.DIR.NAME]"; exit 1; };
|
||||
imageFileName="$2";
|
||||
prodosDir="$3";
|
||||
[[ ! -f "$1" ]] && { echo "Archive file '$1' was not found."; exit 1; };
|
||||
[[ ! -f "$imageFileName" ]] && mkpo "$imageFileName";
|
||||
[[ -n $prodosDir ]] && dirName="$prodosDir/" || dirName=;
|
||||
IFS="";
|
||||
[[ ${1:0:1} == "/" ]] && archiveFile="$1" || archiveFile="$origDir/$1"
|
||||
mkdir -p /tmp/shk2image_temp
|
||||
cd /tmp/shk2image_temp
|
||||
shkFiles=$(nulib2 -xse "$archiveFile" | tr "\r" "~" | cut -d "~" -f 2 | cut -c 18-);
|
||||
cd "$origDir"
|
||||
while read thisFile; do
|
||||
fileName=${thisFile%%#*};
|
||||
fileType=${thisFile##*#};
|
||||
echo "extracting $fileName...";
|
||||
acmd -d "$imageFileName" $dirName$fileName &>/dev/null;
|
||||
acmd -p "$imageFileName" $dirName$fileName \$${fileType:0:2} \$${fileType:2:4} < /tmp/shk2image_temp/"$thisFile"
|
||||
rm /tmp/shk2image_temp/"$thisFile"
|
||||
done <<< $shkFiles
|
||||
rm -r /tmp/shk2image_temp
|
56
setup/term
Executable file
56
setup/term
Executable file
@ -0,0 +1,56 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# term - a2cloud user command to set TERM variable (to be replaced.)
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
force=1
|
||||
else
|
||||
force=
|
||||
fi
|
||||
|
||||
if [[ ! $1 || $1 == "--help" || $1 == "-h" ]]; then
|
||||
echo 'Usage: term [-d] mono|color|none|<terminalName>';
|
||||
echo ' -d sets default emulation for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
echo ' -f forces change even if not running on serial port (e.g. within "screen")'
|
||||
echo ' Terminal emulation: mono->VT-100, color->PC-ANSI/ANSI-BBS, none->no emulation'
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< $1) == "mono" ]]; then
|
||||
term="vt100"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "color" ]]; then
|
||||
term="pcansi"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "none" ]]; then
|
||||
term="dumb"
|
||||
else
|
||||
term="$1"
|
||||
fi
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/\(ttyAMA0 .*\) .*$/\1 $term/" /etc/inittab;
|
||||
sudo sed -i "s/\(ttyUSB.* .*\) .*$/\1 $term/g" /etc/inittab;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $force || $(tty | grep tty) ]]; then
|
||||
TERM="$term"
|
||||
else
|
||||
echo 1>&2 "Not running on serial port. No action taken. Use -f to set anyway."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tty) current emulation: $(tput bold)$TERM$(tput sgr0)"
|
||||
echo -e "default serial port emulation at login: $(tput bold)$(grep ttyUSB /etc/inittab | sed 's/^.*ttyUSB[^ ]* .* \(.*\)$/\1/')$(tput sgr0)"
|
@ -1,46 +0,0 @@
|
||||
if [[ $1 == "-d" ]]; then
|
||||
shift
|
||||
setgetty=1
|
||||
else
|
||||
setgetty=
|
||||
fi
|
||||
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
force=1
|
||||
else
|
||||
force=
|
||||
fi
|
||||
|
||||
if [[ ! $1 || $1 == "--help" || $1 == "-h" ]]; then
|
||||
echo 'Usage: term [-d] mono|color|none|<terminalName>';
|
||||
echo ' -d sets default emulation for all serial port shells (takes effect on logout)'
|
||||
echo ' omitting -d makes change temporary and immediate'
|
||||
echo ' -f forces change even if not running on serial port (e.g. within "screen")'
|
||||
echo ' Terminal emulation: mono->VT-100, color->PC-ANSI/ANSI-BBS, none->no emulation'
|
||||
else
|
||||
if [[ $(tr [:upper:] [:lower:] <<< $1) == "mono" ]]; then
|
||||
term="vt100"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "color" ]]; then
|
||||
term="pcansi"
|
||||
elif [[ $(tr [:upper:] [:lower:] <<< $1) == "none" ]]; then
|
||||
term="dumb"
|
||||
else
|
||||
term="$1"
|
||||
fi
|
||||
if [[ $setgetty ]]; then
|
||||
sudo sed -i "s/\(ttyAMA0 .*\) .*$/\1 $term/" /etc/inittab;
|
||||
sudo sed -i "s/\(ttyUSB.* .*\) .*$/\1 $term/g" /etc/inittab;
|
||||
sudo init q;
|
||||
sudo pkill -f "/sbin/getty"
|
||||
else
|
||||
if [[ $force || $(tty | grep tty) ]]; then
|
||||
TERM="$term"
|
||||
else
|
||||
echo 1>&2 "Not running on serial port. No action taken. Use -f to set anyway."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$(tty) current emulation: $(tput bold)$TERM$(tput sgr0)"
|
||||
echo -e "default serial port emulation at login: $(tput bold)$(grep ttyUSB /etc/inittab | sed 's/^.*ttyUSB[^ ]* .* \(.*\)$/\1/')$(tput sgr0)"
|
66
setup/ttyusbhandler.txt
Normal file → Executable file
66
setup/ttyusbhandler.txt
Normal file → Executable file
@ -1,4 +1,12 @@
|
||||
#!/bin/bash
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# ttyusbhandler.sh - a2cloud udev handler for USB serial devices (to be replaced)
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
# called by udev as:
|
||||
# ttyusbhandler [add|remove] ttyUSBname
|
||||
@ -20,26 +28,42 @@
|
||||
# rescan for getty
|
||||
|
||||
if [[ $1 == "remove" ]]; then
|
||||
rm /tmp/udev-$2-removed &> /dev/null
|
||||
touch /tmp/udev-$2-removed
|
||||
pkill -f "$2.*ADTPro"
|
||||
rm /tmp/udev-$2-removed &> /dev/null
|
||||
touch /tmp/udev-$2-removed
|
||||
pkill -f "$2.*ADTPro"
|
||||
elif [[ $1 == "add" ]]; then
|
||||
[[ $2 == "ttyUSBlower" ]] && sleep 1.5
|
||||
[[ ${#2} -gt 11 ]] && sleep "${2:15:2}"
|
||||
if [[ $2 == "ttyUSBlower" || \
|
||||
$2 == $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-) || \
|
||||
( ${2:0:12} == "ttyUSBlower_" && $2 != $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-) ) \
|
||||
]]; then
|
||||
rm /tmp/udev-ttyUSBlower-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBlower-added
|
||||
pkill -f "[A]DTPro"
|
||||
pkill -f "[u]sbgetty"
|
||||
exec /usr/local/adtpro/adtpro.sh headless serial
|
||||
else # ttyUSBupper
|
||||
rm /tmp/udev-ttyUSBupper-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBupper-added
|
||||
pkill -f "[g]etty.*ttyUSB"
|
||||
fi
|
||||
[[ $2 == "ttyUSBlower" ]] && sleep 1.5
|
||||
[[ ${#2} -gt 11 ]] && sleep "${2:15:2}"
|
||||
if [[ $2 == "ttyUSBlower" || \
|
||||
$2 == $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | head -1 | cut -c 6-) || \
|
||||
( ${2:0:12} == "ttyUSBlower_" && $2 != $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-) ) \
|
||||
]]; then
|
||||
rm /tmp/udev-ttyUSBlower-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBlower-added
|
||||
pkill -f "[A]DTPro"
|
||||
pkill -f "[u]sbgetty"
|
||||
exec echo "/usr/local/adtpro/adtpro.sh headless serial" | at -M now
|
||||
else # ttyUSBupper
|
||||
rm /tmp/udev-ttyUSBupper-added &> /dev/null
|
||||
touch /tmp/udev-ttyUSBupper-added
|
||||
pkill -f "[g]etty.*ttyUSB"
|
||||
if [[ -f /bin/systemctl ]]; then # if systemd
|
||||
# if USB-to-serial adapter is directly attached to upper port
|
||||
if [[ -c /dev/ttyUSBupper ]]; then
|
||||
ttyUSB=ttyUSBupper
|
||||
# if hub in upper port, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
# if hub in lower port with multiple adapters, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
else
|
||||
# by definition, this shouldn't happen
|
||||
ttyUSB=
|
||||
fi
|
||||
exec systemctl restart usbgetty@$ttyUSB
|
||||
fi
|
||||
fi
|
||||
else
|
||||
exit 2
|
||||
exit 2
|
||||
fi
|
||||
|
42
setup/usbgetty-systemd.service
Normal file
42
setup/usbgetty-systemd.service
Normal file
@ -0,0 +1,42 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This file is adapted for A2CLOUD. It to be called usbgetty@.service
|
||||
# and needs to be placed in /etc/systemd/system/getty.target.wants/
|
||||
# Symlinks pointing to it need to be in place for every serial port
|
||||
# defined in /etc/udev/rules.d/50-usb.rules, e.g.
|
||||
# usbgetty@ttyUSBupper.service -> usbgetty@.service
|
||||
|
||||
[Unit]
|
||||
Description=Serial Getty on %I
|
||||
Documentation=man:agetty(8) man:systemd-getty-generator(8)
|
||||
Documentation=http://0pointer.de/blog/projects/serial-console.html
|
||||
BindsTo=dev-%i.device
|
||||
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
|
||||
After=rc-local.service
|
||||
|
||||
# If additional gettys are spawned during boot then we should make
|
||||
# sure that this is synchronized before getty.target, even though
|
||||
# getty.target didn't actually pull it in.
|
||||
Before=getty.target
|
||||
IgnoreOnIsolate=yes
|
||||
|
||||
[Service]
|
||||
#ExecStart=-/sbin/agetty %I 4800 $TERM
|
||||
ExecStart=-/usr/local/sbin/usbgetty -h -L -scanttyUSB 4800 vt100
|
||||
Type=idle
|
||||
Restart=always
|
||||
UtmpIdentifier=%I
|
||||
TTYPath=/dev/%I
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
KillMode=process
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
62
setup/usbgetty.txt
Normal file → Executable file
62
setup/usbgetty.txt
Normal file → Executable file
@ -1,47 +1,49 @@
|
||||
#!/bin/bash
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# usbgetty.sh - a2cloud script to start a getty on a USB serial devie (to be replaced.)
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
ttyUSB=
|
||||
|
||||
pkill -f "sleep 86399"
|
||||
|
||||
if [[ $(grep -e '-scanttyUSB' <<< "$*") ]]; then
|
||||
# called with -scantty isntead of device name?
|
||||
# echo "-scantty mode"
|
||||
# called with -scantty isntead of device name?
|
||||
|
||||
# if upper USB port
|
||||
if [[ -c /dev/ttyUSBupper ]]; then
|
||||
ttyUSB=ttyUSBupper
|
||||
# if upper USB port
|
||||
if [[ -c /dev/ttyUSBupper ]]; then
|
||||
ttyUSB=ttyUSBupper
|
||||
|
||||
# if hub in upper port, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
# if hub in upper port, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | wc -l) -gt 0 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBupper_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
|
||||
# if hub in lower port with multiple adapters, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
# if hub in lower port with multiple adapters, use highest numbered port on hub
|
||||
elif [[ $(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | wc -l) -gt 1 ]]; then
|
||||
ttyUSB=$(ls -1 /dev/ttyUSBlower_hub* 2> /dev/null | tail -1 | cut -c 6-)
|
||||
|
||||
# no port found eligible for getty
|
||||
else
|
||||
sleep 86399
|
||||
fi
|
||||
|
||||
# no port found eligible for getty
|
||||
else
|
||||
# echo "scantty no devices eligible: sleeping"
|
||||
sleep 86399
|
||||
fi
|
||||
|
||||
# echo "result:$ttyUSB"
|
||||
elif [[ $(grep -o 'ttyUSB[^ ]*' <<< "$*") ]]; then
|
||||
# echo "device specified"
|
||||
# if specified USB device name is found
|
||||
ttyUSB=$(grep -o 'ttyUSB[^ ]*' <<< "$*")
|
||||
# if specified USB device name is found
|
||||
ttyUSB=$(grep -o 'ttyUSB[^ ]*' <<< "$*")
|
||||
else
|
||||
# echo "specified device failed: sleeping"
|
||||
sleep 86399
|
||||
sleep 86399
|
||||
fi
|
||||
|
||||
if [[ -c /dev/$ttyUSB && ! $(ps aux | grep "[g]etty.*$ttyUSB") ]]; then
|
||||
# if adapter seems to exist and doesn't already have a getty,
|
||||
# kill all USB gettys and start the getty, otherwise do nothing
|
||||
pkill -f "/sbin/getty.*ttyUSB"
|
||||
exec /sbin/getty $(sed "s/-scanttyUSB/$ttyUSB/" <<< "$@");
|
||||
# if adapter seems to exist and doesn't already have a getty,
|
||||
# kill all USB gettys and start the getty, otherwise do nothing
|
||||
pkill -f "/sbin/getty.*ttyUSB"
|
||||
exec /sbin/getty $(sed "s/-scanttyUSB/$ttyUSB/" <<< "$@");
|
||||
else
|
||||
# echo "getty already running or doesn't exist: sleeping"
|
||||
sleep 86399
|
||||
sleep 86399
|
||||
fi
|
||||
|
50
setup/vsd
Executable file
50
setup/vsd
Executable file
@ -0,0 +1,50 @@
|
||||
#! /bin/bash
|
||||
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
||||
|
||||
# vsd - a2cloud script to change ADTPro virtual disk image symlinks
|
||||
#
|
||||
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
|
||||
# waived all copyright and related or neighboring rights to the a2cloud
|
||||
# scripts themselves. Software used or installed by these scripts is subject
|
||||
# to other licenses. This work is published from the United States.
|
||||
|
||||
skipWarning=
|
||||
drive=
|
||||
if [[ $1 == "-1" || $1 == "-d1" ]]; then
|
||||
shift
|
||||
elif [[ $1 = "-2" || $1 == "-d2" ]]; then
|
||||
drive=2
|
||||
shift
|
||||
fi
|
||||
if [[ ! $1 ]]; then
|
||||
echo "virtual drive $(( drive ? 2 : 1 )): $(readlink /usr/local/adtpro/disks/Virtual${drive}.po)"
|
||||
else
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
skipWarning=1
|
||||
fi
|
||||
if [[ ! -f $1 ]]; then
|
||||
echo "Image file '$1' was not found."
|
||||
elif [[ -f /usr/local/adtpro/disks/Virtual${drive}.po && ! -L /usr/local/adtpro/disks/Virtual${drive}.po ]]; then
|
||||
echo "/usr/local/adtpro/disks/Virtual${drive}.po is an actual disk image"
|
||||
echo "file, not a symbolic link. Please move or rename it, and try again."
|
||||
else
|
||||
rm /usr/local/adtpro/disks/Virtual${drive}.po &>/dev/null;
|
||||
[[ ${1:0:1} != "/" ]] && pwd="$PWD/";
|
||||
ln -s "$pwd$1" /usr/local/adtpro/disks/Virtual${drive}.po
|
||||
[[ $drive ]] && VSD2="$pwd$1" || VSD1="$pwd$1"
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
if [[ ! $skipWarning ]]; then
|
||||
echo "Please make sure you're not writing to either virtual drive on your Apple II."
|
||||
echo -n " Press return when ready, or control-C to cancel..."
|
||||
read
|
||||
fi
|
||||
sudo pkill -f [A]DTPro
|
||||
while [[ $(ps aux | grep [A]DTPro) ]]; do sleep 1; done
|
||||
/usr/local/bin/adtpro-start
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
unset drive
|
||||
unset pwd
|
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
skipWarning=
|
||||
drive=
|
||||
if [[ $1 == "-1" || $1 == "-d1" ]]; then
|
||||
shift
|
||||
elif [[ $1 = "-2" || $1 == "-d2" ]]; then
|
||||
drive=2
|
||||
shift
|
||||
fi
|
||||
if [[ ! $1 ]]; then
|
||||
echo "virtual drive $(( drive ? 2 : 1 )): $(readlink /usr/local/adtpro/disks/Virtual${drive}.po)"
|
||||
else
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
skipWarning=1
|
||||
fi
|
||||
if [[ ! -f $1 ]]; then
|
||||
echo "Image file '$1' was not found."
|
||||
elif [[ -f /usr/local/adtpro/disks/Virtual${drive}.po && ! -L /usr/local/adtpro/disks/Virtual${drive}.po ]]; then
|
||||
echo "/usr/local/adtpro/disks/Virtual${drive}.po is an actual disk image"
|
||||
echo "file, not a symbolic link. Please move or rename it, and try again."
|
||||
else
|
||||
rm /usr/local/adtpro/disks/Virtual${drive}.po &>/dev/null;
|
||||
[[ ${1:0:1} != "/" ]] && pwd="$PWD/";
|
||||
ln -s "$pwd$1" /usr/local/adtpro/disks/Virtual${drive}.po
|
||||
[[ $drive ]] && VSD2="$pwd$1" || VSD1="$pwd$1"
|
||||
if [[ $(ps aux | grep [A]DTPro) ]]; then
|
||||
if [[ ! $skipWarning ]]; then
|
||||
echo "Please make sure you're not writing to either virtual drive on your Apple II."
|
||||
echo -n " Press return when ready, or control-C to cancel..."
|
||||
read
|
||||
fi
|
||||
sudo pkill -f [A]DTPro
|
||||
while [[ $(ps aux | grep [A]DTPro) ]]; do sleep 1; done
|
||||
/usr/local/bin/adtpro-start
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
unset drive
|
||||
unset pwd
|
Loading…
x
Reference in New Issue
Block a user