Open balshetzer opened 12 years ago
https://oeis.org/wiki/Email_Servers_and_Superseeker https://oeis.org/ol_source.txt
Another possible source for finding the "checksum algorithm(s)" since they seem to be "constant" and only vary with the "stroke number." The "checksums" can be viewed as an "integer sequence" so assuming there is some rhyme or reason to them, algorithms used to find other "integer sequences" may show some hints as to the algorithm/operations involved.
I do have a (very old) Mathematica + license, so may look at ol_source.txt some day. Too many other projects, so little time :)
"superproc8.f / superproc9.f "
Fortran is perversely enticing ... and you thought it was obsolete, noone used it anymore :)
I have not really found any generic "algorithm brute force" program for arbitrary data, but such a thing should not be hard to write...the trick is
1) time to run
2) operations to support between "steps" in the sequence, to go from:
value A -> value B -> value C
this could be a number of operations (add 1st and 2nd bytes, shift 3rd byte left 3, complement
8th byte, etc. -- lots of possible operations and also operands, some possibly involving
constant operands not within the data itself..."add" itself has variants "ignore overflow" or
"store high unit to xth byte" so even that is not so simple...god forbid any of the data is "signed"
and yet more possibilities...
so while a "brute force" in theory would work eventually, it may not be
computationally feasible
3) values may not be on even "byte boundaries", would need to guess the bit and byte endian and also "bit size" (e.g. some values might be 4 bits long, others might be 16, etc.)
Which makes generic "brute force" of the algorithm to go from one "checksum" to the next likely to take too long to be feasible without further information. That said, a "typical" search might be feasible, e.g. assume all values are each one byte long, maybe clamp number of operations per transition to 10.
an interesting tool for visual comparison of arbitrary data:
"Protocol Informatics - Tools for Binary Protocol Analysis"
most things I have seen about reverse engineering say "have lots of time & patience, be prepared to write your own tools"...not sure there are too many "generic" tools out there for data of unknown format...even finding the format of one particular field would narrow things down a lot.
The smarter/quicker approach of course is to debug/decompile steno programs/drivers whose license does not forbid this. Or someone has/makes a contact who knows the details :)
The StenoRam itself, the software on it could likely be "dumped" and decompiled too...no idea of the hardware needed/legality of doing that :) AFAIK in the U.S. reverse engineering is generally allowed by default (IANAL...thank god!)...which is why much software you must agree not to reverse-engineer or decompile/disassemble it in order to use it :)
mashing keys / guessing "common phrases" should produce the TODO bytes.
mashing all 2^23 possible strokes should prove if they are unused or not.
"normal use" might stumble upon them.
steno repair shops apparently have "auto-keyers" to test all keys function....software-controlled this would be quicker than human-mashing :)
i consider myself lucky to have stumbled upon the above byte values for strokes...nothing but guesswork.
this would be the "million monkeys" approach -- alternately, dissasemble existing drivers/programs and see what they do...IANAL.
also, an update to the above "protocol": with an intentionally "long delay" between reading/writing to serial port, I have seen up to 4F strokes per "packet" ... typically on my "modern" PC I normally only ever saw 3, but it seems this can vary a lot / there is a large buffer for slower PCs, so # of strokes per packet can be much more than 3 .....baud rate I use 19200 but no idea if that is required or not.....
0x4F == 79 decimal; assuming the largest case of 79 x 3 byte-strokes == up to 237 bytes of stroke data per "packet"..completely guessing, that might mean the stenoram 3 has an internal buffer of 256 bytes of "pending strokes" for the PC to read at a time.
various software speaks to SR3 differently, so there may be variant or completely different (perhaps backwards-compatible with other Xscribe machines?) protocols the machine supports as well......
my driver based on the above mostly works, but still has occasional hangs. the "serial port activity" icon on my machine's LCD disappears. restarting from the top of the protocol seems to work.......which is bad, but might be able to detect this from the PC side and recover...but probably causes loss of some strokes.......
changing the delay between reads/writes to serial port may or may not "fix" such hangs. my driver is not asynchronous yet, so arbitrary sleeps == prevents needlessly pegging the CPU.
there is also still remaining:
1) "modem transfer" (believe there was an xscribe external modem sold separately, for sending data in stenoram RAM over the phone to a PC at another location...would be surprised if this does not work with other modems, but probably not worth the effort)
2) "COM:SND from RAM" (send saved strokes in SR3 RAM -> PC over serial port" should be relatively easy to find the protocol, just looking at serial data transferred using existing steno programs that implement this. globalcat supports this, i believe.
https://web.archive.org/web/19990125085923/http://globalcat32.com/
I should also add, globalcat documentation (text files after installing program) hints there was a "batch mode" that just output untranslated strokes to a file or whatever...so theoretically for machines plover does not yet support, you could run globalcat32 inside a virtual machine, and route the stroke data to plover / whatever on your "host" machine ...... this feature presumably is not in the "student edition" globalcat though....documentation hints it was activated with a command-line option, but the windows globalcat at the above link does not respond to command-line options from what I tried......presumably a "professional edition" feature only, and/or was removed in later versions and that documentation was outdated. maybe was the DOS version only...which does not seem included in the above download.
3) data the stenoram3 saves on floppy
These may or may not be similar to above protocol. Hopefully they at least use similar stroke format(s), I have not looked at that.
The old Xscribe PC I believe ran some form of CP/M, so "filesystem format" or "directory structure" of files on the floppy might be some variant of that. no idea what software/OS the stenoram itself uses, but presumably that would ease compatibility......
I had the Xscribe PC at some point...
It had PIP on it:
http://en.wikipedia.org/wiki/Peripheral_Interchange_Program
so pretty sure it was CP/M of some kind, with various Xscribe programs on it. "system inside the keyboard" + a nice monochrome monitor too. still worked when I had it :)
IIRC the "tape over floppy hole" trick lets "modern" 1.44 MB floppy drives read the (720k double-density?) floppies the SR3 uses...
IIRC windows (after 95/98/ME?) is stupid, will trash the floppy filesystem if you do not write-protect it...trash it and then say it is "unrecognized" ......
something like:
http://atari.8bitchip.info/FloppyMistery.php
Windows XP simple can not work well with floppy what is not strictly DOS standard formatted. Worst in all is that despite of it, it opens and works with non-standard (for him) floppies. Check of disk format is very superficial - if there is 0xE9 or 0xEB at start and more-less standard BPB, such floppy will be opened.... and messed up.
I don't recall finding a way to format a floppy on the PC side and have the stenoram recognize it...but the stenoram has built-in "format floppy" menu item, and I believe I can read the disk properly from a PC on a "typical" 1.44 MB floppy drive (or the newfangled USB enclosures for them), just have not looked at the data yet.....
If not, there is:
http://en.wikipedia.org/wiki/Individual_Computers_Catweasel http://www.kryoflux.com/
Should not be needed though... IIRC I just put a "standard PC 1.44 MB" floppy drive I had lying around in my SR3 because the one that came with it was flaky...and it works fine...so I believe any trouble reading StenoRAM 3 floppies on the PC side is likely a software and not hardware limitation + windows being stupid.
Ben Tarkeshian has posted notes of reverse engineering a stenoram machine to the point where it might be possible to add plover support.
vim: foldmethod=marker
SR3_REVENG_v0.0.2.txt
CHANGELOG: v0.0.2 no need to clear stenoRAM beforehand; init sequence has the "starting" stroke number for "QUERY" / "NO STROKE" exchanges
DISCLAIMER: {{{
This I believe is the bare minimum for how to write a "working" driver; there are still many gaps and this is still very much a rough draft.
And the usual:
}}}
misc. notes: {{{
stroke data is sent as either:
it seems, whenever a "one byte" stroke is keyed, it is always sent as one byte; this means some combinations of keys for the "2-byte" or "3-byte" stroke formats may not actually ever be seen on the wire
in practice, it shouldn't really matter to a driver; it is unambiguous how to decode 1, 2, and 3-byte strokes;
a single "stroke packet" can contain from 1-3 strokes (that is, up to 3 "really fast" strokes might get crammed in a single packet)
there are (at least) 3 different (what look to be) 8-byte "checksums" --
the 2 "checksums" that seem to be "mandatory" to "understand" are:
both of those seem to only be generated from the "stroke number" count, so it is sufficient (if incredibly ugly) to just log each checksum/stroke number pair and build a table, and then the driver knows what to expect/send; reverse engineering the "checksum" format would still be ideal of course
the 3rd checksum is included with stroke data and I assume more useful, and I assume can be used to detect if corrupted stroke info. was received; understanding it would also be ideal, but it seems like it can be entirely ignored for a "bare minimum" implementation
}}}
some possibly useful tools and documents for finding the "checksum" algorithms {{{
(google these)
}}}
{{{ INIT
1 WRITE:28: 16 03 00 00 01 00 00 FF 09 00 BA DD B5 9A 8A 91 25 A4 03 00 00 FF 00 00 02 01 03 00
2 READ_:26: 16 03 00 00 05 00 00 00 08 00 36 9F F4 8A 4C 0C 3C B5 8E 46 0D 01 53 52 33 20 "S""R""3"" " in ASCII
3 WRITE:28: 16 03 00 00 01 00 00 FF 09 00 99 27 52 26 BD 34 6C F8 04 00 00 FF 00 00 02 01 03 00
4 READ_:21: 16 03 00 00 06 00 00 00 03 00 00 00 00 00 4C A8 18 1A 00 00 00 ^^ ^^ for the SR reply, what matters is the stroke number; the PC should take that stroke number, and
}}}
{{{ INITIAL "QUERY FOR STROKE" EXCHANGE
}}}
{{{ SHUTDOWN
}}} ================================================================================
{{{ FLOW OF EXECUTION
do the "INIT" sequence; this determines at what stroke number the initial "PC QUERY FOR STROKE" and "SR NO STROKE REPLY" bytestrings should start at
until PC starts the shutdown sequence do
{{{ 28 bytes: ( 10 constant bytes: 16 03 00 00 01 00 00 FF 09 00 {{{ * 8 variable (well...hardcoded to stroke number...) bytes: DE 0A BB FF EA 2E 97 41 # 01 00 00 90 C8 55 A6 C8 D2 1C E6 # 01 01 00 4C FD 6C 00 28 C2 EB 3A # 01 02 00 5B F0 AD 04 B7 E2 F1 F9 # 01 03 00 D4 18 93 2A B4 94 BF 07 # 01 04 00 8C 0B 98 46 64 20 5B 4B # 01 05 00 74 12 94 B0 59 82 8C 89 # 01 06 00 D8 BD 8F DA B7 CD FE DD # 01 07 00 4F 34 E2 7C 39 EA 04 F3 # 01 08 00 03 77 9D 85 C4 38 F9 D3 # 01 09 00 00 44 28 CB E8 EA 62 C6 # 01 0A 00 ... }}} 1 constant byte: 01 * 2 variable bytes: Y0 Y1 (stroke number) 7 constant bytes: 00 64 00 02 02 03 00 }}} )
{{{ * 8 variable (well...hardcoded to stroke number...) bytes: 07 01 FF FB 1E C4 6D 92 # 00 00 FF FF FF 00 00 00 00 00 EC 49 41 B3 # 00 00 00 00 00 00 07 05 08 0E 91 4F 4E C5 # 00 00 01 00 00 00 0E 0A 10 1C A5 6C 11 1B # 00 00 02 00 00 00 79 17 2C 4A 7F E8 C4 29 # 00 00 03 00 00 00 1C 14 20 38 38 40 24 E2 # 00 00 04 00 00 00 63 19 28 46 0D D0 CE 55 # 00 00 05 00 00 00 F2 2E 58 94 08 54 6D 95 # 00 00 06 00 00 00 5D 6B 9C E2 AD 78 81 DD # 00 00 07 00 00 00 38 28 40 70 37 38 56 AE # 00 00 08 00 00 00 3F 2D 48 7E 74 12 39 98 # 00 00 09 00 00 00 C6 32 50 8C 26 39 F5 F8 # 00 00 0A 00 00 00 ... }}} 2 constant bytes: 00 00 * 2 variable bytes: Y0 Y1 (stroke number) 2 constant bytes: 00 00 }}} ) end
done
}}}
{{{ STROKE DATA
{{{ the SR sends 25-33 bytes containing stroke information (
{{{ determining the size of the stroke info. "packet" ( if single stroke in this transmission, SR sends 24 + (1, 2, or 3) bytes if two strokes in this transmission, SR sends 24 + (1, 2, or 3) + (1, 2, or 3) bytes if three strokes in this transmission, SR sends 24 + (1, 2, or 3) + (1, 2, or 3) + (1, 2, or 3) bytes:
}}} )
{{{ 24 byte "header" ( constant 8 bytes: 16 03 00 00 03 00 00 00 {{{ variable 1 byte: L0 how many bytes follow the X variables if 1 stroke in this transmission: 07-09 for 2 strokes: 08-0C for 3 strokes: 09-0F (to replicate 0F: try hitting -Z quickly, }}} since a single -Z is sent in 3 bytes) constant 1 byte: 00 {{{ variable 8 bytes: X0 X1 X2 X3 X4 X5 X6 X7 }}} checksum of some sort perhaps {{{ constant 2 bytes: 01 00 indicates: "1 stroke in this packet" 02 00 indicates: "2 strokes in this packet" }}} 03 00 indicates: "3 strokes in this packet" {{{ 2 variable bytes: Y0 Y1 stroke number, increments after every stroke;
}}} 00 0F (Y0 Y1 after the stroke) constant 2 bytes: 00 00 }}} )
{{{ 1-9 bytes of stroke data ( {{{ EITHER ( variable 1 byte: Z0
}}} )
}}} )
}}}