TweetFollow Us on Twitter

XModem Transfer
Volume Number:2
Issue Number:12
Column Tag:Forth Forum

Batch Text File Transfer by XMODEM

By Jörg Langowski, MacTutor Editorial Board, Grenoble, France

If you don't happen to have a tape backup unit for your Macintosh, but access to some larger computer installation over a terminal line (with, usually, lots of disk space), there is a slow but secure way to keep backups of your files by uploading them to that machine. There are all sorts of communication utilities that help in doing so, most of them using the XMODEM protocol for up- and downloading files.

The telecommunications programs I am aware of at this moment are excellent tools for transferring single files to and from the Macintosh. If one wants to back up one full disk by such a file transfer, however, the task becomes a little tedious since one has to select one file at a time; particularly time-consuming if your disk has 327 short text files on it. The XMODEM standard does offer a batch transfer mode in which the filename is transferred followed by the file, and if anyone out there knows of a terminal program that has this mode implemented, please let me know.

For the time being, the transfer of one whole volume on a HFS disk from the Mac to another system by XMODEM batch transfer is a neat little project to implement in Forth. Besides being useful, it'll help us gain some insight into HFS file handling.

We will limit ourselves to transferring text files here. Since you all are aware that files on the Macintosh consist of the data and the resource fork, applications and other resource-containing files have to be changed into text files using a utility like BINHEX first. However based on our example, it is rather easy to implement the MacBinary format [a special standard combining both forks together with the Finder information into one structure: see MacTutor V2#1], and transfer files of any type automatically. At the present time, a text file backup system is fine for me, since the documents I most often have to back up, like manuscripts or current versions of Mach 2 and NEON source files, are text files anyway.

The XMODEM Batch Transfer Protocol

How does an XMODEM file transfer proceed? Each file is split up into sectors of 128 bytes each (a relic of old CP/M times), each sector starting at one. A simple file transfer (not batch mode) has the following protocol:

Simple File Transfer Protocol

Sender Receiver

waits for NAK,

80 sec timeout sends NAK at

10 sec intervals

Loop n times for n sectors

send header:

SOH ($01)

sector no. (0-255)

sector no. complement (255-0)

send sector data, 128 bytes

send checksum:

(header bytes + sector data ) mod 255

compute checksum and

compare with checksum


send ACK ($06) if OK and

NAK if not

If ACK received, increment

sector no.

otherwise resend sector

End Loop

send EOT ($04)

send ACK

The transfer may be cancelled at any time by the sender or receiver transmitting a Ctrl-X ($24) to the other end.

In batch mode, there is an additional protocol defined to transmit the filename before the file transfer starts:

Batch Mode Protocol

Sender Receiver

waits for NAK,

80 sec timeout sends NAK at

10 sec intervals

sends ACK

awaits filename characters,

1 sec timeout

on error -> above NAK

Loop 11 times

send filename char

(bit 7=0, upper case)

add to checksum receive filename char

await ACK 1 sec timeout add to checksum


End Loop

send Ctrl-Z

add to checksum receive Ctrl-Z

add to checksum

send checksum

receive checksum +


ACK if OK and "u" if not await ACK

- Normal file transfer starts -








expect NAK to start new

filename NAK

ACK for new file name

or EOT if finished

The routines necessary to implement this protocol are printed in Listing 1. [For the single file transfer protocol, I adapted some routines from an article by Robert Taylor in Dr. Dobbs Journal 83 (9/1983) p.66.]

The program in Listing 1 is best used by having some terminal emulation like Mockterminal running on the Macintosh at the same time. Mach2 users may append this code directly to the "Terminal Emulator" example on the Mach2 demo disk and then start the terminal emulator before doing the transfer. For other Forths, the program should be easily adaptable, you'll have to change the routines for setting the baud rate and for doing the modem input and output.

Look at the definition of the words send and send-filename and the inner loop of send for the implementation of the XMODEM protocol in Forth.

In order to be able to transfer one whole volume automatically, we must have some means for accessing the files on a volume one by one. The example contains some file and directory handling words for this purpose. I have also left in there some words I needed in testing (like $openWD) which are not used in the actual implementation, but could be useful at times.

The Mach2 word $open opens a file on the default volume, given a name string, and returns a file ID number. In order to access files in any arbitrary folder (= HFS volume), we have to get a volume ID number first and set the default volume to this ID. The word promptvolID calls the standard file package to prompt the user to select a file in the folder that is to be transferred. Then the volume ID of this folder is returned. Calling setvol with a volume ID sets the default volume. getidxfile takes as its input a volume ID and an index n and will look for the n-th file in the volume. The filename is returned in a global parameter block, parblock, and can be used to open the file with $open after setting the correct default volume. send-batch simply scans the default volume for all files and transfers them one by one. So far, for text files only. Have fun implementing the MacBinary standard.

Reader Feedback

I got several comments on the floating point routines that we published lately. Ed Moskowitz from Winfield, IL points out correctly that the routines will not work with the new Mach2 since they use D5 and D6. This is correct, and D5 and D6 have to be added to the MOVEM.L save and restore list at the routine entry and exits to fix this bug.

Mike Morton from Cambridge, MA had some useful comments to make about improving the speed of those routines. Excerpts from his letter:

"• If you're doing lots of _Pack4 calls, you can do a GetTrapAddress and call the package directly, saving 30 to 50 microseconds ( )

• Instead of BTST #7, D0, you can do TST.B D0 and use BMI to see if the bit is on.


• when you AND #$7FFFFF to both D3 and D1 in the division routine, it's faster to move the mask to a register just once and use it twice. ( )

• When you're doing multiplications [and divisions, JL], you might optimize for cases where some of the number is zero. So your four MULUs might test whether the operands are zero and handle that case explicitly. I spent some time writing 32-bit fixed-point multiply routines a while ago, and this helped a lot because many numbers don't have any bits on the bottom of the longword. If you expect many of the f.p. numbers to not have many significant bits, this helps some.

( ) "

Thanks, Ed and Mike, for your comments.


One letter came clear from Tasmania, from Phil Barnard:

" I am suffering from the new ROM syndrome at the moment, although the faster and more spacious drives are very pleasant after the original units. Having to replace the interrupt vectors for the interrupt button was a nuisance. As you are no doubt aware the new ROM/System does not present the familiar bomb-box, but an 'empty' dialog.

It may be that the new dialog can be used to resume in the same fashion as the old one, but I don't yet know how. G <return> sends it back into any loop that you may wish to exit. Looking at the register contents by typing A0 through D7 is of limited debugging use. Can it do anything else?"

[Why, I even installed a control panel with flashing LEDs and toggle switches on the top of my Mac. Why do you want anything else? ... Well, G 40F6D8, of course, you probably know by now that that is the address of _Exittoshell and will (sometimes) send you straight back to the Finder. I don't use it for many other things. JL]

"The following routine brings back the old familiar bomb-box on interrupt."

\ installation of custom interrupt vectors; Phil Barnard
\ prints out the seven vectors from the interrupt table
: get.ints ( -- ) cr
 $ 64 -base @ . cr \ VIA
 $ 68 -base @ . cr \ SCC
 $ 6C -base @ . cr \ VIA & SCC
 $ 70 -base @ . cr \ Debugging Button
 $ 74 -base @ . cr \     "
 $ 78 -base @ . cr \     "
 $ 7C -base @ . cr \     "


\ installs RTS in the last four (debugging) vectors in the interrupt 

: put.ints ( -- )
 $ 80 $ 70 do 'c RTS +base i -base ! 4 +loop get.ints ;

Thanks, Phil. I'll deal with more NEON stuff in the next column where I'll also have some time to write about the new release of NEON, version 2.0. Here only a few headlines:

• NEON 2.0 is fully HFS and Switcher compatible; a new class pathlist has been added to specify HFS search paths. The assembler supports the new ROM calls.

• Applications install as a one piece file, no need to keep a copy of the installed NEON kernel on the disk.

• A decompiler has been added that will handle simple definitions, classes, objects and methods.

• A number of bugs, including the famous IC! have been fixed.

More details about NEON 2.0 and other NEON things later. Till then, good holidays.

Listing 1: XMODEM batch file downloader

( Implementation of Modem7 file transfer protocol, 
 © 9/86 J. Langowski  for MacTutor )

only forth also mac also i/o also assembler

60 user fileID

10 constant maxerr   0 constant nul24 constant can
4 constant eot   6 constant ack  21 constant nak
1 constant soh   26 constant ctrl-z
117 constant bdnmch

" Select file on volume to upload:" constant seldirtext

variable time-ct variable nak-ct variable cksum    
variable filename 128 vallot
variable xbuffer 128 vallot
variable replyrecord 74 vallot

header parblock 12 allot  ( 12 bytes junk )
header iocompl   4 allot  ( at PB + 12 )
header iores     8 allot  ( at PB + 16 )
header ioref#    4 allot  ( at PB + 24 )
header iomisc    4 allot  ( at PB + 28 )
100 allot ( some elbow room )

: long-timeout  1000 time-ct ! ; (  17 sec timeout )
: short-timeout 100  time-ct ! ; ( 1.7 sec timeout )

: baud-rate ( - )
 1CC0A COMM1 mode  ( 9600 BAUD Xon/Xoff )
 ABORT" Serial Driver Error" ;  (8 bit, No Par, 2Stop)
: modout comm1 output emit console output ;
: fin can modout ;  : fini fin close-file ;

: timed-read { | tstart -- char }
 call tickcount -> tstart
 comm1 input
 ?terminal if key console input exit then
 call tickcount tstart -  time-ct @ > 
 console input  -1

: ?contrlx ?terminal 
 if key 24 = 
 if fini 1 abort" Control-X abort" then

: wait-ack { | errs -- }
 0 -> errs 
 begin  errs maxerr >  nak-ct @ maxerr > or
 if fini 1 abort" Max error count exceeded." then
 timed-read case
 -1  of errs 1+ -> errs ." Timeout" cr endof
 can of 1 abort" Remote Cancel" endof
 ack of 0 nak-ct !  exit endof
 nak of 1 nak-ct +! exit endof
 ( disp-chr 0 )

: send-setup
 standard-getfile  0= 
 if fin 1 abort" Cancelled." then
 0 nak-ct !

: read-sect { sector# | sect-start -- }
 sector# 128 * -> sect-start
 128 0
 do i sect-start + virtual c@ i xbuffer + c! loop

: send-filename
 ack modout 0 cksum c!
 12 1 do filename i + 
 c@ 127 and dup 95 > if 32 - then
 dup modout dup emit
 cksum c@ + cksum c!
 loop cr
 ctrl-z modout 
 cksum c@ ctrl-z + cksum c!
: send-hdr { sector# | -- }
 soh modout
 sector# 1+ 255 and dup modout 255 xor modout
 ." Sending " sector# . cr

: send-sect ( send sector in xbuffer via XMODEM )
 0 ( sum )
 128 0 do xbuffer i + c@ dup modout + 255 and loop
 cksum c!
: send-cksum cksum c@ modout ;

: end-send
 begin cr ." Sending EOT -" eot modout wait-ack
 nak-ct @ 0= until
 ." ack'd"

: get-file-length ( -- sectors )
 fileID w@ ['] ioref# w!  0 ['] iocompl !
 ['] parblock call geteof . cr
 ['] iomisc @ 128 /mod swap 
 if 1+ then
 dup ." File has " . ."  sectors" cr 
: send ( current file via XMODEM, closes file on exit )
 get-file-length 0
 i read-sect ( into xbuffer )
 i send-hdr send-sect send-cksum
 wait-ack nak-ct @ 0=

: prelude
 short-timeout  begin timed-read -1 = until
 long-timeout  ." Awaiting initial NAK: "
 wait-ack cr   short-timeout

: send-one send-setup prelude send ;

: end-batch ack modout eot modout ;

( *** file and directory  handling routines *** )

: getVolID { index | pb -- VRefNum / errcode 0 }
 ( ID for volume no. index )
   ['] parblock -> pb
 0 ['] iocompl !
 filename pb 18 + !
 index pb 28 + w!
 pb call getvolinfo
 ?dup if 0 else pb 22 + w@ then

CODE SFGetFile  ( x y prompt numTypes typeList ReplyRecord )
 MOVE.L (A6)+,A1 ( reply record )
 MOVE.L (A6)+,A0 ( type list )
 MOVE.L (A6)+,D3 ( numTypes )
 MOVE.L (A6)+,D2 ( prompt )
 MOVE.L (A6)+,D1 ( y-coord )
 MOVE.L (A6)+,D0 ( x-coord )

 MOVE.W D0,-(A7)
 MOVE.W D1,-(A7) ( where )
 MOVE.L D2,-(A7) ( prompt )
 MOVE.L #0,-(A7) ( no filter proc )
 MOVE.W D3,-(A7) ( num Types )
 MOVE.L A0,-(A7) ( type list )
 MOVE.L #0,-(A7) ( no dialog hook )
 MOVE.L A1,-(A7) ( reply record )

 MOVE.W #2,-(A7)

: promptvolID  ( -- VRefNum flag )
 100 50 seldirtext -1 0 replyrecord 
 replyrecord 6 + w@ l_ext
 replyrecord w@ l_ext

 MOVE.L (A6)+,A1
 MOVE.L (A6)+,A0
 MOVE.L (A6)+,D3
 MOVE.L (A6)+,D2
 MOVE.L (A6)+,D1
 MOVE.L (A6)+,D0

 MOVE.W D0,-(A7)
 MOVE.W D1,-(A7)
 MOVE.L D2,-(A7)
 MOVE.L D3,-(A7)
 MOVE.L A0,-(A7)
 MOVE.L A1,-(A7)

 MOVE.W #1,-(A7)

: $openWD { name | pb -- VRefNum / errcode 0 }
   ['] parblock -> pb
 0 ['] iocompl !
 name pb 18 + !
 0 pb 28 + w!
 pb 1 call HFSDispatch
 ?dup if 0 else pb 22 + w@ then

: closeWD { volume | pb -- rescode }
   ['] parblock -> pb
 0 ['] iocompl !
 volume pb 22 + w!
 pb 2 call HFSDispatch

: setVol { volume | pb -- res code }
   ['] parblock -> pb
 0 ['] iocompl !
 0 pb 18 + !
 volume pb 22 + w!
 pb call setVol
: getidxfile { volume index | pb -- res code }
   ['] parblock -> pb
 0 ['] iocompl !
 filename pb 18 + !( ioNamePtr )
 volume pb 22 + w! ( ioVRefNum ) 
 0 pb 26 + w!  ( ioFVersNum )
 index pb 28 + w!( ioFDirIndex )
 pb call getfileinfo 
 dup 0= if ." Found: " filename count type cr then

: openidxfile { volume index | -- res code }
 volume index getidxfile
 ?dup 0= if filename $open then

: find-files { | volume index -- }
 if -> volume 1 -> index
 volume index getidxfile
 index 1+ -> index
 else ." cancelled" . cr 
( *** main definitions for batch file transfer *** )
: display-filename
 12 1 do filename i + c@ 127 and dup 95 > if 32 - then emit
 loop cr
: send-batch{ volume | index }
 1 -> index  0 nak-ct ! 
 begin cr
 filename 1+ 11 32 fill
 volume index getidxfile 0= 
 volume setvol drop 
 filename $open dup 0> 
 if   fileID w!
 prelude send-filename
 timed-read cksum c@ <> 
 ." Checksum Error in filename, restarting" cr
 bdnmch modout
 ack modout
 send ( closes file )
 else drop 
 index 1+ -> index
 wait-ack end-batch
: upload 
 if send-batch 
 else cr ." Cancelled" cr

Community Search:
MacTech Search:

Software Updates via MacUpdate

Apple Remote Desktop 3.8 - Remotely cont...
Apple Remote Desktop is the best way to manage the Mac computers on your network. Distribute software, provide real-time online help to end users, create detailed software and hardware reports, and... Read more
NeoOffice 2014.7 - Mac-tailored, OpenOff...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
DesktopLyrics 2.6.6 - Displays current i...
DesktopLyrics is an application that displays the lyrics of the song currently playing in "iTunes" right on your desktop. The lyrics for the song have to be set in iTunes; DesktopLyrics does nothing... Read more
Ember 1.8.3 - Versatile digital scrapboo...
Ember (formerly LittleSnapper) is your digital scrapbook of things that inspire you: websites, photos, apps or other things. Just drag in images that you want to keep, organize them into relevant... Read more
Apple iTunes 12.1 - Manage your music, m...
Apple iTunes lets you organize and play digital music and video on your computer. It can automatically download new music, app, and book purchases across all your devices and computers. And it's a... Read more
LibreOffice 4.4.3 - Free, open-source of...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
FoldersSynchronizer 4.2.1 - Synchronize...
FoldersSynchronizer is a popular and useful utility that synchronizes and backs-up files, folders, disks and boot disks. On each session you can apply special options like Timers, Multiple Folders,... Read more
Simon 4.0.2 - Monitor changes and crashe...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
Cocktail 8.1.2 - General maintenance and...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
Cyberduck 4.6.4 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more

Playworld Superheroes Review
Playworld Superheroes Review By Tre Lawrence on January 30th, 2015 Our Rating: :: HERO CRAFTINGUniversal App - Designed for iPhone and iPad It’s all about the imagination, fighting bad creatures — and looking good while doing so.   | Read more »
Join the SpongeBob Bubble Party in this...
Join the SpongeBob Bubble Party in this New Match 3 Bubble Poppin’ Frenzy Posted by Jessica Fisher on January 30th, 2015 [ permalink ] | Read more »
Handpick Review
Handpick Review By Jennifer Allen on January 30th, 2015 Our Rating: :: TANTALIZING SUGGESTIONSiPhone App - Designed for the iPhone, compatible with the iPad Handpick will make you hungry, as well as inspire you to cook something... | Read more »
Storm the Halls of Echo Base in First St...
Storm the Halls of Echo Base in First Star Wars: Galactic Defense Event Posted by Jessica Fisher on January 30th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Contradiction Review
Contradiction Review By Tre Lawrence on January 30th, 2015 Our Rating: :: SPOT THE LIEiPad Only App - Designed for the iPad Contradiction is a live action point and click adventure that’s pretty engaging.   Developer: Tim Follin... | Read more »
Unlock Sunshine Girl in Ironkill with th...
Unlock Sunshine Girl in Ironkill with this special 148Apps code Posted by Rob Rich on January 29th, 2015 [ permalink ] Robo-fighter Ironkill has been out on iOS a | Read more »
Crossroad Zombies Review
Crossroad Zombies Review By Jordan Minor on January 29th, 2015 Our Rating: :: CROSSWALKING DEADiPad Only App - Designed for the iPad Crossroad Zombies is a rough draft of a cool genre mash-up.   | Read more »
Blood Brothers 2 – Tips, Cheats, and Str...
War is hell: Is it the kind of hell you want to check out? Read our Blood Brothers 2 review to find out! Blood Brothers 2, DeNA’s follow-up to the original Blood Brothers, is an intriguing card collecting / role-playing / strategy hybrid. There’s... | Read more »
Blood Brothers 2 Review
Blood Brothers 2 Review By Nadia Oxford on January 29th, 2015 Our Rating: :: AN AGGRAVATING RELATIVEUniversal App - Designed for iPhone and iPad Blood Brothers 2 is built on a simple, solid foundation, but its free-to-play system... | Read more »
I AM BREAD, the Toast of the Town, is Ro...
Have you ever dreamt of being deliciously gluten-y? Do you feel passionate about Rye and Wheat? The guys at Bossa Studios do and that is why they are bringing I AM BREAD to iOS soon. The loafy app will feature all the new content that is being... | Read more »

Price Scanner via

Intel Aims to Transform Workplace With 5th-Ge...
Intel Corporation today announced the availability of its 5th generation Intel Core vPro processor family that provides cutting-edge features to enable a new and rapidly shifting workplace. To meet... Read more
iOS App Sharalike Introduces New Instant Smar...
Sharalike slideshow and photo management software for iOS, is making it easier than ever to create shareable meaningful moments with its new instant SmartShow technology. Staying organized is a goal... Read more
Apple Becomes World’s Largest Smartphone Vend...
According to the latest research data from Strategy Analytics, as global smartphone shipments grew 31 percent annually to reach a record 380 million units in the fourth quarter of 2014. Apple became... Read more
Cut the Cord: OtterBox Resurgence Power Case...
Dead batteries and broken phones are two of the biggest issues for smartphone users today. Otterbox addresses both with the new Resurgence Power Case for Apple iPhone 6, promising to make those panic... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has 13″ Retina MacBook Pros on sale for $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1199.99 save $100 - 13″ 2.6GHz/... Read more
15-inch 2.5GHz Retina MacBook Pro on sale for...
 B&H Photo has the 15″ 2.5GHz Retina MacBook Pro on sale for $2319.99 including free shipping plus NY sales tax only. Their price is $180 off MSRP, and it’s the lowest price available for this... Read more
Back in stock: Refurbished iPod nanos for $99...
The Apple Store has Apple Certified Refurbished 16GB iPod nanos available for $99 including free shipping and Apple’s standard one-year warranty. That’s $50 off the cost of new nanos. Most colors are... Read more
Apple lowers price on refurbished 256GB MacBo...
The Apple Store has lowered prices on Apple Certified Refurbished 2014 MacBook Airs with 256GB SSDs, now available for up to $200 off the cost of new models. An Apple one-year warranty is included... Read more
New Good Management Suite Simplifies Enterpri...
Good Technology has announced the availability of the Good Management Suite, a comprehensive cross-platform solution for organizations getting started with mobile business initiatives. Built on the... Read more
15-inch 2.0GHz Retina MacBook Pro (refurbishe...
The Apple Store has Apple Certified Refurbished previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1489 including free shipping plus Apple’s standard one-year warranty. Their price is... Read more

Jobs Board

At-Home Chat Specialist- *Apple* Online Stor...
**Job Summary** At Apple , we believe in hard work, a fun environment, and the kind of creativity and innovation that only comes about when talented people from diverse Read more
Sr. Mac Expert- *Apple* Online Store - Apple...
**Job Summary** The World Wide Apple Online Store (AOS) Sales and Service team is looking for motivated, outgoing, and tech savvy individuals who want to offer Apple Read more
*Apple* Solutions Consultant- Retail Sales (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
At-Home Chat Specialist- *Apple* Online Stor...
**Job Summary** At Apple , we believe in hard work, a fun environment, and the kind of creativity and innovation that only comes about when talented people from diverse Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.