home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / qltools / part01 < prev    next >
Encoding:
Text File  |  1993-11-13  |  29.7 KB  |  1,140 lines

  1. Newsgroups: comp.sources.misc
  2. From: beppe@maya.dei.unipd.it (Giuseppe Zanetti (beppe)
  3. Subject: v40i127:  qltools - read QL files on PC, Unix and Mac, Part01/01
  4. Message-ID: <1993Nov14.025013.29430@sparky.sterling.com>
  5. X-Md4-Signature: 275236bdd79713e82931aa9f3ad9327c
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: BBS-MAYA-Padua University-Italy
  8. Date: Sun, 14 Nov 1993 02:50:13 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: beppe@maya.dei.unipd.it (Giuseppe Zanetti (beppe)
  12. Posting-number: Volume 40, Issue 127
  13. Archive-name: qltools/part01
  14. Environment: QL, PC, UNIX, Mac
  15.  
  16. This is the new version of QLtools, a program that reads QL floppies on a
  17. MS-DOS, UNIX or MAC platform. QL is a microcomputer from Sinclair ltd.
  18.  
  19. Giuseppe Zanetti
  20. ---
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # Contents:  qltools.1.6 qltools.1.6/changes qltools.1.6/copyrigh
  26. #   qltools.1.6/examples qltools.1.6/format qltools.1.6/qltools.c
  27. #   qltools.1.6/qltools.man qltools.1.6/readme qltools.1.6/viewall.sh
  28. # Wrapped by kent@sparky on Tue Nov  9 20:40:50 1993
  29. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive 1 (of 1)."'
  32. if test ! -d 'qltools.1.6' ; then
  33.     echo shar: Creating directory \"'qltools.1.6'\"
  34.     mkdir 'qltools.1.6'
  35. fi
  36. if test -f 'qltools.1.6/changes' -a "${1}" != "-c" ; then 
  37.   echo shar: Will not clobber existing file \"'qltools.1.6/changes'\"
  38. else
  39.   echo shar: Extracting \"'qltools.1.6/changes'\" \(3496 characters\)
  40.   sed "s/^X//" >'qltools.1.6/changes' <<'END_OF_FILE'
  41. XChanges from 1.0 to 1.1
  42. X=======================
  43. X
  44. X- There are a couple of bugs corrected: (tanks to Paul Foley)
  45. X
  46. X   1) When a file is deleted, QDOS only sets the top byte of the info
  47. X      in the map to 0xFD.
  48. X      1.0 assumes the entire 12 bit entry is set to 0xFDF, but the final F
  49. X      will probably not be there unless that block has never been used.
  50. X
  51. X   2) 1.0 use read_block0() to read in the map block, but it assumes the
  52. X      map block is 3 sectors long, in sectors 0, 3 and 6.  This is normally
  53. X      the case, but it _can_ be changed (there is an 84-track formatting
  54. X      program around that forces 4 sector allocation blocks).  All you can
  55. X      guarantee is that the first sector will be sector 0.  What I would
  56. X      suggest is to load in sector 0, get the info in the first 96 bytes and
  57. X      then use the general read_block() routine to read the entire map.
  58. X
  59. X   3) #define for Maximum allocation block, since if allocation block was >3
  60. X      this cause a "core dump".
  61. X
  62. X   4) Another #define for Maximum number of sectors (not ever 1440).
  63. X
  64. X   5) Use the "allocblock" variable for allocation blocksnumber (refer to 2)).
  65. X
  66. X   6) Check for unexistent sectors in a file.
  67. X
  68. X   7) Check if the disk is a QL disk (1.0 simply dump)
  69. X
  70. XI think there are some bugs with 3) and 4) and 5), but I cannot try the code
  71. X(I have never seen any of these disks).
  72. X
  73. XChanges from 1.1 to 1.2
  74. X=======================
  75. X
  76. X   1) A little bug: now argfnum is a long int (problems with Turbo C)
  77. X
  78. X   2) MS-DOS support !!!
  79. X
  80. X   3) A bug with lwrd, now return a unsigned long int and is a new function.
  81. X
  82. X   4) Eh eh eh a bug in the name of my city (Padova and NOT Pdaova :-)
  83. X
  84. XChanges from 1.2 to 1.3
  85. X=======================
  86. X
  87. X   1) MS-DOS is a brain damnaged system. Stdout was opened with CR/LF
  88. X      conversion and this cause damnages of binaries.
  89. X
  90. X   2) Corrected a bug in floppy reset under MS-DOS.
  91. X
  92. XChanges from 1.3 to 1.4
  93. X=======================
  94. X
  95. X   1) "bleod" and "byeod" now are unsigned integers.
  96. X
  97. X   2) "wrd()" take a unsigned char pointer and return a unsigned int. There
  98. X      are some problems with directories. Now in wrd() are some type
  99. X      conversions.
  100. X
  101. XChanges from 1.4 to 1.5
  102. X=======================
  103. X
  104. X   1) Apple Mac adaption by Roberto Avanzi <gandalf@sabrina.dei.unipd.it>
  105. X
  106. X   2) patches by Scott Telford <st@epcc.edinburgh.ac.uk>
  107. X      - Improved error messages
  108. X      - Qdos level 2 device subdirectories (file type 255) are now
  109. X        recognised in the directory listing (indicated by a "->" like
  110. X        the level 2 WSTAT.
  111. X      - Unrecognised file types have their type number printed.
  112. X      - Empty directory entries (length=0) are skipped in the directory
  113. X        listing.
  114. X
  115. XChanges from 1.5 to 1.6
  116. X=======================
  117. X
  118. X   1) Corrected a bug in the memory allocation of pdir. Now malloc
  119. X      allocate the right size of memory (blocks of 512*allocblocks and not
  120. X      of 512 bytes !)
  121. X
  122. X   2) A new switch -s for a short listing with only filenames. This is very
  123. X      usefull for obtaining file names in scripts in a Unix environment.
  124. X
  125. X      example:
  126. X                  # this program convert every file in a QL disk
  127. X
  128. X                  for i in `qltools $device -s`
  129. X                  do
  130. X                          qltools $device $i > $i
  131. X                  done
  132. X
  133. X--
  134. X       (c)1992 by Giuseppe Zanetti
  135. X
  136. X       Giuseppe Zanetti
  137. X       via Vergani, 11 - 35031 Abano Terme (Padova) ITALY
  138. X       e-mail: beppe@sabrina.dei.unipd.it
  139. X
  140. X       This is copyrighted software, but freely distributable.
  141. X
  142. X
  143. END_OF_FILE
  144.   if test 3496 -ne `wc -c <'qltools.1.6/changes'`; then
  145.     echo shar: \"'qltools.1.6/changes'\" unpacked with wrong size!
  146.   fi
  147.   # end of 'qltools.1.6/changes'
  148. fi
  149. if test -f 'qltools.1.6/copyrigh' -a "${1}" != "-c" ; then 
  150.   echo shar: Will not clobber existing file \"'qltools.1.6/copyrigh'\"
  151. else
  152.   echo shar: Extracting \"'qltools.1.6/copyrigh'\" \(1389 characters\)
  153.   sed "s/^X//" >'qltools.1.6/copyrigh' <<'END_OF_FILE'
  154. X/*
  155. X *       Copyright (c)1992 by Giuseppe Zanetti
  156. X *
  157. X *       Giuseppe Zanetti
  158. X *       via Vergani, 11 - 35031 Abano Terme (Padova) ITALY
  159. X *       e-mail: beppe@sabrina.dei.unipd.it
  160. X *
  161. X *       This is copyrighted software, but freely distributable.
  162. X *
  163. X * Permission to use, copy, modify, distribute this software and its
  164. X * documentation for any purpose is hereby granted without fee, provided that
  165. X * the above copyright notice appear in all copies and that both that
  166. X * copyright notice and this permission notice appear in supporting
  167. X * documentation, and that the name of Giuseppe Zanetti not be used in
  168. X * advertising or publicity pertaining to distribution of the software without
  169. X * specific, written prior permission.  Giuseppe Zanetti makes no
  170. X * representations about the suitability of this software for any purpose.
  171. X * It is provided "as is" without express or implied warranty.
  172. X *
  173. X * GIUSEPPE ZANETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  174. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  175. X * EVENT SHALL GIUSEPPE ZANETTI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  176. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  177. X * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  178. X * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  179. X * PERFORMANCE OF THIS SOFTWARE.
  180. X *
  181. X * $Header$
  182. X */
  183. END_OF_FILE
  184.   if test 1389 -ne `wc -c <'qltools.1.6/copyrigh'`; then
  185.     echo shar: \"'qltools.1.6/copyrigh'\" unpacked with wrong size!
  186.   fi
  187.   # end of 'qltools.1.6/copyrigh'
  188. fi
  189. if test -f 'qltools.1.6/examples' -a "${1}" != "-c" ; then 
  190.   echo shar: Will not clobber existing file \"'qltools.1.6/examples'\"
  191. else
  192.   echo shar: Extracting \"'qltools.1.6/examples'\" \(907 characters\)
  193.   sed "s/^X//" >'qltools.1.6/examples' <<'END_OF_FILE'
  194. XQltools: examples of use
  195. X
  196. XNOTE: In my Linux box (freddy) the 3"1/2 720K floppy drive is /dev/fd0H720
  197. X
  198. X- Listing a ql floppy directory
  199. X
  200. Xqltools /dev/fd0H720 -d
  201. X
  202. X- Read the 5th file in the directory to console
  203. X
  204. Xqltools /dev/fd0H720 -n5
  205. X
  206. X- Read the file named "abcd_c" to console
  207. X
  208. Xqltools /dev/fd0H720 abcd_c
  209. X
  210. X- Read a file with pause (under unix only)
  211. X
  212. Xqltools /dev/fd0H720 my_file_txt | more
  213. X
  214. X- Copy a file named "test_doc" to a unix file
  215. X
  216. Xqltools /dev/fd0H720 test_doc > test_doc
  217. X
  218. X- Read a disk map
  219. X
  220. Xqltools /dev/fd0H720 -m
  221. X
  222. X- List disk info
  223. X
  224. Xqltools /dev/fd0H720 -i
  225. X
  226. X- Read some files under UNIX (a trick with the UNIX shell)
  227. X
  228. Xfor i in file1 file2 file3 file4 file5
  229. Xdo
  230. X    qltools /dev/fd0H720 $i > $i
  231. Xdone
  232. X
  233. X- Making a disk image under UNIX and use it as a QL floppy image
  234. X
  235. Xdd if=/dev/fd0H720 of=image
  236. X
  237. Xqltools image -d
  238. X
  239. X- Using a UNIX shell variable for the floppy name
  240. X
  241. Xflp1=/dev/fd0H720
  242. X
  243. Xqltools $flp1 -d
  244. X
  245. END_OF_FILE
  246.   if test 907 -ne `wc -c <'qltools.1.6/examples'`; then
  247.     echo shar: \"'qltools.1.6/examples'\" unpacked with wrong size!
  248.   fi
  249.   # end of 'qltools.1.6/examples'
  250. fi
  251. if test -f 'qltools.1.6/format' -a "${1}" != "-c" ; then 
  252.   echo shar: Will not clobber existing file \"'qltools.1.6/format'\"
  253. else
  254.   echo shar: Extracting \"'qltools.1.6/format'\" \(3546 characters\)
  255.   sed "s/^X//" >'qltools.1.6/format' <<'END_OF_FILE'
  256. XQL disks Format by Paul Foley
  257. X
  258. X    What exactly do you want to know?  I don't know about the
  259. X3.2MB format, but I can tell you about 720k.  Allocation blocks are 3
  260. Xsectors long (normally.  This can be changed) and the block 0
  261. X(consisting of sectors 0, 3 and 6 of side 0 on cylinder 0) contains
  262. Xthe mapping info.  The first 96 bytes are used as follows:
  263. X       OFFSET  SIZE           VALUE
  264. X    $00    .L        $514C3541
  265. X    $04    10 bytes    disk label
  266. X    $0E    .W        random number (created by FORMAT)
  267. X    $10    .L        #writes to this disk
  268. X    $14    .W        #free sectors
  269. X    $16    .W        #good sectors
  270. X    $18    .W        total sectors
  271. X    $1A    .W        #sectors per track (9)
  272. X    $1C    .W        #sectors per cylinder (18 for DS)
  273. X    $1E    .W        number of cylinders (80)
  274. X    $20    .W        size of allocation block (3)
  275. X    $22    .W        block number for end-of-directory
  276. X    $24    .W        byte number of end-of-directory
  277. X    $26    .W        sector offset/cylinder
  278. X    $28    18 bytes    logical-to-physical sector mapping table
  279. X    $3A    18 bytes    physical-to-logical sector mapping table
  280. X    $4C    20 bytes    unused
  281. X
  282. XThe rest of the block consists of pairs of 12-bit values (24 bits for
  283. Xeach block on a fully formatted, 80 track, double sided disk) the
  284. Xfirst of which contains the file number which that block belongs to,
  285. Xthe seconds holds the position of this block within that file.  Some
  286. Xspecial file numbers are used for the mapping block itself ($F80),
  287. Xunused blocks ($FDF), bad blocks ($FEF) and non-existant blocks ($FFF)
  288. Xand the block-number of unused, bad and non-existant blocks is always
  289. X$FFF (but when a file is deleted, only the top byte is set to $FD)
  290. Xthe map is $F80 000 - it consists of one block!  The directory
  291. Xis file number $000, and all other files have numbers corresponding to
  292. Xtheir positions in the directory (file $001 is the first, $002 is the
  293. Xsecond, etc.)
  294. X    The "logical-to-physical sector mapping table" contains a byte
  295. Xfor each sector on a cylinder (18) corresponding to the physical
  296. Xsector number (0 to 8, with the MSB set for sectors on side 1) for
  297. Xeach logical file sector.  This table is always "0 3 6 128 131 134 1 4
  298. X7 129 132 135 2 5 8 130 133 136" (unless someone has changed it)
  299. Xmeaning sectors 0, 3, 6 of side 0 are used first, then sectors 0, 3, 6
  300. Xof side 1, then sectors 1, 4, 7 of side 0, etc.  _BUT_ the sector
  301. Xnumber is offset by an amount depending on the cylinder number (the
  302. Xnumbers above are correct for cylinder 0, but the "sector
  303. Xoffset/track" value is added (mod 9) for each cylinder.  This value is
  304. Xusually 5, so the table values are correct again at cylinder 9)
  305. X    The "physical-to-logical sector mapping table" contains 9
  306. Xentries for each side of the disk, containing the logical sector
  307. Xnumbers of the physical sectors on the disk.  It is "0 6 12 1 7 13 2 8
  308. X14" for side 0 and "3 9 15 4 1 16 5 11 17" for side 1 (that is, for
  309. Xside 0, phys. sector 0 contains log. sector 0, phys. sector 1 contains
  310. Xlog. sector 6, ...) again, this is affected by the "sector
  311. Xoffset/track".
  312. X
  313. X    The directory consists of 64 '0's ($30 bytes, not $00 bytes.
  314. XI don't know what they're for) followed by a 64 byte entry for each
  315. Xfile, in the following format:
  316. X       OFFSET  SIZE           USE
  317. X    $00    .L        file length
  318. X    $04    .B        unused
  319. X    $05    .B        file type
  320. X    $06    .L        dataspace (for exec'able programs)
  321. X    $0A    .L        unused
  322. X    $0E    .W        length of file name
  323. X    $10    36 bytes    file name
  324. X    $34    .L        file update date
  325. X    $38    .L        unused.  Supposed to be reference date.
  326. X    $3C    .L        unused.  Supposed to be backup date.
  327. X
  328. XThe first 64 bytes in the first block of each file contains a copy of
  329. Xthe directory entry, but most of the information in it is not correct
  330. X(the name is OK, though)
  331. X
  332. X    Hope that helps.
  333. X
  334. X                            - Paul
  335. X
  336. END_OF_FILE
  337.   if test 3546 -ne `wc -c <'qltools.1.6/format'`; then
  338.     echo shar: \"'qltools.1.6/format'\" unpacked with wrong size!
  339.   fi
  340.   # end of 'qltools.1.6/format'
  341. fi
  342. if test -f 'qltools.1.6/qltools.c' -a "${1}" != "-c" ; then 
  343.   echo shar: Will not clobber existing file \"'qltools.1.6/qltools.c'\"
  344. else
  345.   echo shar: Extracting \"'qltools.1.6/qltools.c'\" \(10550 characters\)
  346.   sed "s/^X//" >'qltools.1.6/qltools.c' <<'END_OF_FILE'
  347. X/*
  348. X
  349. XQLTOOLS 
  350. X
  351. XRead a QL floppy disk
  352. X
  353. X(c)1992 by Giuseppe Zanetti
  354. X
  355. XGiuseppe Zanetti
  356. Xvia Vergani, 11 - 35031 Abano Terme (Padova) ITALY
  357. Xe-mail: beppe@sabrina.dei.unipd.it
  358. X
  359. X*/
  360. X
  361. X#define VERSION     "1.6,  Jan 31 1992"
  362. X
  363. X/* Maximum allocation block (normally 3) */
  364. X
  365. X#define MAXALB        6
  366. X
  367. X/* Maximum number of sectors (norm. 1440) */
  368. X
  369. X#define MAXSECT        2880
  370. X
  371. X#include <stdio.h>
  372. X
  373. X#ifdef THINK_C
  374. X#include "console.h"
  375. X#include <string.h>
  376. X#else
  377. X#include <string.h>
  378. X#endif
  379. X
  380. X#ifdef MSDOS
  381. X#include <bios.h>
  382. X#include <dos.h>    /* for delay    */
  383. X#include <io.h>     /* for setmode  */
  384. X#include <fcntl.h>  /* for O_BINARY */
  385. X#define    RESET    0
  386. X#define LAST    1
  387. X#define READ    2
  388. X#define    WRITE    3
  389. X#define VERIFY    4
  390. X#define FORMAT    5
  391. X#endif
  392. X
  393. X/* this line is neccessary since stdio.h in SUN 4.0 do not define it */
  394. X
  395. X#ifndef SEEK_SET
  396. X#define SEEK_SET    0
  397. X#endif
  398. X
  399. XFILE *f;
  400. Xstatic unsigned char b[512*MAXALB];
  401. Xstatic unsigned char b0[512*MAXALB];
  402. Xstatic unsigned char ltp[18];
  403. Xstatic unsigned char ptl[18];
  404. Xstatic unsigned int bleod;
  405. Xstatic unsigned int byeod;
  406. Xstatic unsigned char *pdir;
  407. X
  408. Xstatic unsigned int convtable[MAXSECT];
  409. X
  410. X#ifdef MSDOS
  411. Xstatic unsigned int drive;
  412. Xstatic unsigned int conv_side[MAXSECT];
  413. Xstatic unsigned int conv_sector[MAXSECT];
  414. Xstatic unsigned int conv_track[MAXSECT];
  415. X#endif
  416. X
  417. X
  418. Xstatic int gsides,gtracks,gsectors,goffset,allocblock;
  419. X
  420. Xunsigned int wrd(wp)
  421. Xunsigned char *wp;
  422. X{
  423. X    unsigned int r;
  424. X
  425. X    r= ((unsigned int) *(wp))*256 + (unsigned int) *(wp+1);
  426. X
  427. X    return r;
  428. X}
  429. X
  430. Xunsigned long int lwrd(p)
  431. Xunsigned char *p;
  432. X{
  433. X    unsigned long int r,h,l;
  434. X
  435. X    h=(unsigned long int) *(p)*256 + *(p+1);
  436. X    l=(unsigned long int) *(p+2)*256 + *(p+3);
  437. X
  438. X
  439. X    r = (unsigned long int) (h * 65536 + l);
  440. X
  441. X    return(r);
  442. X}
  443. X
  444. Xvoid cat_file(fnum)
  445. Xlong int fnum;
  446. X{
  447. X    long int flen,file,blk;
  448. X    int i,s,c,start,end;
  449. X    char buffer[512*MAXALB];
  450. X    unsigned char *base;
  451. X    int ok;
  452. X
  453. X#ifdef MSDOS
  454. X    setmode(fileno(stdout),O_BINARY);
  455. X#endif
  456. X
  457. X    flen=lwrd(pdir+fnum*64);    /* with the header */
  458. X
  459. X    for (s=0;s<=flen/(512*allocblock);s++)
  460. X    {
  461. X        ok=0;
  462. X
  463. X            for (i=0;i<(wrd(b0+28)*wrd(b0+30))/wrd(b0+32);i++)
  464. X            {
  465. X            base=b0+0x4C+20+i*allocblock;
  466. X            file=(int) (*(base) * 0x10) + (int) ((*(base+1) >> 4) & 0x0F) ;
  467. X            blk= (*(base+1) & 0x0F)*0x100 + *(base+2);
  468. X            if (file == fnum)
  469. X            {
  470. X                if (blk == s)
  471. X                {
  472. X                    read_block(buffer,i);
  473. X
  474. X                    start=0; if (s==0) start=64;
  475. X                    end=512*allocblock; if (s==(flen/(512*allocblock))) end=flen % (512*allocblock);
  476. X
  477. X                    for(c=start;c<end;c++) printf("%c",*(buffer+c));
  478. X
  479. X                    ok=1;
  480. X                }
  481. X            }
  482. X        }
  483. X
  484. X        if (!ok)
  485. X        {
  486. X            fprintf(stderr,"\n\nBlock #%i of file #%i not found\n\n",s,fnum);
  487. X
  488. X            if (s==0) fprintf(stderr,"I think this file was erased\n\n");
  489. X
  490. X#ifdef MSDOS
  491. X    setmode(fileno(stdout),O_BINARY);
  492. X#endif
  493. X
  494. X            exit(1);
  495. X        }
  496. X    }
  497. X
  498. X#ifdef MSDOS
  499. X    setmode(fileno(stdout),O_BINARY);
  500. X#endif
  501. X
  502. X}
  503. X
  504. Xvoid usage(error)
  505. Xchar *error;
  506. X{
  507. X    fprintf(stderr,"error %s\n\n",error);
  508. X
  509. X#ifdef MSDOS
  510. X    fprintf(stderr,"Usage: qltools [a:|b:] -[options] [filename]\n\n");
  511. X#else
  512. X    fprintf(stderr,"Usage: qltools diskimage -[options] [filename]\n\n");
  513. X#endif
  514. X
  515. X    fprintf(stderr,"options:\n\n");
  516. X    fprintf(stderr,"-d      list directory\n");
  517. X    fprintf(stderr,"-s      list short directory\n");
  518. X    fprintf(stderr,"-i      list info\n");
  519. X    fprintf(stderr,"-m      list disk map\n");
  520. X    fprintf(stderr,"-c      list conversion table of sectors\n");
  521. X    fprintf(stderr,"-nFN    output file number FN in the directory listing\n\n");
  522. X
  523. X#ifdef MSDOS
  524. X    fprintf(stderr,"QLTOOLS for MS-DOS (version ");
  525. X    fprintf(stderr,VERSION);
  526. X    fprintf(stderr,")\n\n");
  527. X#else
  528. X    fprintf(stderr,"diskimage is either a file with the image of a QL format disk\n");
  529. X    fprintf(stderr,"or a Unix device with a QL disk inserted in it (/dev/fd...)\n\n");
  530. X    fprintf(stderr,"QLTOOLS for UNIX (version: ");
  531. X    fprintf(stderr,VERSION);
  532. X    fprintf(stderr,")\n\n");
  533. X#endif
  534. X
  535. X    fprintf(stderr,"Giuseppe Zanetti\n");
  536. X    fprintf(stderr,"via Vergani, 11 - 35031 Abano Terme (Padova) ITALY\n");
  537. X    fprintf(stderr,"e-mail: beppe@sabrina.dei.unipd.it\n");
  538. X    exit(1);
  539. X}
  540. X
  541. X
  542. Xvoid print_info()
  543. X{
  544. X    int i;
  545. X
  546. X    printf("Disk ID          : ");
  547. X
  548. X    for (i=0;i<4;i++)
  549. X    {
  550. X        printf("%c",b0[i]);
  551. X    }
  552. X    printf("\n");
  553. X
  554. X    printf("Disk Label       : ");
  555. X
  556. X    for (i=0;i<10;i++)
  557. X    {
  558. X        printf("%c",b0[4+i]);
  559. X    }
  560. X    printf("\n");
  561. X
  562. X    printf("sectors per track: %i\n",gsectors);
  563. X    printf("sectors per cyl. : %i\n",wrd(b0+28));
  564. X    printf("number of cylind.: %i\n",gtracks);
  565. X    printf("allocation block : %i\n",allocblock);
  566. X    printf("sector offset/cyl: %i\n",goffset);
  567. X
  568. X    printf("free sectors     : %i\n",wrd(b0+20));
  569. X    printf("good sectors     : %i\n",wrd(b0+22));
  570. X    printf("total sectors    : %i\n",wrd(b0+24));
  571. X
  572. X    printf("directory is     : %u sectors and %u bytes\n",bleod,byeod);
  573. X
  574. X    printf("\nlogical-to-physical sector mapping table:\n\n");
  575. X    for (i=0;i<18;i++) printf("%u ",ltp[i]);
  576. X    printf("\n");
  577. X
  578. X    printf("\nphysical-to-logical sector mapping table:\n\n");
  579. X    for (i=0;i<18;i++) printf("%u ",ptl[i]);
  580. X    printf("\n");
  581. X}
  582. X
  583. Xvoid print_dir(shortflag)
  584. Xint shortflag;
  585. X{
  586. X    int d,i;
  587. X    char c;
  588. X
  589. X    if (!shortflag)
  590. X    {
  591. X        for (i=0;i<10;i++)
  592. X            {
  593. X                    printf("%c",b0[4+i]);
  594. X            }
  595. X            printf("\n");
  596. X
  597. X        printf("%i/%i sectors.\n\n",wrd(b0+20),wrd(b0+22));
  598. X    }
  599. X
  600. X    for (d=64;d <512*bleod+byeod;d+=64)
  601. X    {
  602. X        if(lwrd(pdir+d)==0)
  603. X            continue;
  604. X
  605. X        if (!shortflag)
  606. X        {
  607. X            printf("%3i : ",d/64);
  608. X        }
  609. X
  610. X        for (i=0;i<wrd(pdir+d+14);i++)
  611. X        {
  612. X            c=*(pdir+d+16+i);
  613. X
  614. X            printf("%c",c);
  615. X        }
  616. X
  617. X        if (!shortflag)
  618. X        {
  619. X            for(i=0;i<38-wrd(pdir+d+14);i++) printf(" ");
  620. X
  621. X            switch(*(pdir+d+5))
  622. X            {
  623. X                case 0: printf("          "); break;
  624. X                case 1: printf("Exec      "); break;
  625. X                case 2: printf("Rel       "); break;
  626. X                case 255:printf("->        "); break;
  627. X                default:printf("(type %3d)",*(pdir+d+5)); break;
  628. X            }
  629. X
  630. X                printf("    %ld",lwrd(pdir+d) - 64);
  631. X        }
  632. X
  633. X        printf("\n");
  634. X    }
  635. X}
  636. X
  637. Xvoid make_convtable(verbose)
  638. Xint verbose;
  639. X{
  640. X    int i,si,tr,se,ls,ps,uxs;
  641. X
  642. X    if (verbose)
  643. X    {
  644. X        printf("\nCONVERSION TABLE\n\n");
  645. X        printf("logic\ttrack\tside\tsector\tunix_dev\n\n");
  646. X    }
  647. X
  648. X    for(i=0;i<gtracks*gsectors*gsides;i++)
  649. X    {
  650. X        tr=i / (gsectors*gsides);
  651. X        ls=i % (gsectors*gsides);
  652. X
  653. X        ps = ltp[ls];
  654. X
  655. X        si=(ps & 0x80) != 0;
  656. X
  657. X        ps &= 0x7F;
  658. X
  659. X        ps += goffset*tr;
  660. X        se = ps % gsectors;
  661. X
  662. X        uxs = tr*gsectors*gsides+gsectors*si+se;
  663. X
  664. X        convtable[i] = uxs;
  665. X
  666. X#ifdef MSDOS
  667. Xconv_side[i]=si;
  668. Xconv_sector[i]=se;
  669. Xconv_track[i]=tr;
  670. X#endif
  671. X
  672. X        if (verbose)
  673. X        {
  674. X            printf("%i\t%i\t%i\t%i\t%i\n",i,tr,si,se,uxs);
  675. X        }
  676. X    }
  677. X}
  678. X
  679. Xint read_block(p,num)
  680. Xchar *p;
  681. Xint num;
  682. X{
  683. X    int i;
  684. X    int r=0;
  685. X
  686. X    for(i=0;i<allocblock;i++)
  687. X    {
  688. X
  689. X#ifdef MSDOS
  690. X        /* biosdisk(RESET, drive , 0, 0, 0, 0, p+512*i); */
  691. X        biosdisk(READ, drive ,conv_side[num*allocblock+i],conv_track[num*allocblock+i],1+conv_sector[num*allocblock+i],1,p+512*i);
  692. X#else
  693. X        fseek(f,(512*convtable[num*allocblock+i]),SEEK_SET);
  694. X        r += fread(p+512*i,512,1,f);
  695. X#endif
  696. X
  697. X    }
  698. X
  699. X    return(r);
  700. X}
  701. X
  702. Xint read_block0(argconv)
  703. Xint argconv;
  704. X{
  705. X    int i;
  706. X
  707. X#ifdef MSDOS
  708. X
  709. X    int status;
  710. X
  711. X    /* reset the disk */
  712. X
  713. X    status = biosdisk(READ, drive, 0, 10, 1, 1, b0);
  714. X
  715. X    /* door change signal ? */
  716. X
  717. X    if (status == 0x06) status = biosdisk(READ, drive, 0, 0, 1, 1, b0);
  718. X
  719. X    status = biosdisk(RESET, drive , 0, 0, 0, 0, b0);
  720. X
  721. X    if (status != 0) fprintf(stderr,"Disk not ready (continuing...)\n");
  722. X
  723. X    /* read block 0 */
  724. X
  725. X    biosdisk(READ, drive ,0,0,1,1,b0);
  726. X#else
  727. X    fseek(f,0,SEEK_SET);
  728. X    fread(b0,512,1,f);
  729. X#endif
  730. X
  731. X    /* is this a QL disk ? */
  732. X
  733. X    if ((*(b0) != 'Q') || (*(b0+1) != 'L'))
  734. X    {
  735. X        fprintf(stderr,"\nNot a QL disk !!!\n\n");
  736. X        exit(1);
  737. X    }
  738. X
  739. X    /* read ptl and ptl tables */
  740. X
  741. X    for (i=0;i<18;i++)
  742. X    {
  743. X        ltp[i] = *(b0+40+i);
  744. X        ptl[i] = *(b0+58+i);
  745. X    }
  746. X
  747. X    gsides=2;
  748. X    gtracks=wrd(b0+30);
  749. X    gsectors=wrd(b0+26);
  750. X    goffset=wrd(b0+38);
  751. X    bleod=wrd(b0+34);
  752. X    byeod=wrd(b0+36);
  753. X    allocblock=wrd(b0+32);
  754. X
  755. X    make_convtable(argconv);
  756. X
  757. X    read_block(b0,0);
  758. X
  759. X    return(0);
  760. X}
  761. X
  762. Xlong int match_file(fname)
  763. Xchar *fname;
  764. X{
  765. X    int d,i,match,len;
  766. X    long int r=0L;
  767. X    char c;
  768. X
  769. X    len=strlen(fname);
  770. X
  771. X    for (d=64;d <512*bleod+byeod;d+=64)
  772. X    {
  773. X        match=1;
  774. X
  775. X        if (wrd(pdir+d+14) == len)
  776. X        {
  777. X            for (i=0;i<len;i++)
  778. X            {
  779. X                c=*(pdir+d+16+i);
  780. X
  781. X                if (c != fname[i]) match=0;
  782. X            }
  783. X
  784. X            if (match)
  785. X            {
  786. X                r=d/64;
  787. X                break;
  788. X            }
  789. X        }
  790. X    }
  791. X
  792. X    return(r);
  793. X}
  794. X
  795. Xmain(argc,argv)
  796. Xint argc;
  797. Xchar * argv[];
  798. X{
  799. X    int i;
  800. X    unsigned long int finfofile, finfoblk;
  801. X    unsigned char *base;
  802. X
  803. X    int argdir,arginfo,argfnum,argmap,argconv,argshort;
  804. X    char argfname[255];
  805. X
  806. X#ifdef THINK_C
  807. X    argc=ccommand(&argv);
  808. X#endif
  809. X
  810. X    argdir=arginfo=argfnum=argmap=argconv=argshort=0;
  811. X    strcpy(argfname,"");
  812. X
  813. X    if (argc < 2)
  814. X    {
  815. X        usage("too few parameters");
  816. X    }
  817. X
  818. X    for(i=2;i<argc;i++)
  819. X    {
  820. X        if ( (argv[i][0] == '-') || (argv[i][0] == '/') )
  821. X        {
  822. X            switch(argv[i][1])
  823. X            {
  824. X                case 'd': argdir=1; break;
  825. X                case 's': argdir=1; argshort=1; break;
  826. X                case 'i': arginfo=1; break;
  827. X                case 'm': argmap=1; break;
  828. X                case 'c': argconv=1; break;
  829. X                case 'n': argfnum=atol(argv[i]+2); break;
  830. X                default: usage("bad option"); break;
  831. X            }
  832. X        }
  833. X        else
  834. X        {
  835. X            strcpy(argfname,argv[i]);
  836. X        }
  837. X    }
  838. X
  839. X#ifdef MSDOS
  840. X    if (argv[1][1] != ':')
  841. X    {
  842. X        fprintf(stderr,"Bad drive %s\n",argv[1]);
  843. X        usage("Bad drive: use a: or b:");
  844. X    }
  845. X
  846. X    switch(argv[1][0])
  847. X    {
  848. X        case 'a':
  849. X        case 'A': drive=0; break;
  850. X
  851. X        case 'b':
  852. X        case 'B': drive=1; break;
  853. X
  854. X        default: usage("Bad drive: use a: or b:"); break;
  855. X    }
  856. X#else
  857. X    f=fopen(argv[1],"rb");
  858. X
  859. X    if (f==NULL)
  860. X    {
  861. X        usage("bad image file or device");
  862. X    }
  863. X#endif
  864. X
  865. X    read_block0(argconv);
  866. X
  867. X    pdir=(unsigned char *) malloc(512*allocblock*(bleod+1));
  868. X
  869. X    /* read the directory map */
  870. X
  871. X    if (argmap)
  872. X    {
  873. X        printf("\nblock\tfile\tpos\n\n");
  874. X    }
  875. X
  876. X    for (i=0;i<(wrd(b0+28)*wrd(b0+30))/wrd(b0+32);i++)
  877. X    {
  878. X        base=b0+0x4C+20+i*allocblock;
  879. X
  880. X        finfofile= (unsigned long int) (*(base) * 0x10) + (unsigned long int) ((*(base+1) >> 4) & 0x0F) ;
  881. X        finfoblk= (*(base+1) & 0x0F)*0x100 + *(base+2);
  882. X
  883. X
  884. X        if (finfofile == 0x00)
  885. X        {
  886. X            read_block(pdir+512*allocblock*finfoblk,i);
  887. X        }
  888. X
  889. X        if (argmap)
  890. X        {
  891. X            printf("%d\t%ld\t%ld\t",i,finfofile,finfoblk);
  892. X
  893. X            if ((*(base) & 0xFD) == 0xFD)
  894. X            {
  895. X                printf("erased ");
  896. X            }
  897. X
  898. X            switch(finfofile)
  899. X            {
  900. X                case 0x000: printf("directory %i\n",finfoblk); break;
  901. X                case 0xF80: printf("map\n"); break;
  902. X                case 0xFDF: printf("unused\n"); break;
  903. X                case 0xFEF: printf("bad\n"); break;
  904. X                case 0xFFF: printf("not existent\n"); break;
  905. X                default: printf("\n"); break;
  906. X            }
  907. X
  908. X        }
  909. X    }
  910. X
  911. X    if (arginfo) print_info();
  912. X    if (argdir) print_dir(argshort);
  913. X    if (argfnum != 0) cat_file((long int)argfnum);
  914. X    if (strcmp(argfname,"") != 0)
  915. X    {
  916. X        argfnum=match_file(argfname);
  917. X
  918. X        if (argfnum == 0)
  919. X        {
  920. X            fprintf(stderr,"file not found\n");
  921. X            exit(2);
  922. X        }
  923. X
  924. X    cat_file((long int)argfnum);
  925. X    }
  926. X
  927. X#ifdef MSDOS
  928. X#else
  929. X    fclose(f);
  930. X#endif
  931. X
  932. X    return (0);
  933. X}
  934. X
  935. END_OF_FILE
  936.   if test 10550 -ne `wc -c <'qltools.1.6/qltools.c'`; then
  937.     echo shar: \"'qltools.1.6/qltools.c'\" unpacked with wrong size!
  938.   fi
  939.   # end of 'qltools.1.6/qltools.c'
  940. fi
  941. if test -f 'qltools.1.6/qltools.man' -a "${1}" != "-c" ; then 
  942.   echo shar: Will not clobber existing file \"'qltools.1.6/qltools.man'\"
  943. else
  944.   echo shar: Extracting \"'qltools.1.6/qltools.man'\" \(1247 characters\)
  945.   sed "s/^X//" >'qltools.1.6/qltools.man' <<'END_OF_FILE'
  946. X
  947. XQLTOOLS(1)                                                 QLTOOLS(1)
  948. X
  949. XNAME
  950. X       Qltools - a tool for manipulating QL files
  951. X
  952. XSYNOPSIS
  953. X       qltools diskimage [-dimc] [-nNF] [filename]
  954. X
  955. XDESCRIPTION
  956. X       Qltools is a public domain collection of programs to allow
  957. X       Unix  systems  to  list  and read files on an  Sinclair QL
  958. X       filesystem (typically  a  diskette or a image of a disk).
  959. X
  960. X       options:
  961. X
  962. X       -d      list directory
  963. X       -i      list info
  964. X       -m      list disk map
  965. X       -c      list conversion table of sectors
  966. X       -nFN    output file number FN in the directory listing
  967. X
  968. X       diskimage is either a file with the image of a QL format disk
  969. X       or a unix device with a ql disk inserted in it (/dev/fd...)
  970. X
  971. X       Under Unix you can obtain a disk image with:
  972. X
  973. X       dd if=/dev/fd of=imagefile
  974. X
  975. XNOTE
  976. X       MS-DOS version is included, but there are some changes in the syntax.
  977. X       Please do qltools.exe without parameters for the help screen.
  978. X
  979. XBUGS
  980. X       My english !
  981. X
  982. XAUTHOR
  983. X       (c)1992 by Giuseppe Zanetti
  984. X
  985. X       Giuseppe Zanetti
  986. X       via Vergani, 11 - 35031 Abano Terme (Padova) ITALY
  987. X       e-mail: beppe@sabrina.dei.unipd.it
  988. X
  989. X       This is copyrighted software, but freely distributable.
  990. X
  991. X
  992. END_OF_FILE
  993.   if test 1247 -ne `wc -c <'qltools.1.6/qltools.man'`; then
  994.     echo shar: \"'qltools.1.6/qltools.man'\" unpacked with wrong size!
  995.   fi
  996.   # end of 'qltools.1.6/qltools.man'
  997. fi
  998. if test -f 'qltools.1.6/readme' -a "${1}" != "-c" ; then 
  999.   echo shar: Will not clobber existing file \"'qltools.1.6/readme'\"
  1000. else
  1001.   echo shar: Extracting \"'qltools.1.6/readme'\" \(2668 characters\)
  1002.   sed "s/^X//" >'qltools.1.6/readme' <<'END_OF_FILE'
  1003. X** what is qltools ? **
  1004. X
  1005. X       This is qltools, a simple tool for manipulating QL files.
  1006. X
  1007. X** compiling qltools **
  1008. X
  1009. X       cc -o qltools qltools.c
  1010. X
  1011. X       under MSDOS and Turbo C: tcc -DMSDOS -o qltools qltools.c
  1012. X
  1013. X** development **
  1014. X
  1015. XQltools was developed under linux 0.98, the free OS for i386 with gcc 2.2.2,
  1016. Xthe gnu c compiler (also free). I use only PD and shareware software and
  1017. Xhave not any problem. Since some software is better than some commercial
  1018. Xsoftware. A reliable "pubblic domain workstation" costs only the money for the
  1019. Xhardware and is comparable with a commercial system.
  1020. X
  1021. X** porting **
  1022. X
  1023. XSince qltools is a portable program. It compile ok under:
  1024. X
  1025. X       - linux (0.96c and gcc 2.2.2, 0.98pl1 and gcc 2.2.2d)
  1026. X
  1027. X       - SUN 4 (Sparc Station 2, SLC and IPC, SparcServer 830 Multiprocessor)
  1028. X
  1029. X       - HP9000/825 under HP/UX 7.00 and HP/UX 8.00
  1030. X
  1031. X       - MS-DOS 5.0 and Turbo C++ 1.00
  1032. X
  1033. X       and, but not compiled myself:
  1034. X
  1035. X       - NeXT
  1036. X
  1037. X       - RS3000
  1038. X
  1039. X       - It compiles ok also on the Macintosh platform under the Think C
  1040. X         environment provided you use libraries compiled with 4 byte ints
  1041. X         and the 4 byte int option turned on (Roberto Avanzi).
  1042. X
  1043. X         (for Mac related questions ask Roberto Avanzi at the e-mail address
  1044. X         <gandalf@sabrina.dei.unipd.it>
  1045. X
  1046. X       - A amiga port is possible with a BSD compatibility box and a raw
  1047. X         drive device.
  1048. X
  1049. X                                               Giuseppe Zanetti
  1050. X
  1051. X** Tanks **
  1052. X
  1053. X        Tanks to all QL users that encourage me and help me !!!
  1054. X        (Please, write to me if you are a contributor but your name is not here)
  1055. X
  1056. X        - Tank'you to Paul Foley for the support and the documentation.
  1057. X
  1058. X        - Think C (Apple Mac) adaption:
  1059. X          Roberto Avanzi <gandalf@sabrina.dei.unipd.it>
  1060. X          via Luigi Balzan 12 - 45100 Rovigo ITALY
  1061. X
  1062. X        - qltools 1.4 patches:
  1063. X          Scott Telford <st@epcc.edinburgh.ac.uk>
  1064. X          - Improved error messages
  1065. X          - Qdos level 2 device subdirectories (file type 255) are now
  1066. X            recognised in the directory listing (indicated by a "->" like
  1067. X            the level 2 WSTAT.
  1068. X          - Unrecognised file types have their type number printed.
  1069. X          - Empty directory entries (length=0) are skipped in the directory
  1070. X            listing.
  1071. X
  1072. X        - support and distribution
  1073. X          Davide Santachiara (ERGON DEVELOPMENT)
  1074. X
  1075. X** my english **
  1076. X
  1077. X          is very very bad ! Sorry !
  1078. X
  1079. X--
  1080. X
  1081. X       (c)1992 by Giuseppe Zanetti
  1082. X
  1083. X       Giuseppe Zanetti
  1084. X       via Vergani, 11 - 35031 Abano Terme (Padova) ITALY
  1085. X       e-mail: beppe@sabrina.dei.unipd.it
  1086. X
  1087. X       This is copyrighted software, but freely distributable.
  1088. X
  1089. X
  1090. END_OF_FILE
  1091.   if test 2668 -ne `wc -c <'qltools.1.6/readme'`; then
  1092.     echo shar: \"'qltools.1.6/readme'\" unpacked with wrong size!
  1093.   fi
  1094.   # end of 'qltools.1.6/readme'
  1095. fi
  1096. if test -f 'qltools.1.6/viewall.sh' -a "${1}" != "-c" ; then 
  1097.   echo shar: Will not clobber existing file \"'qltools.1.6/viewall.sh'\"
  1098. else
  1099.   echo shar: Extracting \"'qltools.1.6/viewall.sh'\" \(188 characters\)
  1100.   sed "s/^X//" >'qltools.1.6/viewall.sh' <<'END_OF_FILE'
  1101. X# Please personalize this script for your system
  1102. X
  1103. XDEV=/dev/fd0H720
  1104. X
  1105. Xfor i in `qltools $DEV -s`
  1106. Xdo
  1107. X    echo -n $i:
  1108. X    read yn
  1109. X
  1110. X    if [ $yn = y ]
  1111. X    then
  1112. X        qltools $DEV $i | strings | more
  1113. X    fi
  1114. Xdone
  1115. X
  1116. END_OF_FILE
  1117.   if test 188 -ne `wc -c <'qltools.1.6/viewall.sh'`; then
  1118.     echo shar: \"'qltools.1.6/viewall.sh'\" unpacked with wrong size!
  1119.   fi
  1120.   # end of 'qltools.1.6/viewall.sh'
  1121. fi
  1122. echo shar: End of archive 1 \(of 1\).
  1123. cp /dev/null ark1isdone
  1124. MISSING=""
  1125. for I in 1 ; do
  1126.     if test ! -f ark${I}isdone ; then
  1127.     MISSING="${MISSING} ${I}"
  1128.     fi
  1129. done
  1130. if test "${MISSING}" = "" ; then
  1131.     echo You have the archive.
  1132.     rm -f ark[1-9]isdone
  1133. else
  1134.     echo You still must unpack the following archives:
  1135.     echo "        " ${MISSING}
  1136. fi
  1137. exit 0
  1138. exit 0 # Just in case...
  1139.