====================================================================== Instructions for the 1541-dos package (January 4, 1994 version) ====================================================================== These are the instructions on how to read and write to MS-DOS floppy disks with a slightly modified Commodore 1541 or Oceanic OC-118/OC-118N disk drive. Included is information about the necessary modification of the 1541 drive and the usage of the programs in this package. CONTENTS -------- 1) Hardware requirements 2) MFM modification 2A) 1541 disk drive modification 2B) 1541 disk drive modification -- first alternate 2C) 1541 disk drive modification -- second alternate 2D) Oceanic OC-118/OC-118N disk drive modification 3) Preparing disks for data transfer 4) Transferring files from MS-DOS disks to CBM disks with "1541-reads-dos" 5) Transferring files from CBM disks to MS-DOS disks with "1541-writes-90k" and "read90k" 6) Error messages 7) Compatibility 8) Possible improvements 9) Disclaimer 10) Contacting the authors APPENDIX A: Listing of BASIC program 1541-dos.boot APPENDIX B: C-version of Read90k for Unix ----------------------------------------------------------------------- 1) HARDWARE REQUIREMENTS You require a C64 or C128 (in C64 mode) with at least one 1541 or OC-118/OC-118N floppy disk drive. The drive must be modified slightly to allow it to utilize the MFM method of storing data used on MS-DOS compatible disks. This modification does not affect the normal operation of the drive. If you don't have experience in soldering circuit boards then find someone who does; the modification is small, but tricky, and will void the warranty on your disk drive. The 1541 can then read single sided, double density disks written by MS-DOS computers with 5 1/4" inch disk drives. You need an MS-DOS computer with at least one 5 1/4" floppy drive and one other writable disk device (a floppy, hard or RAM disk drive) to read files written by the 1541. ----------------------------------------------------------------------- 2) MFM MODIFICATION WARNING: the disk drive motherboard can be easily damaged by static electricity. Don't work on this project wearing synthetic clothes and rubber shoes on a nylon carpet and expect your drive to come through unscathed! Use of a grounded soldering iron is recommended, as is minimizing contact with the board. As long as you take reasonable precautions, no damage should occur to your disk drive by following these instructions. However, differences between board revisions make it impossible to guarantee that the modifications described here will work on your disk drive. Caveat emptor! The clock divisor is a 74LS193 hexadecimal counter in the 1541, and the similar 74LS161 in the Oceanic drives. The CPU loads the number to start counting at on its inputs and the overflow from the counter is chained to the next portion of the circuit. Of the 4 counter inputs, the lower two are controlled by the CPU and the higher 2 are tied to ground. This means values of 0 through 3 on the counter inputs require 16 to 13 counts (respectively) before overflow, thus dividing the input by that amount. The range of clock rates that can be generated with those divisors is from 250 kHz to 307 kHz. Modifying the 1541 to read MFM disks involves placing the higher two bits of the counter under CPU control. That allows a full range of divisors from 1 through 16, an even greater range than the divide by 8 required for a 500 kHz clock. In fact, only one additional counter input needs to be under CPU control, but while we're in the drive with a soldering iron, why not connect the other one too? It might be required to read other disk formats in the future. Once you've chosen one of the modification instructions below and completed it, take one last look at your work. Look especially for solder bridges and wires touching adjacent pads. Next, re-attach any connectors, screw the drive together and plug it in. Before attaching it to your C64, try turning it on. If you don't hear anything unusual and don't smell smoke, your drive has passed the first test! Turn the drive off and plug it into your computer. Turn them both on and try loading a program from a noncritical 1541 disk. If it reads fine and doesn't erase the disk, then move to the next section and try reading an MS-DOS disk. If it doesn't work properly, open the drive again and compare your work to the instructions carefully. 2A) 1541 DISK DRIVE MODIFICATION This section describes the easiest modification to make to your 1541, and has the potential of working with more disk formats than just MS-DOS MFM (using future software). The disadvantage is that part of the unused I/O port A is required, which means that the port cannot be used with a fast loading device that requires a parallel cable connection to the 1541 (standard fast loader cartridges work fine). Use one of the alternate modifications if you want to use such a fast loader. The unused I/O port available on the first 6522 versatile interface adapters (VIA) can be connected to the counter's extra inputs (which are normally connected to ground) and used to extend the clock frequency range. Since the port is also at ground potential upon reset, the clock circuitry is not affected by the modification. Refer to the figure in file 1541CLK.GIF while making these modifications. Unplug your 1541 and remove its cover by unscrewing the four screws on the bottom of the case. Locate the controller PCB and unplug the transformer connector near the regulator ICs and heat sink. Remove the screws attaching the PCB to the chassis, including the two screws attached to the regulator heat sink, and tilt the board up. Locate UE6 (the 74LS193 counter IC) and cut the traces going to pins 9 and 10; make sure the two pins are not still connected to each other, too. Carefully solder a short wire to pin 9 and another one to pin 10. Locate UC3 (6522 VIA) and solder the other end of the first wire (from UE6 pin 9) to UC3 pin 3 (which is otherwise unconnected). Solder the other end of the second wire (from UE6 pin 10) to UC3 pin 2 (also otherwise unconnected). Currently, only the jumper to UE6 pin 9 is required to read IBM diskettes. If you want to save yourself soldering one jumper, you may leave UE6 pin 10 connected to ground. The jumper to UE6 pin 10 may be required in the future to read other new and exciting disk formats. 2B) 1541 DISK DRIVE MODIFICATION -- FIRST ALTERNATE Use the following modification instructions if you want to leave the first VIA's unused port A alone. You'll need a 4.7 kilohm resistor to perform this modification (although anything 3.3k to 10k should also work). Besides all of port A, pin CA1 of the first VIA is also unused in a stock 1541. Unfortunately, it goes high (not to ground) when reset and can't be directly connected to the counter's input for the drive to be able to read regular 1541 disks at power up. Instead, an unused inverter is used to invert the high signal to low, which is then connected to the counter. Unplug your 1541 and remove its cover by unscrewing the four screws on the bottom of the case. Locate the controller PCB and unplug the transformer connector near the regulator ICs and heat sink. Remove the screws attaching the PCB to the chassis, including the two screws attached to the regulator heat sink, and tilt the board up. Locate UE6 (the 74LS193 counter IC) and cut the trace going to pin 9; make sure the pin 9 isn't still connected to pin 10. Carefully solder a short wire to pin 9. Locate UB1 (7406 open-collector hex inverter) and verify that pins 5 and 6 are unconnected. Solder the other end of the wire and one end of the resistor to pin 6. The other end of the resistor must be soldered to pin 14 (Vcc). Locate UC3 (6522 VIA) and solder a short length of wire between pin 39 (CA2) and pin 5 of UB1. 2C) 1541 DISK DRIVE MODIFICATION -- SECOND ALTERNATE If you don't have a resistor handy, or are modifying a 1541 compatible disk drive that doesn't have an unused port or inverter (or even one that does, like the OC-118), then you may be forced to use this alternate modification. A switch is installed which allows you to choose to read normal 1541 disks when down or MFM disks when up. Locate UE6 (the 74LS193 counter IC) and cut the trace going to pin 9; make sure the pin 9 isn't still connected to pin 10. Carefully solder a short wire between pin 9 and the middle position of a SPDT switch. Connect one remaining switch contact to ground and the other to Vcc (+5 V). To use regular 1541 disks, switch to the ground position. To use MFM disks, switch to the +5 V position. 2D) OCEANIC OC-118/OC-118N DISK DRIVE MODIFICATION The OC-118 and OC-118N are third party 1541-compatible disk drives. They appear similar to the Amiga external disk drives in that they are compact and have an external power supply. Their circuitry is slightly different from that of the 1541, and they require a different modification. This description is equivalent to the first alternate 1541 modification above, so you'll need a 3.3k to 10k kilohm resistor. Locate U4 (74LS161 counter IC) on the board in the top right of the diagram. There may be another U4 on a different board, so make sure the U4 you use has 74LS161 written on it. Cut the trace between pin 6 of U4 and GND and solder a short wire to pin 6. Locate U15 (7406 open- collector hex inverter) and solder the other end of the wire and one end of the resistor to pin 8 (which should otherwise be unconnected). Connect the other end of the resistor to pin 14 (Vcc). Locate U8 (6522 VIA) and solder a short length of wire between pin 39 (CA2) and pin 9 of U15. U1,3,5 U2,4,6 ____________ _____ U7,9 U8,10 !! \ =MMMMM=========__ / ! H#H H#H H !! --------------------- ! ============== !! servo card motherboard ! MMH -- connectors !! - - - - - - - - - - - - - - - -!================ !!_______________________W_W_W_W_W_W_W___! H#H H#H " U1...9 U10...U18 OC-118, OC-118N - side view ----------------------------------------------------------------------- 3) PREPARING DISKS FOR DATA TRANSFER The 1541 drive only has a single head to read single-sided disks. This means you need disks formatted with the 180 KB MS-DOS format (40 tracks on a single side, 9 sectors per track with a sector size of 512 bytes). Such disks can be formatted using the MS-DOS FORMAT command on double density disks with the /1 command line option. E.g.: FORMAT /1 A: If you use a high density disk drive (1.2 MB) you will also have to use the /4 command line option to create double density format. E.g.: FORMAT /1 /4 A: Newer versions of MS-DOS allow the /F switch which will work on both kinds of drives. E.g.: FORMAT /F:180 A: If you use other programs to format disks instead of the MS-DOS FORMAT command, you may have to use different parameters to generate disks with exactly the disk organization 1541-reads-dos expects. E.g. with the public-domain program FDFORMAT you have to use FDFORMAT A: /F:180 /C:1 /D:64 These are the boot sector parameters for a 1541-reads-dos readable disk: Bytes per sector: 512 Sectors per Cluster: 1 Reserved Sectors at beginning: 1 FAT Copies: 2 Root directory entries: 64 Total sectors on disk: 360 Sectors per FAT: 2 Sectors per track: 9 Sides: 1 High density drives use a narrower read/write head than double density drives and the 1541. Therefore, you should not write to a double density disk with a high density drive if the disk has previously been written to by one of those drives with its wider read/write head. ----------------------------------------------------------------------- 4) TRANSFERRING FILES FROM MS-DOS DISKS TO CBM DISKS WITH "1541-reads-dos" You need the program 1541-reads-dos to read files from MS-DOS disks. If you have no other way of transferring it to the C64, you can type in the BASIC listing of 1541-dos.boot in Appendix A to read 1541-dos.sfx for the first time. The program 1541-reads-dos copies files in the root directory of a 180 KB MS-DOS disk to a CBM disk. It can be loaded and started like a BASIC program. The user interface is dialogue oriented, so you have to input data when asked for it. You can accept default values by simply pressing the RETURN-key. At the beginning it will ask for the device number of the 1541 drive modified for MFM reading. This is the drive the MS-DOS source disk will be read from. Next you have to enter the device number of the drive the file shall be copied to. This can be any Commodore compatible disk drive. You can enter equal numbers for both drives; the program will then work with a single 1541 disk drive. However, the program will be a bit slower and you will have to swap disks quite frequently. You may then let the program start reading format and directory information from an MS-DOS disk. Only the root directory is supported -- you can not copy from subdirectories. With each file you are given the option of copying it to a CBM disk. If you decide to copy a file, you must enter a text conversion number. If you enter 0, the file will be copied without conversion. With number 1, you select conversion from ASCII to CBM character set (PETSCII); number 2 stands for conversion from ASCII to Data Becker C-editor format. The latter uses the CBM character set extended by characters needed for the programming language C. Characters that do not exist in the destination character set are ignored. Tab characters are converted to single spaces. Note that uuencoded files can contain characters (backslash and underscore) that do not exist in CBM character set. In detail, conversion is done according to the following tables: ASCII -> CBM ------------------- 0..7 - 8 32 9 - 10 13 11..31 - 32..64 32..64 65..90 193..218 91 91 92 - 93..94 93..94 95..96 - 97..122 65..90 123..255 - ASCII -> C-editor ------------------------ 0..7 - 8 32 9 - 10 13 11..31 - 32..64 32..64 65..90 193..218 91..95 91..95 96 - 97..122 65..90 123..126 219..222 127..255 - Text conversion can take quite a while, leading to pauses during the copy process. After selecting the conversion number you can specify the destination file type. PRG-, SEQ- and USR-files can be created. Next, the name of the destination file has to be entered. The default filename is the MS-DOS name with lower case letters. After files have been selected the copy process can be started. With different source and destination disk drives all files are copied without any further user interaction necessary. When a single drive is used, you have to swap disks for every file. Long files require additional swapping. At the end you can decide to start copying from another MS-DOS disk. Otherwise the program will be terminated by issuing a reset of both the C64 and the MFM- disk drive. ----------------------------------------------------------------------- 5) TRANSFERRING FILES FROM CBM DISKS TO MS-DOS DISKS WITH "1541-writes-90k" AND "read90k.com" A special 90k-format is used for transferring files to MS-DOS computers. This is not a regular MS-DOS format, although it uses formatted 180 KB MS-DOS disks. The program 1541-writes-90k writes a file with a maximum length of 91904 bytes to a disk using the 90k-format. All previous data on this disk is overwritten. As only one file per disk can be written, you need to have as many formatted disks available as files you want to copy. The program read90k.com is used on an MS-DOS computer to read files from such disks and save them as regular files on another drive. Like 1541-reads-dos, the program 1541-writes-90k can be loaded and started like a BASIC program. However, you should know the filename of the programs you want to write beforehand as there is no option to display a directory while the program is running. The program also asks for the device numbers of the MFM- and CBM-disk drives. Here, the CBM-drive contains the source disk and the MFM-drive contains the destination disk. You can work with a single drive, but copying large files will be much slower. If you decide to start copying you have to enter the name of the CBM file. The program will then search for the file on the source disk. If the file exists, you can select a conversion number (analogous to 1541-reads-dos) to specify conversion from CBM or C-editor character set to MS-DOS ASCII. CBM graphic characters, the left arrow and the pound symbol will be ignored. In detail, conversion is done according to the following tables: CBM -> MS-DOS ----------------------------- 0..12 - 13 13, 10 14..31 - 32..64 32..64 65..90 (+32) 97..122 91 91 92 - 93..94 93..94 95..96 - 97..122 (-32) 65..90 123..192 - 193..218 (-128) 65..90 219..255 - C-EDITOR -> MS-DOS ----------------------------- 0..12 - 13 13, 10 14..31 - 32..64 32..64 65..90 (+32) 97..122 91..95 91..95 96 - 97..122 (-32) 65..90 123..192 - 193..218 (-128) 65..90 219..222 (-96) 123..126 223..255 - In contrast to 1541-reads-dos, text conversion does not lead to pauses, as it is performed by the program "read90k.com" on the MS-DOS machine. After selecting the conversion number you have to enter the MS-DOS filename. The program tries to create a reasonable filename by searching for an extension from the right to the left. Superfluous dots are converted to underscores, blanks are omitted. The filename and its extension are truncated to 8 and 3 characters. However, you have to remove special characters like asterisks yourself. You can change the suggested filename, however, letters are always stored in upper case and the complete name is truncated to a maximum of 12 characters. If you enter an invalid MS-DOS filename you will have troubles copying the file with read90k.com. After you have entered a non-blank MS-DOS file name the copy process begins. Copying a long file with a single drive means you will have to swap disks during the operation. At the end you can decide to start copying to another MS-DOS disk in 90k-format. Otherwise the program will be terminated by issuing a reset of both the C64 and the MFM disk drive. Now you must use read90k.com to generate regular MS-DOS files from the 90k-disks. You have to specify the drive that contains the disk as a parameter. E.g.: READ90K A: reads all files from the disk in drive A and copies them to the current device. If you just want to view the names of the files on the disk you have to add the letter D as a second parameter. E.g.: READ90K A: D Executing read90k.com without parameters will display a short help message. Source code for read90k is available (Appendix B) for compiling on Unix and Unix-like machines with a 5 1/4" drive. The program will compile using gcc, and likely your native cc as well (use the command "cc -o read90k read90k.c"). Before using the program, you must find the device driver which handles single-sided or double-sided 40-track double-density floppy disks. Put any formatted floppy disk into the drive and execute the command "wc -c /dev/floppyname" (where floppyname is the name of the special file for the floppy device driver). If it completes without errors and the size given is 184 320 (180k), you can use read90k with the command line "read90k /dev/floppyname". If the size is 368 640, you have a 360 kB sized disk driver and must use "read90k 1 /dev/filename". If you don't get either sized image, you cannot access the 90 kB disk. As an example, the Linux OS ver. 0.99 patchlevel 10 uses the names /dev/fd0 and /dev/fd0d360 for the floppy device driver for the first floppy drive. These are both 360 kB drivers which require using the "1" option on the read90k command line (i.e. to copy a 1541-written disk, use the command line "read90k 1 /dev/fd0"). ----------------------------------------------------------------------- 6) ERROR MESSAGES During the execution of 1541-reads-dos and 1541-writes-90k several disk errors may occur. An error always leads to a termination of the copy process. If an error occurs during a CBM disk access, the drive's error channel message is displayed. During an MS-DOS disk access one of the following error messages can appear. (The probable reason(s) for an error is described here, below each message.) * Can't access MFM-disk (drive not ready) There is either no disk in the drive, or the drive door is open, or the disk is not a formatted MFM-disk. The message might also appear if the 1541 has not been modified or if the modification was not correct. * CRC-error in sector header The disk is of bad quality or is not an MFM-disk. * sector header not found The disk is of bad quality or is not an MFM-disk. It could also indicate corrupt disk control information. * data section not found The disk is of bad quality. * CRC-error in data section The disk is of bad quality. There could also be a problem with the drive. If this error happens during writing data it indicates a write verify error. * write protect on An attempt was made to write to a write protected disk. * disk full An attempt was made to write more than 91904 bytes to a 90k-disk. * Illegal MFM-disk sidenr. ( <> 0 ) The disk control information is corrupt (or the drive is spinning backwards...). * Unsupported MFM-sector size ( <> 512 ) The inserted disk is not an MS-DOS disk (e.g. it could be a CP/M disk). * Not (yet) supported MS-DOS format The disk has been formatted with wrong command line options, or it is not an MS-DOS disk, or the disk control information is corrupt. The positions where disk errors have occurred may be indicated by an MFM track and sector number in parentheses. The programs retry reading and writing to bad quality disks several times before displaying an error message. Some drives behave differently after they have been in use for a long time. So, after an error, it might be worth trying again after the drive has been switched off for quite a while. Sometimes it takes a very long time to detect an error. In that case, you could open the drive door to interrupt the reading process. Normally the read/write head will not bump against its boundaries if this is done during an MS-DOS disk access. ----------------------------------------------------------------------- 7) COMPATIBILITY The C64 programs have been tested in the following configurations: - a single modified 1541 drive - a single modified OC-118N drive - a modified 1541 and a stock OC-118N - a modified OC-118N and a stock 1541 - a modified 1541 and RAMDOS emulating a second disk drive They should also work with any other Commodore compatible disk drive used as the second drive (the one holding the CBM format disk). The memory between $C000 and $CFFF has intentionally been left blank. This is the place to put utility programs like the RAMDOS interface page. Disk speedup utilities should work well with reading and writing to CBM format disks. If they speed up sequential file access, copying will be much faster. While reading and writing to MS-DOS disks almost any available RAM in the 1541 is used. Therefore you might have troubles with utilities that rely upon that RAM. The programs will reset the disk drive after each copy pass if a single disk drive is used. This will reset device numbers changed by software to their original values. ----------------------------------------------------------------------- 8) POSSIBLE IMPROVEMENTS The programs 1541-reads-dos and 1541-writes-90k are both divided into machine language code executed in the modified 1541 disk drive and a compiled C-program executed in the C64. There are some restrictions due to the use of C as the programming language. If the C64 programs would be rewritten in assembler many improvements could be achieved. * Smaller program size The read and write programs could be combined into one and a bigger copy buffer could be used (current size is 12KB). * Higher speed The routines for text conversion especially could be much faster. With fast transfer routines, MS-DOS reading and writing speed could be doubled. As an option, CBM disk reading and writing could also be made 5 times faster quite easily. * Better user interface A less modal user interface, either command line or menu oriented, could be implemented. * More flexibility 1541-reads-dos could handle quite easily also 160KB disks. Subdirectories could be supported. * Improvement of low level routines Currently, it is not possible to write complete sectors due to too little memory in the 1541. That is why the 90k-format is used. By letting the C64 do some of the work currently done by the 1541 it could be possible to write complete sectors. The regular MS-DOS format could then be used for writing, too. Commands to delete and rename files could be also implemented then. It would be possible to support double sided disks by flipping disks over. A hardware or software switch installed in the 1541 to change the spinning direction would probably be necessary. ----------------------------------------------------------------------- 9) DISCLAIMER Although the drive modification and programs have been tested on several disk drives and computers, the authors cannot guarantee that anyone else can perform this upgrade without damaging his computer. We therefore disclaim any responsibility for any damage that may occur as result of attempting this upgrade or using the accompanying programs. Keep in mind that the modification will also void any warranty on your disk drive. ----------------------------------------------------------------------- 10) CONTACTING THE AUTHORS If you have comments or bug reports or if you are interested in improving the programs feel free to send email to the programmer of the C64 programs, Richard Hable Richard.Hable@jk.uni-linz.ac.at to the original developer of the drive modification and MFM reading routine, Daniel Fandrich dan@fch.wimsey.bc.ca or CompuServe 72365,306 or to the author of the Read90k programs, Marko Makela Marko.Makela@Helsinki.fi ------------------------------------------------------------------------- APPENDIX A: LISTING OF BASIC PROGRAM 1541-DOS.BOOT This BASIC program allows you to read 1541-dos.sfx for the first time. It has been kept as small as possible, therefore, there is little error checking. Please read the following instructions to avoid incorrect results. Format an MS-DOS disk for data transfer, as described in 3). Copy the file 1541-dos.sfx to the freshly formatted MS-DOS disk. Type in the BASIC program 1541-dos.boot, save it and run it on a C64. First, you have to enter the device number of the modified 1541. This drive will be used for both reading and writing. Then, you have to insert a correctly formatted CBM disk. No data on this disk will be changed. It is only necessary to let the drive find correct track positions. Then, you have to insert the MS-DOS disk. The program 1541-dos.sfx will be read into memory. This will take quite a while. If no errors occur, you can insert a CBM disk, to which the program 1541-dos.sfx will be written to. 0 rem 1541-dos.boot ver. 16.11.1993 1 rem read 1541-dos.instr ! 2 : 10 poke55,0:poke56,48:clr 100 input"device number";v 150 input"insert correct cbm disk ";x$ 160 open1,v,15,"i":input#1,a,b$,c,d:close1:ifa>=20thenstop 200 input"insert ms-dos source disk ";x$ 210 open1,v,15:gosub2000:close1 300 open1,v,15:print"reading" 310 t=1:s=1:m=12288:b=56 320 ford=1tob:gosub1000:m=m+512:s=s+1:ifs>9thens=1:t=t+1 330 print"#";:nextd:print:print#1,"ui"; 400 input"insert cbm destination disk ";x$ 410 open2,v,1,"1541-dos.sfx":input#1,a,b$,c,d:ifa>=20thenstop 420 fori=0tob*512-1:print#2,chr$(peek(12288+i));:next:close2 430 close1:poke56,160:clr:end 999 : 1000 rem read sector t/s into m 1010 forc=1to15:forp=0to1 1020 print#1,"m-w"chr$(6)chr$(4)chr$(4)chr$(p)chr$(t)chr$(0)chr$(s); 1030 print#1,"m-e"chr$(3)chr$(4);:print#1,"m-r"chr$(13)chr$(4)chr$(1);:get#1,e$ 1040 ife$<>""thenifp=0or(e$<>chr$(2))and(e$<>chr$(4))thenprint"read error":stop 1050 ife$<>""thennextc:print"read error":stop 1060 fori=0to255step32:print#1,"m-r"chr$(i)chr$(3)chr$(32); 1070 forj=0to31:get#1,c$:pokem+256*p+i+j,asc(c$+chr$(0)):next:next 1080 nextp:return 2000 rem transfer m.code 2010 fori=0to1023:reada:print#1,"m-w"chr$(iand255)chr$(4+i/256)chr$(1)chr$(a); 2020 h=h+a*(i+1):next:ifh<>52477511thenstop 2030 return 9999 : 10000 data76,75,4,76,14,4,0,18,0 10010 data1,2,0,0,0,32,0,193,173 10020 data1,24,72,41,252,9,2,141 10030 data1,24,173,12,24,72,41,241 10040 data9,12,141,12,24,169,76,141 10050 data0,4,169,75,141,1,4,174 10060 data7,4,232,134,8,169,224,133 10070 data1,165,1,48,252,141,13,4 10080 data104,141,12,24,104,141,1 10090 data24,96,160,33,185,42,2,153 10100 data213,2,136,16,247,173,0 10110 data28,41,159,141,0,28,162 10120 data6,189,248,7,157,209,1,202 10130 data208,247,160,146,165,16 10140 data72,165,17,72,169,117,133 10150 data16,169,55,133,17,134,23 10160 data189,7,4,32,187,7,32,218 10170 data7,153,70,1,200,165,84,153 10180 data70,1,200,232,224,4,144 10190 data232,169,0,32,187,7,32,187 10200 data7,165,17,32,218,7,153,70 10210 data1,200,165,84,153,70,1,165 10220 data16,200,192,158,144,237 10230 data104,133,17,104,133,16,169 10240 data78,32,218,7,153,70,1,165 10250 data84,153,71,1,160,0,152,141 10260 data127,7,162,141,189,69,1 10270 data192,80,144,3,169,137,202 10280 data133,22,189,70,1,72,32,125 10290 data7,153,70,1,104,232,200 10300 data224,159,144,237,208,4,192 10310 data80,144,231,173,127,7,24 10320 data105,3,141,127,7,169,255 10330 data153,70,1,200,192,140,144 10340 data200,141,229,1,169,13,141 10350 data34,6,169,0,141,47,6,32 10360 data76,5,169,67,141,34,6,169 10370 data54,141,47,6,169,208,160 10380 data200,174,6,4,208,12,169 10390 data112,133,16,169,55,133,17 10400 data169,153,160,0,141,130,6 10410 data140,131,6,162,144,169,255 10420 data157,70,1,138,56,233,20 10430 data170,176,244,162,202,154 10440 data169,203,141,5,24,169,180 10450 data133,82,160,0,169,48,133 10460 data24,184,80,254,44,1,28,184 10470 data80,254,173,1,28,184,162 10480 data80,201,85,240,36,80,254 10490 data173,1,28,184,162,100,201 10500 data170,240,89,136,208,222 10510 data198,24,208,218,162,1,76 10520 data68,7,80,254,44,1,28,184 10530 data56,76,25,6,169,85,80,254 10540 data237,1,28,240,247,201,13 10550 data240,233,144,13,80,254,44 10560 data1,28,162,120,233,51,240 10570 data116,208,175,80,254,44,1 10580 data28,184,162,40,201,3,240 10590 data14,80,254,44,1,28,184,162 10600 data0,201,1,240,90,208,149 10610 data80,254,173,1,28,233,74 10620 data240,79,208,138,169,170 10630 data80,254,237,1,28,240,247 10640 data201,25,240,168,144,13,80 10650 data254,44,1,28,162,140,233 10660 data102,240,51,208,215,80,254 10670 data44,1,28,184,162,60,201 10680 data6,240,15,80,254,44,1,28 10690 data184,162,20,201,1,240,25 10700 data76,86,5,80,254,173,1,28 10710 data233,148,240,13,208,242 10720 data152,56,233,3,168,176,235 10730 data76,120,5,232,80,254,173 10740 data1,28,253,70,1,208,13,232 10750 data80,254,173,1,28,253,70 10760 data1,240,234,208,0,56,138 10770 data170,233,20,176,251,224 10780 data6,144,211,224,19,240,12 10790 data198,82,240,3,76,80,5,162 10800 data3,76,68,7,96,140,131,6 10810 data80,254,44,1,28,184,169 10820 data153,136,240,34,80,254,44 10830 data1,28,184,141,130,6,76,79 10840 data6,80,254,173,1,28,184,133 10850 data83,188,70,1,80,254,173 10860 data1,28,184,133,84,200,208 10870 data153,80,254,173,1,28,184 10880 data153,0,3,80,254,173,1,28 10890 data184,153,129,3,200,80,254 10900 data173,1,28,184,153,202,1 10910 data192,129,80,254,173,1,28 10920 data184,72,144,217,44,5,24 10930 data48,5,162,4,76,68,7,138 10940 data162,255,56,233,20,232,176 10950 data251,138,73,7,133,26,10 10960 data101,26,141,127,7,169,0 10970 data133,23,141,107,7,160,129 10980 data224,4,104,176,3,173,75 10990 data2,133,22,176,6,144,10,104 11000 data32,83,7,185,202,1,32,83 11010 data7,136,185,129,3,32,83,7 11020 data185,0,3,32,83,7,152,208 11030 data230,165,84,32,83,7,165 11040 data83,32,83,7,174,6,4,240 11050 data7,169,0,141,203,1,162,0 11060 data160,0,185,203,1,157,0,3 11070 data32,187,7,185,129,3,157 11080 data1,3,32,187,7,200,232,232 11090 data208,233,174,6,4,208,9,173 11100 data75,2,141,2,7,76,68,7,173 11110 data75,2,32,187,7,173,1,4,32 11120 data187,7,165,16,5,17,170,240 11130 data2,162,5,160,33,185,213 11140 data2,153,42,2,136,16,247,138 11150 data76,105,249,166,22,72,133 11160 data22,138,32,125,7,166,23 11170 data133,23,240,23,138,32,150 11180 data7,162,0,134,23,240,0,153 11190 data129,3,162,7,208,3,153,203 11200 data1,142,107,7,104,133,22 11210 data96,24,144,254,70,22,106 11220 data70,22,106,70,22,106,70 11230 data22,106,70,22,106,70,22 11240 data106,70,22,106,96,41,170 11250 data105,42,41,212,105,20,41 11260 data232,105,8,74,74,74,74,133 11270 data26,165,23,41,170,105,42 11280 data41,212,105,20,41,232,105 11290 data8,41,240,5,26,96,72,133 11300 data26,56,38,26,240,21,38,16 11310 data38,17,144,246,165,16,73 11320 data33,133,16,165,17,73,16 11330 data133,17,24,144,231,104,96 11340 data56,42,8,176,6,36,23,48 11350 data2,56,36,24,38,84,38,83 11360 data40,8,102,23,40,38,84,38 11370 data83,10,208,230,165,83,96 11380 data68,137,68,137,85,84,144 ------------------------------------------------------------------------- APPENDIX B: C-VERSION OF READ90K FOR UNIX If you don't have MS-DOS installed on your PC, it might be possible to use the following C-program to read files from disks in 90k-format. #include #include /************************************************************ * Read90k v0.1 * * Marko Mdkeld * Mail: Sillitie 10 A * 01480 Vantaa * Finland * E-Mail: Marko.Makela@Helsinki.FI * * Version history: * * Version Date Description * v0.1 June 23rd, 1993 The first version for Unix. ************************************************************/ /******************* * Translation table *******************/ unsigned char TranslaTable[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20 */ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30 */ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40 */ 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50 */ 0x78, 0x79, 0x7A, 0x5B, 0x00, 0x5D, 0x5E, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 60 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 70 */ 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* D0 */ 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20 */ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30 */ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40 */ 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50 */ 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 60 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 70 */ 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* D0 */ 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /********************* * Function prototypes *********************/ #ifndef __STDC__ int main(); /* main function */ #else int main(int argc, char **argv); #endif /*********** * Functions ***********/ #ifdef __STDC__ int main(int argc, char **argv) #else int main(argc,argv) int argc; char **argv; #endif { FILE *disk, *outfile; unsigned char dirbuf[256], diskbuf[512], byte; unsigned uFileCounter, uCounter, uSectorCounter, mode = 1, uTrans1, uTrans2; unsigned long luFileLength, luFinalLength; fprintf(stderr, "90 kB disk reader for Unix v0.1\n"); if (argc < 2 || argc > 3) { Usage: fprintf (stderr, "Usage: %s [d|1] disk\n", *argv); fprintf (stderr, "Options: d to display the directory only.\n"); fprintf (stderr, " 1 to extract skipping the second side.\n"); fprintf (stderr, "disk is /dev/fd0, for instance.\n"); return (1); } if (argc == 3 && argv[1][1]) goto Usage; if (argc == 3) { argv++; if (**argv == 'd') mode = 0; else if (**argv == '1') mode = 2; else goto Usage; } if ((disk = fopen(*++argv, "rb")) == NULL) { fprintf(stderr, "Opening the disk %s failed.\n", *argv); return(2); } /* read directory */ if (512 > fread (diskbuf, sizeof *diskbuf, 512, disk)) { fprintf (stderr, "Error reading disk directory.\n"); fclose (disk); return (3); } uSectorCounter = 1; memcpy (dirbuf, diskbuf, 256); /* start processing the directory */ for (uFileCounter = 0; uFileCounter < 256 && dirbuf[uFileCounter]; uFileCounter += 16) { luFileLength = 1 + (unsigned long)dirbuf[uFileCounter + 13] + ((unsigned long)dirbuf[uFileCounter + 14] << 8) + (((unsigned long)dirbuf[uFileCounter + 15] & 1) << 16); if (mode) fprintf (stdout, "Creating `%s', %lu bytes -- ", &dirbuf[uFileCounter], luFileLength); else fprintf (stdout, "`%s', %lu bytes\n", &dirbuf[uFileCounter], luFileLength); if (mode) { if (!(outfile = fopen (&dirbuf[uFileCounter], "wb"))) { outFail: fprintf (stderr, "Failed in creating the file.\n"); fclose (disk); return (4); } luFinalLength = 0; while (luFileLength) { if (512 > fread (diskbuf, sizeof *diskbuf, 512, disk)) { fprintf (stderr, "Error reading the disk.\n"); fclose (disk); fclose (outfile); return (3); } luFileLength -= (uCounter = luFileLength > 256 ? 256 : luFileLength); if (dirbuf[uFileCounter + 15] & 192) /* translation */ { memcpy (diskbuf + 256, diskbuf, 256); for (uTrans1 = uTrans2 = 0; uTrans1 < uCounter; uTrans1++) if (byte = TranslaTable[((dirbuf[uFileCounter + 15] & 128) << 1) + diskbuf[256 + uTrans1]]) diskbuf[uTrans2++] = byte; uCounter = uTrans2; } if (uCounter > fwrite (diskbuf, sizeof *diskbuf, uCounter, outfile)) { fclose (outfile); goto outFail; } luFinalLength += uCounter; if (++uSectorCounter == 9) { if (mode == 2) /* optionally skip the second side */ for (uSectorCounter++; --uSectorCounter; fread (diskbuf, sizeof *diskbuf, 512, disk)); uSectorCounter = 0; } } fclose (outfile); fprintf (stdout, "%lu bytes converted.\n", luFinalLength); } } fclose (disk); return (0); }