home *** CD-ROM | disk | FTP | other *** search
/ Go64! / Go64_1999-06_1999_CSW_Side_A.d64 / 1581cp50.zip / SRC / 1581HLVL.C < prev    next >
C/C++ Source or Header  |  1999-05-13  |  36KB  |  1,077 lines

  1. /*
  2.  
  3.  * cOPYRIGHT (c) 1998, 1999 wOLFGANG mOSER
  4.  
  5.  *
  6.  
  7.  * tHIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
  8.  
  9.  * IT UNDER THE TERMS OF THE gnu gENERAL pUBLIC lICENSE AS PUBLISHED BY
  10.  
  11.  * THE fREE sOFTWARE fOUNDATION; EITHER VERSION 2, OR (AT YOUR OPTION)
  12.  
  13.  * ANY LATER VERSION.
  14.  
  15.  *
  16.  
  17.  * tHIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
  18.  
  19.  * BUT without any warranty; WITHOUT EVEN THE IMPLIED WARRANTY OF
  20.  
  21.  * merchantability OR fitness for a particular purpose.  sEE THE
  22.  
  23.  * gnu gENERAL pUBLIC lICENSE FOR MORE DETAILS.
  24.  
  25.  *
  26.  
  27.  * yOU SHOULD HAVE RECEIVED A COPY OF THE gnu gENERAL pUBLIC lICENSE
  28.  
  29.  * ALONG WITH THIS PROGRAM (SEE THE FILE copying); IF NOT, WRITE TO THE
  30.  
  31.  * fREE sOFTWARE fOUNDATION, iNC., 675 mASS aVE, cAMBRIDGE, ma 02139, usa.
  32.  
  33.  */
  34.  
  35.  
  36.  
  37. /*
  38.  
  39.  * cOMMODORE cbm 1581 FLOPPY DISK COPY UTIL FOR pc'S, 1581hlvl.c
  40.  
  41.  *
  42.  
  43.  * wOLFGANG mOSER <WOMO@MINDLESS.COM>
  44.  
  45.  *   HTTP://WWW.GM.FH-KOELN.DE/{$7e}WOMO (UP TO dEZEMBER 1999)
  46.  
  47.  *
  48.  
  49.  *
  50.  
  51.  * bASIC INFORMATIONS FROM dAN fANDRICH <DAN@FCH.WIMSEY.BC.CA>.
  52.  
  53.  *   hIS README OF THE CBMFS-0.3 DRIVER FOR lINUX EXPLAINED ME, WHAT THE
  54.  
  55.  *   DIFFERENCE BETWEEN A dos FORMATTED 800 KB DISK AND A cbm 1581 DISK IS.
  56.  
  57.  *   (CHECK: HTTP://VANBC.WIMSEY.COM/{$7e}DANF/SOFTWARE/)
  58.  
  59.  *
  60.  
  61.  *
  62.  
  63.  * bASIC IMPLEMENTATIONS BY cIRIACO gARC{CBM-K}A DE cELIS <CIRI@GUI.UVA.ES>
  64.  
  65.  *   hIS UTIL 765dEBUG, vERSION 5.0 IS GREAT FOR LEARNING DMA BASED
  66.  
  67.  *   DIRECT FLOPPY DISK CONTROLLER PROGRAMMING.
  68.  
  69.  *   (CHECK: FTP://FTP.GUI.UVA.ES/PUB/PC/2M/765D50SR.ZIP)
  70.  
  71.  *
  72.  
  73.  * cHECK OUT FOR HIS FLOPPY DISK UTILS 2m AND 2mgui, THE LAST WORDS
  74.  
  75.  * IN IMPROVING FLOPPY DISK STORAGE CAPACITY.
  76.  
  77.  *   HTTP://WWW.GUI.UVA.ES/2M, FTP://FTP.GUI.UVA.ES/PUB/PC/2M
  78.  
  79.  *
  80.  
  81.  *
  82.  
  83.  * fOR ADDITIONAL INFORMATIONS TO fdc PROGRAMMING CHECK:
  84.  
  85.  *     HTTP://DEVELOPER.INTEL.COM/DESIGN/PERIPHRL/DATASHTS/290468.HTM
  86.  
  87.  *   AND GET THE INTEL 82078 chmos sINGLE-cHIP fLOPPY dISK cONTROLLER
  88.  
  89.  *   pdf DOCUMENT:
  90.  
  91.  *     HTTP://WWW.INTEL.NL/DESIGN/PERIPHRL/DATASHTS/29047403.PDF
  92.  
  93.  *   nATIONAL sEMICONDUCTOR HAS ALSO SOME PAGES ABOUT THEIR pc
  94.  
  95.  *   COMPATIBLE CONTROLLERS:
  96.  
  97.  *     HTTP://WWW.NATIONAL.COM/PF/dp/dp8473.HTML
  98.  
  99.  *     HTTP://WWW.NATIONAL.COM/PF/dp/dp8477b.HTML
  100.  
  101.  *
  102.  
  103.  * aNOTHER GOOD SOURCE FOR FLOPPY DISK CONTROLLER PROGRAMMING INFORMATION
  104.  
  105.  * ARE THE LINUX KERNAL SOURCES, YOU COULD HAVE A LOOK INTO:
  106.  
  107.  *     HTTP://WWW.CS.UTEXAS.EDU/USERS/PETERSON/LINUX/INCLUDE/LINUX/FDREG.H
  108.  
  109.  *     HTTP://WWW.CS.UTEXAS.EDU/USERS/PETERSON/LINUX/DRIVERS/BLOCK/FLOPPY.C
  110.  
  111.  */
  112.  
  113.  
  114.  
  115.  
  116.  
  117. #INCLUDE "1581HLVL.H"
  118.  
  119. #INCLUDE <STDIO.H>
  120.  
  121. #INCLUDE <CONIO.H>
  122.  
  123. #INCLUDE <ASSERT.H>
  124.  
  125.  
  126.  
  127. /*
  128.  
  129.   80,// cYLINDERS:   80 CYLINDERS PER DISK
  130.  
  131.    2,// hEADS:        2 SIDES (TRACKS) PER CYLINDER
  132.  
  133.   10,// sECTORS:     10 SECTORS PER TRACK (SIDE)
  134.  
  135.    2,// bPs:        512 BYTES PER SECTOR
  136.  
  137.    2,// rATE:       250 KILOBIT PER SECOND
  138.  
  139.    1,// mODULATION: mfm
  140.  
  141. 0Xdf,// sPECIFYcmd
  142.  
  143. 0X0c,// rwgap3:      12
  144.  
  145. 0X23,// fMTgap:      35
  146.  
  147. 0X00// pATTERN:      0
  148.  
  149. */
  150.  
  151. STATIC CONST fdcPARAMETERsET fdPRMsETS[2]={$7b}
  152.  
  153. {$7b}80,2,10,2,2,1,0Xdf,0X0c,0X23,0X00{$7d},
  154.  
  155. //{$7b}81,2,10,3,0,1,0Xcf,0X0c,0X64,0Xe5{$7d}// gap AND pATTERN ARE FROM THE cmd fd2000 MANUAL
  156.  
  157.    {$7b}81,2,10,3,0,1,0Xcf,0X0c,0X64,0X00{$7d}// gap AND pATTERN ARE FROM THE cmd fd2000 MANUAL
  158.  
  159. {$7d};
  160.  
  161.  
  162.  
  163. STATIC CHAR fILENAMErETsTR[261];// OUTPUT PATH AND FILENAME
  164.  
  165.  
  166.  
  167. // WAITS FOR A DISK OR A NEW DISK IN THE SPECIFIED DRIVE
  168.  
  169. //
  170.  
  171. // INPUT:  DRIVE:THE DRIVE, WHERE A DISK HAS TO BE INSERTED INTO
  172.  
  173. //         NEWdISK:  IF NOT 0, A NEW DISK IS REQUIRED (DISK CHANGE)
  174.  
  175. // OUTPUT: 1 - DISK OR NEW DISK IS IN
  176.  
  177. //         0 - THE WAIT HAS BEEN ABORTED BY THE USER (<esc> PRESSED)
  178.  
  179. //
  180.  
  181. INT WAITfORdISKcHNG(UINT8 DRIVE, INT NEWdISK){$7b}
  182.  
  183. INT KEY=0X20,O,N;
  184.  
  185.  
  186.  
  187. IF(NEWdISK) PRINTF("pLEASE CHANGE THE DISK ...\N");
  188.  
  189.    ELSE PRINTF("wAITING FOR DISK DRIVE READY STATUS, PLEASE INSERT A DISK ...\N");
  190.  
  191.  
  192.  
  193.    O=-1;
  194.  
  195. DO{$7b}
  196.  
  197.    IF(KEY==0X00) WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  198.  
  199.    DO{$7b}
  200.  
  201.       N=SENSEdISKsTATUS(DRIVE);
  202.  
  203.          IF(O!=N){$7b}
  204.  
  205.          PRINTF("\RdISK sTATUS: ");
  206.  
  207. SWITCH(N){$7b}
  208.  
  209.          CASE 0: PRINTF("DISK IS OUT     "); BREAK;
  210.  
  211.             CASE 1: PRINTF("(OLD) DISK IS IN"); BREAK;
  212.  
  213.             CASE 2: PRINTF("NEW DISK IS IN  ");
  214.  
  215.          {$7d}
  216.  
  217.             {$7d}
  218.  
  219.    SWITCH(N){$7b}
  220.  
  221.             CASE 1:// (OLD) DISK IS IN
  222.  
  223.             IF(NEWdISK) BREAK;// IF NEW DISK INSERT NEEDED, DON'T RETURN
  224.  
  225.          CASE 2:// NEW DISK
  226.  
  227. PRINTF("\N");
  228.  
  229.             RETURN 1;
  230.  
  231.          {$7d}
  232.  
  233.          O=N;
  234.  
  235.       {$7d}WHILE(!KBHIT());
  236.  
  237.       {$7d}WHILE((KEY=GETCH())!=0X1b);
  238.  
  239. PRINTF("\N");
  240.  
  241. RETURN 0;
  242.  
  243. {$7d}
  244.  
  245.  
  246.  
  247. // PRINTS ALL VALUES FROM A RESULT STRING TO THE CONSOLE
  248.  
  249. //
  250.  
  251. // INPUT:  POINTER TO THE RESULT STRING STRUCTURE
  252.  
  253. // OUTPUT: NONE
  254.  
  255. //
  256.  
  257. VOID cbmPRINTsTATUS(RESULTsTRING *RESsTR, CONST CHAR *jOB){$7b}
  258.  
  259.    IF(RESsTR==null) RETURN;
  260.  
  261.  
  262.  
  263.    IF(RESsTR->d.st1&0X02) jOB="wRITE PROTECT ";
  264.  
  265.    ELSE IF(jOB==null) jOB="";
  266.  
  267.  
  268.  
  269. IF(RESsTR->d.st0&0Xff00){$7b}
  270.  
  271.    IF(RESsTR->d.st0>=-2) PRINTF("fdc DOESN'T ANSWER (%SPUT TIMEOUT).\N",(RESsTR->d.st0)==-1?"IN":"OUT");
  272.  
  273.       ELSE PRINTF("uNKNOWN fdc COMMUNICATION PROBLEM\N");
  274.  
  275.       {$7d}
  276.  
  277. ELSE PRINTF("0X%02x,0X%02x,0X%02x,%S%S,%2D,%1D,%2D,%1D\N",
  278.  
  279. RESsTR->d.st0, RESsTR->d.st1, RESsTR->d.st2,
  280.  
  281.                jOB,RESsTR->d.st0&0Xc0?"error":"ok",
  282.  
  283. RESsTR->d.cYLINDER+1, RESsTR->d.sIDE,
  284.  
  285. RESsTR->d.sECTOR, RESsTR->d.bYTESps);
  286.  
  287. {$7d}
  288.  
  289.  
  290.  
  291. // RESET AND RECALIBRATE THE SPECIFIED DRIVE
  292.  
  293. //
  294.  
  295. // INPUT:  DRIVE:THE DRIVE, THAT SHALL BE RESETTED
  296.  
  297. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  298.  
  299. //         0 - THE OPERATION WAS UNSUCESSFUL
  300.  
  301. //
  302.  
  303. INT cbmRESETdRIVE(UINT8 DRIVE){$7b}
  304.  
  305. RESETdRIVE(DRIVE);
  306.  
  307. RETURN RECALIBRATEdRIVE(DRIVE,0)==null;
  308.  
  309. {$7d}
  310.  
  311.  
  312.  
  313. // RECALIBRATE THE SPECIFIED DRIVE
  314.  
  315. //
  316.  
  317. // INPUT:  DRIVE:THE DRIVE, THAT SHALL BE RECALIBRATED
  318.  
  319. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  320.  
  321. //         0 - THE OPERATION WAS UNSUCESSFUL
  322.  
  323. //
  324.  
  325. INT cbmRECALIBRATE(UINT8 DRIVE){$7b}
  326.  
  327. RESULTsTRING *res;
  328.  
  329.    UINT I;
  330.  
  331.  
  332.  
  333.    FOR(I=0;I<3;I++){$7b}
  334.  
  335. res=RECALIBRATEdRIVE(DRIVE,0);
  336.  
  337. IF(res==null) BREAK;
  338.  
  339. cbmPRINTsTATUS(res,"rECALIBRATE ");
  340.  
  341.       {$7d}
  342.  
  343.  
  344.  
  345. IF(res!=null && !cbmRESETdRIVE(DRIVE)){$7b}
  346.  
  347. PRINTF("uNSUCCESSFUL ATTEMPT TO RECALIBRATE DRIVE %D\N",DRIVE);
  348.  
  349. //cbmPRINTsTATUS(res);
  350.  
  351. RETURN 0;
  352.  
  353. {$7d}
  354.  
  355. RETURN 1;
  356.  
  357. {$7d}
  358.  
  359.  
  360.  
  361. // PERFORM A READ/WRITE HEAD SEEK OF THE SPECIFIED DRIVE
  362.  
  363. //
  364.  
  365. // INPUT:  DRIVE:THE DRIVE, WHERE THE SEEK SHALL BE DONE
  366.  
  367. //         TRACK:THE CYLINDER NUMBER, WHERE THE SEEK SHALL BE DONE
  368.  
  369. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  370.  
  371. //         0 - THE OPERATION WAS UNSUCESSFUL
  372.  
  373. //
  374.  
  375. INT cbmSEEK(UINT8 DRIVE, UINT8 CYL){$7b}
  376.  
  377. RESULTsTRING *res; //,rs;
  378.  
  379. UINT8 T=CYL-1;
  380.  
  381. UINT RETRY=3;
  382.  
  383.  
  384.  
  385. WHILE((res=SEEKtOcYL(DRIVE,T,0))!=null){$7b}
  386.  
  387. cbmPRINTsTATUS(res,"sEEK ");
  388.  
  389. IF(RETRY--<=0 {$7c}{$7c} !cbmRECALIBRATE(DRIVE)){$7b}
  390.  
  391. PRINTF("uNSUCCESSFUL ATTEMPT TO SEEK TO TRACK %2D ON DRIVE %D\N",CYL,DRIVE);
  392.  
  393. //cbmPRINTsTATUS(res);
  394.  
  395. RETURN 0;
  396.  
  397. {$7d}
  398.  
  399. {$7d}
  400.  
  401. RETURN 1;
  402.  
  403. {$7d}
  404.  
  405.  
  406.  
  407. // SETS THE FLOPPY DISK PARAMETER TABLE TO THE SELECTED TYPE
  408.  
  409. //
  410.  
  411. // INPUT:  sET:THE NAME (ENUM CONSTANT) OF THE PREDEFINED PARAMETER SET
  412.  
  413. // OUTPUT: NONE
  414.  
  415. //
  416.  
  417. VOID cbmPRESETfdPRM(UINT8 DRIVE, fdPRMsET sET){$7b}
  418.  
  419. IF(sET<cbm1581 {$7c}{$7c} sET>=fdundef) RETURN;// UNKNOWN TYPE, DON'T CHANGE ANYTHING
  420.  
  421.  
  422.  
  423. ASSERT(fdPRMsETS[sET].sECTORS<=mAXsECTORS);
  424.  
  425. // INCREASE SECTOR BUFFER PARAMETER VIA central.h, IF ASSERTION FAULT
  426.  
  427. ASSERT((128U << fdPRMsETS[sET].bPs)*fdPRMsETS[sET].sECTORS<=tRbUFsIZE);
  428.  
  429. // INCREASE TRACK BUFFER SIZE VIA central.h, IF ASSERTION FAULT
  430.  
  431.  
  432.  
  433. fdPRM=fdPRMsETS[sET];
  434.  
  435. cbmRECALIBRATE(DRIVE);
  436.  
  437. {$7d}
  438.  
  439.  
  440.  
  441.  
  442.  
  443. // CHECKS, IF THE INSERTED DISK IS A cbm FORMATTED DISK AND DETECTS THE FORMAT
  444.  
  445. //
  446.  
  447. // INPUT:  DRIVE:THE DRIVE, WHERE THE DISK TO BE CHECKED IS IN
  448.  
  449. // OUTPUT: non_3_5 -THE DRIVE TYPE IS NO 3,5" TYPE
  450.  
  451. //         cbm1581 - THE DISK WAS DETECTED AS cbm 1581 DISK FORMAT COMPATIBLE
  452.  
  453. //         cmdfd2m - THE DISK WAS DETECTED AS cmd fd2000 DISK FORMAT COMPATIBLE
  454.  
  455. //         fdundef - THE DISK WAS NOT DETECTED AS A cbm FORMAT TYPE
  456.  
  457. //
  458.  
  459. fdPRMsET cbmCHECKdISK(UINT8 DRIVE){$7b}
  460.  
  461. RESULTsTRING rs;
  462.  
  463. fdcPARAMETERsET OLDfdPRM=fdPRM;// SAVE CURRENT PARAMETER SET
  464.  
  465.  
  466.  
  467.    fdPRMsETpsET;
  468.  
  469. CHARSECmAP[mAXsECTORS];// mAXsECTORS IS DEFINED IN central.h
  470.  
  471.  
  472.  
  473.    UINT8 WRONGid,TYPE,DObr=0Xff;
  474.  
  475. INT   I,TMO;
  476.  
  477.  
  478.  
  479.    // DO A cmos CHECK, IF IT IS A 3,5" DRIVE
  480.  
  481.       // IF NOT, RETURN -1 (CAN NEVER BE A "CORRECT" DISK)
  482.  
  483.    DISABLE();
  484.  
  485. OUTPORTB(0X70, 0X10);// cmos ADDRESS 0X10
  486.  
  487. TYPE=INPORTB(0X71);// READ ADDRESSED cmos VALUE
  488.  
  489.    ENABLE();
  490.  
  491.    SWITCH(DRIVE){$7b}
  492.  
  493.    CASE 0:TYPE>>=4;BREAK;// TEST UPPER NIBBLE
  494.  
  495.       CASE 1:TYPE&=0X0f;BREAK;// TEST LOWER NIBBLE
  496.  
  497.       DEFAULT:TYPE=0X04;// ASSUME 1,44 mb DRIVE
  498.  
  499.    {$7d}
  500.  
  501.  
  502.  
  503.    IF(TYPE<3 {$7c}{$7c} TYPE>5) RETURN non_3_5;// CAN'T SUPPORT THESE DISK TYPES (5,25")
  504.  
  505.    IF(TYPE==3) DObr&={$7e}1;// 500 KBPS ARE NOT SUPPORTED ON 720 Kb DISK DRIVES
  506.  
  507.  
  508.  
  509.    FOR(psET=fdundef-1;psET>fdunknw;psET--){$7b}
  510.  
  511.    IF(DObr&(1<<fdPRMsETS[psET].bITRATE)){$7b}// IF THE WISHED BITRATE IS SUPPORTED
  512.  
  513. cbmPRESETfdPRM(DRIVE,psET);// sET BITRATE, MODULATION AND SPECIFYcmd
  514.  
  515. IF(cbmRECALIBRATE(DRIVE)){$7b}// TRACK 0 SHOULD BE SELECTED
  516.  
  517.             FOR(I=0;I<fdPRM.sECTORS;I++) SECmAP[I]=0;// DELETE SECTOR DETECTION MAP
  518.  
  519.             WRONGid=0;
  520.  
  521.  
  522.  
  523.  
  524.  
  525.                // WAIT FOR MORE THAN 4 TIMER TICKS (222 MS, A DISK ROUND)
  526.  
  527.          I=5;
  528.  
  529.    TMO=PEEKB(0X40, 0X6c);
  530.  
  531.             WHILE(READsECTORid(DRIVE,0,&rs,1)){$7b}
  532.  
  533.    IF(TMO!=PEEKB(0X40, 0X6c)){$7b}
  534.  
  535.    TMO=PEEKB(0X40,0X6c);
  536.  
  537.                   IF(I--<0) BREAK;
  538.  
  539.                   {$7d}
  540.  
  541.               IF(rs.d.cYLINDER!=0) WRONGid{$7c}=1;// tRACKhEADER WRONG
  542.  
  543.               IF(rs.d.sIDE!=0)     WRONGid{$7c}=2;// sIDEhEADER WRONG
  544.  
  545.    IF(rs.d.sECTOR<1 {$7c}{$7c} rs.d.sECTOR>fdPRM.sECTORS)
  546.  
  547.                   WRONGid{$7c}=4;// sECTORhEADER WRONG
  548.  
  549.    ELSE SECmAP[rs.d.sECTOR-1]=1;// MARK SECTOR READ
  550.  
  551.               IF(rs.d.bYTESps!=fdPRM.bPs)
  552.  
  553.    WRONGid{$7c}=8;// bPshEADER WRONG
  554.  
  555.                {$7d}
  556.  
  557.             IF(I>=5){$7b}// READsECTORid TIMEOUT HAPPENED
  558.  
  559.    // DESELECT THE DESIRED BITRATE
  560.  
  561. #IF (messages >= 5)
  562.  
  563. FPRINTF(STDERR,"wRONG BITRATE, DESELECTING %D\N",fdPRMsETS[psET].bITRATE);
  564.  
  565. #ENDIF
  566.  
  567.       DObr&={$7e}(1<<fdPRMsETS[psET].bITRATE);
  568.  
  569.    // RESET CONTROLLER WITHOUT RECALIBRATING AGAIN
  570.  
  571.    RESETdRIVE(DRIVE);
  572.  
  573.                {$7d}
  574.  
  575.    ELSE{$7b}
  576.  
  577.          FOR(I=0;I<fdPRM.sECTORS;I++) IF(!SECmAP[I]) BREAK;
  578.  
  579.          IF(!WRONGid && I>=fdPRM.sECTORS) BREAK;// FORMAT IS DETECTED
  580.  
  581. #IF (messages >= 5)
  582.  
  583. FPRINTF(STDERR,"fORMAT IS NOT DETECTED: 0X%02x, %D OF %D\N",WRONGid,I,fdPRM.sECTORS);
  584.  
  585. #ENDIF
  586.  
  587.    {$7d}
  588.  
  589.    {$7d}
  590.  
  591. {$7d}
  592.  
  593.       {$7d}
  594.  
  595. fdPRM=OLDfdPRM;// RESTORE PARAMETER SET (SHOULD BE DRIVE RELATED)
  596.  
  597. cbmRECALIBRATE(DRIVE);
  598.  
  599.    RETURN psET;
  600.  
  601. {$7d}
  602.  
  603.  
  604.  
  605. /*
  606.  
  607. // tHE ALGORITHM ABOVE IS NOT VERY WELL OPTIMIZED, ESPECIALLY NOT, IF YOU
  608.  
  609. // WANT TO DECIDE BETWEEN MUCH MORE DISK FORMATS.
  610.  
  611. // iF THERE ARE E.G. TWO FORMATS, THAT ARE VERY SIMILAR TOGETHER, THEN
  612.  
  613. // THIS ROUTINE WILL NEED TOO MUCH TIME FOR DETECTION, BECAUSE IT SCANS
  614.  
  615. // THE DISK TRACK FOR EACH FORMAT AGAIN AND AGAIN.
  616.  
  617. //
  618.  
  619. // iT WOULD BE MUCH BETTER TO FIRST DETECT THE DRIVE TYPE (3,5" OR 5.25")
  620.  
  621. // FROM THE cmos ENTRY, SO THAT STANDARD PARAMETERS CAN BE SPECIFIED FOR
  622.  
  623. // EACH BITRATE. tHEN THE RIGHT BITRATE AND MODULATION SHOULD BE DETECTED
  624.  
  625. // AND IF IT CAN BE FOUND, THE TRACK SCAN SHOULD BE DONE BY FILLING UP A
  626.  
  627. // TABLE, THAT HOLDS THE INFORMATIONS READ FROM EACH SECTOR HEADER.
  628.  
  629. // aFTER THIS, THE DRIVE TYPE, BITRATE AND TABLE ENTRIES SHOULD BE
  630.  
  631. // COMPARED AGAINST THE DIFFERENT FORMAT SPECIFICATION ENTRIES.
  632.  
  633. // iF NO FORMAT COULD BE DETECTED, THE REST OF THE UNTESTED BITRATES AND
  634.  
  635. // MODULATIONS HAS TO BE DONE (a PRIORITY TABLE WITH THE BITRATES AND
  636.  
  637. // MODULATION VALUES WOULD HELP MINIMIZING THE DETECTION TIME).
  638.  
  639. //
  640.  
  641. // tHIS WAY WE HAVE TO SCAN A DISK TRACK ONLY ONCE (EXCEPT, IF TWO OR MORE
  642.  
  643. // BITRATES ARE DETECTED ON THE SAME TRACK).
  644.  
  645. //
  646.  
  647. // tHE ALGORITHM BELOW SHOULD WORK MUCH BETTER, WHEN SUPPORTING ALL THE
  648.  
  649. // DIFFERENT FORMATS IS NEEDED, BUT i FIGURED OUT, THAT IT IS VERY LAME.
  650.  
  651.  
  652.  
  653.  
  654.  
  655. // CHECKS, IF THE INSERTED DISK IS A cbm FORMATTED DISK AND DETECTS THE FORMAT
  656.  
  657. //
  658.  
  659. // INPUT:  DRIVE:THE DRIVE, WHERE THE DISK TO BE CHECKED IS IN
  660.  
  661. // OUTPUT: non_3_5 -THE DRIVE TYPE IS NO 3,5" TYPE
  662.  
  663. //         cbm1581 - THE DISK WAS DETECTED AS cbm 1581 DISK FORMAT COMPATIBLE
  664.  
  665. //         cmdfd2m - THE DISK WAS DETECTED AS cmd fd2000 DISK FORMAT COMPATIBLE
  666.  
  667. //         fdundef - THE DISK WAS NOT DETECTED AS A cbm FORMAT TYPE
  668.  
  669. //
  670.  
  671. fdPRMsET cbmCHECKdISK(UINT8 DRIVE){$7b}
  672.  
  673. RESULTsTRING rs;
  674.  
  675. fdcPARAMETERsET OLDfdPRM=fdPRM;// SAVE CURRENT PARAMETER SET
  676.  
  677.    UINT8 rATES[4]={$7b}2,0,3,1{$7d};// BITRATES 250, 500, 1000/125 AND 300 KBPS
  678.  
  679.  
  680.  
  681.    fdPRMsETpsET;
  682.  
  683. CHARSECmAP[mAXsECTORS];// mAXsECTORS IS DEFINED IN central.h
  684.  
  685.  
  686.  
  687.    UINT8 WRONGid;
  688.  
  689. INT   I,TMO,rATE,mDLTN;
  690.  
  691.  
  692.  
  693.    // DO A cmos CHECK, IF IT IS A 3,5" DRIVE
  694.  
  695.       // IF NOT, RETURN -1 (CAN NEVER BE A "CORRECT" DISK)
  696.  
  697.    DISABLE();
  698.  
  699. OUTPORTB(0X70, 0X10);// cmos ADDRESS 0X10
  700.  
  701. WRONGid=INPORTB(0X71);// READ ADDRESSED cmos VALUE
  702.  
  703.    ENABLE();
  704.  
  705.    SWITCH(DRIVE){$7b}
  706.  
  707.    CASE 0:WRONGid>>=4;BREAK;// TEST UPPER NIBBLE
  708.  
  709.       CASE 1:WRONGid&=0X0f;BREAK;// TEST LOWER NIBBLE
  710.  
  711.       DEFAULT:WRONGid=0X04;// ASSUME 1,44 mb DRIVE
  712.  
  713.    {$7d}
  714.  
  715.  
  716.  
  717.    IF(WRONGid<3 {$7c}{$7c} WRONGid>5) RETURN non_3_5;// CAN'T SUPPORT THESE DISK TYPES (5,25")
  718.  
  719.  
  720.  
  721. fdPRM=fdPRMsETS[0];// LOAD cbm 1581 PARAMETER SET AS STANDARD VALUES
  722.  
  723.    FOR(mDLTN=0;mDLTN<2;mDLTN++){$7b}
  724.  
  725. fdPRM.mODULATION=({$7e}mDLTN)&1;              // TEST mfm FIRST, THEN fm
  726.  
  727.    FOR(rATE=0;rATE<4;rATE++){$7b}
  728.  
  729.          fdPRM.bITRATE=rATES[rATE];// 250, 500, 1000/125, 300
  730.  
  731.          fdPRM.hEADS=0;
  732.  
  733.          fdPRM.bPs=0;
  734.  
  735.          fdPRM.sECTORS=0;
  736.  
  737. IF(cbmRECALIBRATE(DRIVE)){$7b}
  738.  
  739.             FOR(I=0;I<mAXsECTORS;I++) SECmAP[I]=0;// DELETE SECTOR DETECTION MAP
  740.  
  741.             WRONGid=0;
  742.  
  743.                // SCAN A TRACK
  744.  
  745.                // WAIT FOR MORE THAN 4 TIMER TICKS (222 MS, A DISK ROUND)
  746.  
  747.          I=5;
  748.  
  749.    TMO=PEEKB(0X40, 0X6c);
  750.  
  751.             WHILE(READsECTORid(DRIVE,0,&rs,1)){$7b}
  752.  
  753.    IF(TMO!=PEEKB(0X40, 0X6c)){$7b}
  754.  
  755.    TMO=PEEKB(0X40,0X6c);
  756.  
  757.                   IF(I--<0) BREAK;
  758.  
  759.                   {$7d}
  760.  
  761.                IF(!fdPRM.sECTORS++){$7b}      // FIRST SECTOR READ
  762.  
  763.                fdPRM.hEADS=rs.d.sIDE;// ALL SIDE AND bPs id FIELDS OF THE
  764.  
  765.                fdPRM.bPs=rs.d.bYTESps;// WHOLE TRACK SHOULD BE THE SAME
  766.  
  767.                {$7d}
  768.  
  769.  
  770.  
  771.               IF(rs.d.cYLINDER!=0) WRONGid{$7c}=1;// tRACKhEADER WRONG
  772.  
  773.               IF(rs.d.sIDE!=fdPRM.hEADS)
  774.  
  775. WRONGid{$7c}=2;// sIDEhEADER WRONG
  776.  
  777.    IF(rs.d.sECTOR<1 {$7c}{$7c} rs.d.sECTOR>mAXsECTORS)
  778.  
  779.                   WRONGid{$7c}=4;// sECTORhEADER NOT SUPPORTED
  780.  
  781.    ELSE SECmAP[rs.d.sECTOR-1]=1;// MARK SECTOR READ
  782.  
  783.               IF(rs.d.bYTESps!=fdPRM.bPs)
  784.  
  785.    WRONGid{$7c}=8;// bPshEADER WRONG
  786.  
  787.                {$7d}
  788.  
  789.             IF(I>=5){$7b}// READsECTORid TIMEOUT HAPPENED
  790.  
  791.    // DESELECT THE DESIRED BITRATE
  792.  
  793. #IF (messages >= 5)
  794.  
  795. FPRINTF(STDERR,"nO DETECTION WITH MODULATION %D AND BITRATE %D\N",
  796.  
  797.                 fdPRM.mODULATION,fdPRM.bITRATE);
  798.  
  799. FPRINTF(STDERR,"tIMEOUT VALUES: TMO %D, ACT: %D\N",TMO,PEEKB(0X40, 0X6c));
  800.  
  801. #ENDIF
  802.  
  803.    // RESET CONTROLLER WITHOUT RECALIBRATING AGAIN
  804.  
  805.    RESETdRIVE(DRIVE);
  806.  
  807.                {$7d}
  808.  
  809.    ELSE{$7b}
  810.  
  811.             IF(!WRONGid){$7b}// HEADERS ARE NOT "SYMMETRIC"
  812.  
  813.                // CHECK THE READ TRACK AGAINST THE SUPPORTED FORMATS
  814.  
  815.       FOR(psET=fdundef-1;psET>fdunknw;psET--){$7b}
  816.  
  817.                   // COMPARE THE SELECTED BITRATE AGAINST THE SPECIFIED
  818.  
  819.                   IF(fdPRMsETS[psET].bITRATE!=rATES[rATE]) CONTINUE;
  820.  
  821.                   // COMPARE THE SELECTED MODULATION AGAINST THE SPECIFIED
  822.  
  823.                   IF(fdPRMsETS[psET].mODULATION!=fdPRM.mODULATION) CONTINUE;
  824.  
  825.                   // COMPARE THE READ SIDE (MUST BE 0/SWAPPED)
  826.  
  827.                   IF(fdPRM.hEADS!=0) CONTINUE;
  828.  
  829.                   // COMPARE THE READ bPs AGAINST THE SPECIFIED
  830.  
  831.                   IF(fdPRMsETS[psET].bPs!=fdPRM.bPs) CONTINUE;
  832.  
  833.                      // CHECK THE SECTORS
  834.  
  835.          FOR(I=0;I<fdPRMsETS[psET].sECTORS;I++){$7b}
  836.  
  837. IF(!SECmAP[I]) BREAK;
  838.  
  839.                         {$7d}
  840.  
  841.                      IF(I<fdPRMsETS[psET].sECTORS) CONTINUE;
  842.  
  843.                      // CHECK, IF THERE ARE NOT MORE MARKED SECTORS
  844.  
  845.                      FOR(;I<mAXsECTORS;I++){$7b}
  846.  
  847. IF(SECmAP[I]) BREAK;
  848.  
  849.                      {$7d}
  850.  
  851.                      IF(I<mAXsECTORS) CONTINUE;
  852.  
  853.  
  854.  
  855.                      // ALL TESTS ARE SUCCESSED, THIS SEEMS
  856.  
  857. // TO BE THE RIGHT FORMAT
  858.  
  859. fdPRM=OLDfdPRM;// RESTORE PARAMETER SET (SHOULD BE DRIVE RELATED)
  860.  
  861. cbmRECALIBRATE(DRIVE);
  862.  
  863.    RETURN psET;
  864.  
  865.                   {$7d}
  866.  
  867.                   {$7d}
  868.  
  869. #IF (messages >= 5)
  870.  
  871. FPRINTF(STDERR,"cURRENT TRACK FORMAT IS NOT SUPPORTED 0X%02x %D %D %D %D\N",
  872.  
  873.  WRONGid,fdPRM.mODULATION,fdPRM.bITRATE,fdPRM.hEADS,fdPRM.bPs);
  874.  
  875. FPRINTF(STDERR,"rEAD SECTOR NUMBERS:");
  876.  
  877.                FOR(I=0;I<mAXsECTORS;I++) IF(SECmAP[I]){$7b}
  878.  
  879. FPRINTF(STDERR,"%D, ",I+1);
  880.  
  881.                   {$7d}
  882.  
  883. FPRINTF(STDERR,"\N");
  884.  
  885. #ENDIF
  886.  
  887.                {$7d}
  888.  
  889.          {$7d}
  890.  
  891.       {$7d}
  892.  
  893.    {$7d}
  894.  
  895.  
  896.  
  897. fdPRM=OLDfdPRM;// RESTORE PARAMETER SET (SHOULD BE DRIVE RELATED)
  898.  
  899. cbmRECALIBRATE(DRIVE);
  900.  
  901.    RETURN fdunknw;
  902.  
  903. {$7d}
  904.  
  905. */
  906.  
  907.  
  908.  
  909. // RETURN THE SECTOR NUMBER OF THE NEXT AVAILABLE SECTOR HEADER
  910.  
  911. //
  912.  
  913. // INPUT:  DRIVE:THE DRIVE, WHERE THE DISK TO READ IS IN
  914.  
  915. //         CYL:THE CYLINDER NUMBER OF THE TRACK TO READ
  916.  
  917. //         SIDE:THE DISK SIDE NUMBER OF THE TRACK TO READ
  918.  
  919. //         TRIES:THE NUMBER OF RETRIES FOR THIS OPERATION
  920.  
  921. // OUTPUT: 0- THE OPERATION WAS UNSUCCESSFUL
  922.  
  923. //         120- A POSSIBLY NOT cbm COMPATIBLE DISK WAS DETECTED
  924.  
  925. //         1...fdPRM.sECTORS- THE SECTOR NUMBER OF THE CURRENTLY READ SECTOR HEADER
  926.  
  927. //        -1 - THE OPERATION WAS ABORTED BY USER INTERACTION
  928.  
  929. //
  930.  
  931. STATIC INT cbmpRErwv(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE, UINT TRIES){$7b}
  932.  
  933. RESULTsTRING rs, *res;
  934.  
  935. UINT RETR1, RETR2, RETR3, RETR4, RETR5, OP;
  936.  
  937.  
  938.  
  939. OP=255;
  940.  
  941. RETR1=RETR2=RETR3=RETR4=RETR5=TRIES;
  942.  
  943.  
  944.  
  945. WHILE(RETR1>0 && RETR2>0 && RETR3>0 && RETR4>0 &&RETR5>0){$7b}
  946.  
  947.    IF(KBHIT()){$7b}
  948.  
  949.       SWITCH(GETCH()){$7b}
  950.  
  951.             CASE 0X1b: RETURN -1;
  952.  
  953.          CASE 0X00: WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  954.  
  955.          {$7d}
  956.  
  957.       {$7d}
  958.  
  959.  
  960.  
  961. DO{$7b}
  962.  
  963. IF(OP--==4){$7b}
  964.  
  965. RESETdRIVE(DRIVE);
  966.  
  967. SELECTdRIVE(DRIVE);
  968.  
  969. IF((res=SEEKtOcYL(DRIVE,1,0))!=null){$7b}
  970.  
  971. cbmPRINTsTATUS(res,"sEEK ");
  972.  
  973. RETR1--;
  974.  
  975. BREAK;
  976.  
  977. {$7d}
  978.  
  979. {$7d}
  980.  
  981.  
  982.  
  983. OP=1;
  984.  
  985. IF((res=SEEKtOcYL(DRIVE,CYL,0))!=null){$7b}
  986.  
  987. cbmPRINTsTATUS(res,"sEEK ");
  988.  
  989. RETR2--;
  990.  
  991. BREAK;
  992.  
  993. {$7d}
  994.  
  995.  
  996.  
  997. OP=2;
  998.  
  999.          res=&rs;
  1000.  
  1001. IF(!READsECTORid(DRIVE,SIDE,&rs,op_timeout)){$7b}
  1002.  
  1003. cbmPRINTsTATUS(&rs,"rEAD HEADER id ");
  1004.  
  1005. RETR3--;
  1006.  
  1007. BREAK;
  1008.  
  1009. {$7d}
  1010.  
  1011. #IF (messages >= 5)
  1012.  
  1013. FPRINTF(STDERR,"dRIVE %D, tRACK %2D, sIDE %2D   --> rEADid: t %2D, h %D, s %2D, bps %D\N",
  1014.  
  1015.   DRIVE, CYL, SIDE, rs.d.cYLINDER, rs.d.sIDE, rs.d.sECTOR, rs.d.bYTESps);
  1016.  
  1017. #ENDIF
  1018.  
  1019. OP=3;
  1020.  
  1021. IF(rs.d.cYLINDER!=CYL){$7b}
  1022.  
  1023. RETR4--;
  1024.  
  1025. BREAK;
  1026.  
  1027. {$7d}
  1028.  
  1029. IF(rs.d.sIDE!=SIDE {$7c}{$7c} rs.d.sECTOR<1 {$7c}{$7c} rs.d.sECTOR>fdPRM.sECTORS {$7c}{$7c} rs.d.bYTESps!=fdPRM.bPs){$7b}
  1030.  
  1031. PRINTF("pOSSIBLY NO cbm COMPATIBLE DISK INSERTED\N");
  1032.  
  1033. rs.d.sECTOR=120;
  1034.  
  1035. {$7d}
  1036.  
  1037. RETURN rs.d.sECTOR;
  1038.  
  1039.  
  1040.  
  1041. {$7d}WHILE(0);
  1042.  
  1043.  
  1044.  
  1045.      IF(res!=null && res->d.st0<0) BREAK; // TIMEOUT!!!
  1046.  
  1047.  
  1048.  
  1049. IF((res=RECALIBRATEdRIVE(DRIVE,0))!=null){$7b}
  1050.  
  1051. cbmPRINTsTATUS(res,"rECALIBRATE ");
  1052.  
  1053. OP=4;
  1054.  
  1055. RETR5--;
  1056.  
  1057. {$7d}
  1058.  
  1059. {$7d}
  1060.  
  1061. IF(res!=null && res->d.st0<0) PRINTF("fdc IS NOT RESPONDING ON ");
  1062.  
  1063. ELSE PRINTF("%D UNSUCCESSFUL ATTEMPTS TO ",TRIES);
  1064.  
  1065. SWITCH(OP){$7b}
  1066.  
  1067. CASE 1: PRINTF("SEEK TO");BREAK;
  1068.  
  1069. CASE 2: PRINTF("READ SECTOR id FROM");BREAK;
  1070.  
  1071. CASE 3: PRINTF("GET A VALID id FOR");       BREAK;
  1072.  
  1073. CASE 4: PRINTF("RECALIBRATE");
  1074.  
  1075. {$7d}
  1076.  
  1077. IF(OP<4) PRINTF(" SIDE %1D OF CYLINDER %2D OF",SIDE,CYL);
  1078.  
  1079. PRINTF(" DRIVE %D\N",DRIVE);
  1080.  
  1081. RETURN 0;
  1082.  
  1083. {$7d}
  1084.  
  1085.  
  1086.  
  1087. // TRANSFER A TRACK WITH THE MULTIPLE SECTOR fdc FEATURE
  1088.  
  1089. //
  1090.  
  1091. // INPUT:  XFER:THE TRANSFER COMMAND (rEAD, wRITE, wRITE&vERIFY)
  1092.  
  1093. //         DRIVE:THE DRIVE, WHERE THE DISK TO IS IN
  1094.  
  1095. //         CYL:THE CYLINDER NUMBER OF THE TRACK TO HANDLE
  1096.  
  1097. //         SIDE:THE DISK SIDE NUMBER OF THE TRACK TO HANDLE
  1098.  
  1099. //         BUFFER:   A POINTER TO THE DATA TRANSFER BUFFER
  1100.  
  1101. //         ILEAVE:AN INTERLEAVE FACTOR TO BE USED
  1102.  
  1103. //         RETRIES:THE NUMBER OF RETRIES FOR THIS OPERATION
  1104.  
  1105. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  1106.  
  1107. //         0 - THE OPERATION FAILED
  1108.  
  1109. //        -1 - THE OPERATION WAS ABORTED BY USER INTERACTION
  1110.  
  1111. //        -2 - WRITE PROTECT ERROR
  1112.  
  1113. //
  1114.  
  1115. // (nOTE: cbmXFERtRACKss WILL NOT BE INVOKED AUTOMATICALLY ANYMORE)
  1116.  
  1117. //
  1118.  
  1119. INT cbmXFERtRACKss(XFERm XFER, UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1120.  
  1121.  UINT8 HUGE *BUFFER, UINT8 ILEAVE, UINT RETRIES){$7b}
  1122.  
  1123. CONST CHAR  JOB[3]={$7b}'W','V','R'{$7d};
  1124.  
  1125. CONST CHAR *JOBERR[3]={$7b}"wRITE ","vERIFY ","rEAD "{$7d};
  1126.  
  1127. RESULTsTRING *res;
  1128.  
  1129. UINT8 HUGE *BUF;
  1130.  
  1131. UINT RETRY;
  1132.  
  1133. UINT8 V,R,I,T=CYL-1,CSEC;
  1134.  
  1135. INT RET;
  1136.  
  1137.  
  1138.  
  1139. CHAR dONE[mAXsECTORS];// mAXsECTORS IS DEFINED IN central.h
  1140.  
  1141.    // MARKERS: 0 - TO WRITE
  1142.  
  1143. //          1 - TO VERIFY
  1144.  
  1145. //          2 - TO READ
  1146.  
  1147. //          3 - READ/WRITE/VERIFY ERROR
  1148.  
  1149. //  -1- DONE
  1150.  
  1151.  
  1152.  
  1153.    SWITCH(XFER&(wRvRFY{$7c}rEAD)){$7b}
  1154.  
  1155.       DEFAULT:
  1156.  
  1157.       RETURN -1;
  1158.  
  1159.       CASE 0:
  1160.  
  1161.       R=0;
  1162.  
  1163.       IF(XFER&fORMAT) BREAK;
  1164.  
  1165.          RETURN -1;
  1166.  
  1167.    CASE rEAD:
  1168.  
  1169.       IF(XFER&fORMAT){$7b}
  1170.  
  1171. RETURN -1;
  1172.  
  1173.             {$7d}
  1174.  
  1175.       R=2;
  1176.  
  1177.          BREAK;
  1178.  
  1179.       CASE wRITE:
  1180.  
  1181.       CASE wRvRFY:
  1182.  
  1183.       R=0;
  1184.  
  1185.          BREAK;
  1186.  
  1187.       CASE vERIFY:
  1188.  
  1189.       R=1;
  1190.  
  1191.    {$7d}
  1192.  
  1193. FOR(CSEC=0;CSEC<fdPRM.sECTORS;CSEC++) dONE[CSEC]=R;
  1194.  
  1195.  
  1196.  
  1197.   // CLEAR DONE BUFFER
  1198.  
  1199. ILEAVE%=fdPRM.sECTORS;
  1200.  
  1201.  
  1202.  
  1203.   IF(XFER&fORMAT){$7b}
  1204.  
  1205.   IF(!cbmSEEK(DRIVE,CYL)) RETURN 0;
  1206.  
  1207.   CSEC=0;
  1208.  
  1209.   {$7d}
  1210.  
  1211.   ELSE{$7b}
  1212.  
  1213.   CSEC=RET=cbmpRErwv(DRIVE,T,SIDE,RETRIES);
  1214.  
  1215.    IF(RET<0) RETURN 0;
  1216.  
  1217.   {$7d}
  1218.  
  1219.  
  1220.  
  1221. RETRY=RETRIES;
  1222.  
  1223.  
  1224.  
  1225.    WHILE(RETRY-->0){$7b}
  1226.  
  1227. IF(KBHIT()){$7b}
  1228.  
  1229.    SWITCH(GETCH()){$7b}
  1230.  
  1231.       CASE 0X1b: RETURN -1;
  1232.  
  1233.          CASE 0X00: WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  1234.  
  1235.          {$7d}
  1236.  
  1237.    {$7d}
  1238.  
  1239.  
  1240.  
  1241. IF(XFER&fORMAT){$7b}
  1242.  
  1243.    PRINTF("%2D %1D F  \R",CYL,SIDE);
  1244.  
  1245. #IF (messages >= 2)
  1246.  
  1247.    FPRINTF(STDERR,"%2D %1D F      \N",CYL,SIDE);
  1248.  
  1249. #ENDIF
  1250.  
  1251. res=FORMATcbmTRACK(DRIVE,T,SIDE);
  1252.  
  1253.          IF(res!=null){$7b}
  1254.  
  1255. cbmPRINTsTATUS(res,"fORMAT ");
  1256.  
  1257.          IF(res->d.st1&0X02) RETURN -2;
  1258.  
  1259. IF(!cbmRECALIBRATE(DRIVE) {$7c}{$7c} !cbmSEEK(DRIVE,CYL)) BREAK;
  1260.  
  1261. CONTINUE;
  1262.  
  1263.       {$7d}
  1264.  
  1265.  
  1266.  
  1267.          SWITCH(XFER&(wRvRFY{$7c}rEAD)){$7b}
  1268.  
  1269.          CASE rEAD:
  1270.  
  1271.             R=2;
  1272.  
  1273.                BREAK;
  1274.  
  1275.             CASE wRITE:
  1276.  
  1277.             CASE wRvRFY:
  1278.  
  1279.             R=0;
  1280.  
  1281.                BREAK;
  1282.  
  1283.             CASE vERIFY:
  1284.  
  1285.             R=1;
  1286.  
  1287.          {$7d}
  1288.  
  1289.       FOR(CSEC=0;CSEC<fdPRM.sECTORS;CSEC++) dONE[CSEC]=R;
  1290.  
  1291.  
  1292.  
  1293. IF(XFER&wRvRFY) CSEC=fdPRM.sECTORS-1;
  1294.  
  1295. //IF(XFER&wRvRFY) CSEC=0;
  1296.  
  1297. ELSE RETURN 1;
  1298.  
  1299.          {$7d}
  1300.  
  1301.  
  1302.  
  1303.       V=(XFER&vERIFY)?1:0;// ENDING WITH VERIFY?
  1304.  
  1305.       R=(XFER&wRITE)?0:1;// STARTING WITH WRITING?
  1306.  
  1307.       IF(XFER&rEAD) V=R=2;// OR IS IT READING
  1308.  
  1309.       FOR(;R<=V;R++){$7b}// R=0 - WRITE, R=1 - VERIFY
  1310.  
  1311.    PRINTF("%2D %1D %C  \R",CYL,SIDE,JOB[R]);
  1312.  
  1313.  
  1314.  
  1315. FOR(I=0;I<fdPRM.sECTORS;I++){$7b}// ONE ROUND VERIFY OR WRITE
  1316.  
  1317.    IF(KBHIT()){$7b}
  1318.  
  1319.       SWITCH(GETCH()){$7b}
  1320.  
  1321.             CASE 0X1b: RETURN -1;
  1322.  
  1323.          CASE 0X00: WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  1324.  
  1325.          {$7d}
  1326.  
  1327.       {$7d}
  1328.  
  1329.          // CALCULATE THE FOLLOWING SECTOR NUMBER
  1330.  
  1331.             CSEC+=ILEAVE;
  1332.  
  1333.             CSEC%=fdPRM.sECTORS;
  1334.  
  1335.             // SEARCH THE NEXT SECTOR TO DO (DEPENDEND ON WRITE OR VERIFY)
  1336.  
  1337.                // IF READING OR WRITING, WE SEARCH FOR A TODO ENTRY (0)
  1338.  
  1339.                // IF VERIFYING AFTER WRITING, WE SEARCH FOR A WRITTEN ENTRY (1)
  1340.  
  1341. // SEARCHING THE REST OF THE ARRAY
  1342.  
  1343.             FOR(;CSEC<fdPRM.sECTORS;CSEC++) IF(dONE[CSEC]==R) BREAK;
  1344.  
  1345.             IF(CSEC>=fdPRM.sECTORS){$7b}// NOTHING FOUND, SEARCH FROM THE BEGINNING
  1346.  
  1347. // SEARCHING FROM THE BEGINNING OF THE ARRAY
  1348.  
  1349. FOR(CSEC=0;CSEC<fdPRM.sECTORS;CSEC++) IF(dONE[CSEC]==R) BREAK;
  1350.  
  1351.             IF(CSEC>=fdPRM.sECTORS) BREAK;// NOTHING FOUND, NOTHING MORE TO DO
  1352.  
  1353.             {$7d}
  1354.  
  1355. // NEXT SECTOR TO DO IS: CSEC
  1356.  
  1357.                // CALCULATING BUF POINTER
  1358.  
  1359. BUF=BUFFER+CSEC*(128U << fdPRM.bPs);
  1360.  
  1361. #IF (messages >= 2)
  1362.  
  1363. FPRINTF(STDERR,"%2D %1D %C %3D  \N",CYL,SIDE,JOB[R],CSEC+1);
  1364.  
  1365. #ENDIF
  1366.  
  1367.             SWITCH(R){$7b}
  1368.  
  1369.             CASE 0:// WRITING
  1370.  
  1371. res=WRITEcbmSECTOR(DRIVE,T,SIDE,CSEC+1,BUF);
  1372.  
  1373.                BREAK;
  1374.  
  1375.             CASE 1://VERIFYING
  1376.  
  1377. res=VERIFYcbmSECTOR(DRIVE,T,SIDE,CSEC+1,BUF);
  1378.  
  1379.                BREAK;
  1380.  
  1381.             CASE 2:// READING
  1382.  
  1383. res=READcbmSECTOR(DRIVE,T,SIDE,CSEC+1,BUF);
  1384.  
  1385.                BREAK;
  1386.  
  1387.                DEFAULT:
  1388.  
  1389.                res=null;
  1390.  
  1391.             {$7d}
  1392.  
  1393.             IF(res!=null){$7b}
  1394.  
  1395. cbmPRINTsTATUS(res,JOBERR[R]);
  1396.  
  1397.          IF(res->d.st1&0X02) RETURN -2;
  1398.  
  1399. dONE[CSEC]=3;
  1400.  
  1401.                {$7d}
  1402.  
  1403.             ELSE{$7b}// SUCCESS
  1404.  
  1405.             IF(R<V) dONE[CSEC]=1;// WRITING DONE, VERIFY FOLLOWS
  1406.  
  1407.             ELSE dONE[CSEC]=-1;// dONE
  1408.  
  1409.             {$7d}
  1410.  
  1411.       {$7d}
  1412.  
  1413.       {$7d}
  1414.  
  1415.    // SET ALL NOT DONE JOBS (NOT -1) IN THE DONE BUFFER TO TO DO (0)
  1416.  
  1417.       // IF ALL SECTORS ARE DONE, WE CAN RETURN
  1418.  
  1419.  
  1420.  
  1421.    // MARKERS: 0      - TO DO
  1422.  
  1423. //          0X10   - READ/WRITE/VERIFY ERROR
  1424.  
  1425. //          wRvRFY - WRITTEN, IF VERIFY IS DONE AFTER
  1426.  
  1427. //          OTHER  - DONE
  1428.  
  1429.  
  1430.  
  1431.       R=1;
  1432.  
  1433.      IF(V==1 && (XFER&wRITE)) V=0;// WRITING FOLLOWS ON VERIFY, SET TO "DO WRITE"
  1434.  
  1435.       FOR(I=0;I<fdPRM.sECTORS;I++) IF(dONE[I]!=-1){$7b}
  1436.  
  1437. //      IF(V==1 && (XFER&wRITE)) V=0;
  1438.  
  1439.       dONE[I]=V;// IF THERE ARE NOT DONE OR ERRORNOUS SECTORS,
  1440.  
  1441.         R=0;// WE DO A RETRY
  1442.  
  1443.       {$7d}
  1444.  
  1445.       IF(R) RETURN 1;
  1446.  
  1447.    {$7d}
  1448.  
  1449. PRINTF("%D UNSUCCESSFUL ATTEMPTS TO TRANSFER DATA AT SIDE %1D, CYLINDER %2D, DRIVE %D\N",RETRIES,SIDE,CYL,DRIVE);
  1450.  
  1451. //PRINTF("%D UNSUCCESSFUL ATTEMPTS TO FORMAT SIDE %1D, CYLINDER %2D, DRIVE %D\N",RETRIES,SIDE,CYL,DRIVE);
  1452.  
  1453. //PRINTF("\N%S eRROR\N",(XFER&rEAD)?"rEAD":((XFER&wRITE)?"wRITE":"vERIFY"));
  1454.  
  1455.    RETURN 0;
  1456.  
  1457. {$7d}
  1458.  
  1459.  
  1460.  
  1461. // TRANSFER A TRACK WITH THE MULTIPLE SECTOR fdc FEATURE
  1462.  
  1463. //
  1464.  
  1465. // INPUT:  XFER:THE TRANSFER COMMAND (rEAD, wRITE, wRITE&vERIFY)
  1466.  
  1467. //         DRIVE:THE DRIVE, WHERE THE DISK TO IS IN
  1468.  
  1469. //         CYL:THE CYLINDER NUMBER OF THE TRACK TO HANDLE
  1470.  
  1471. //         SIDE:THE DISK SIDE NUMBER OF THE TRACK TO HANDLE
  1472.  
  1473. //         BUFFER:   A POINTER TO THE DATA TRANSFER BUFFER
  1474.  
  1475. //         ILEAVE:AN INTERLEAVE FACTOR TO BE USED
  1476.  
  1477. //         RETRIES:THE NUMBER OF RETRIES FOR THIS OPERATION
  1478.  
  1479. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  1480.  
  1481. //         0 - THE OPERATION FAILED
  1482.  
  1483. //        -1 - THE OPERATION WAS ABORTED BY USER INTERACTION
  1484.  
  1485. //        -2 - WRITE PROTECT ERROR
  1486.  
  1487. //
  1488.  
  1489. // (nOTE: cbmXFERtRACKss WILL NOT BE INVOKED AUTOMATICALLY ANYMORE)
  1490.  
  1491. //
  1492.  
  1493. INT cbmXFERtRACKms(XFERm XFER, UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1494.  
  1495.  UINT8 HUGE *BUFFER, UINT8 ILEAVE, UINT RETRIES){$7b}
  1496.  
  1497. RESULTsTRING *res;
  1498.  
  1499.    CONST CHAR *JOBERR[4]={$7b}"rEAD ","wRITE ","vERIFY ","fORMAT "{$7d};
  1500.  
  1501.  
  1502.  
  1503. UINT RETRY;
  1504.  
  1505. UINT8 T=CYL-1,CSEC;
  1506.  
  1507. INT RET,JOB;
  1508.  
  1509.  
  1510.  
  1511.   IF(XFER&0X01 && XFER&0X0e){$7b}
  1512.  
  1513.    PRINTF("wOMO ISN iDIOT!!!\N");
  1514.  
  1515. RETURN -1;
  1516.  
  1517.       {$7d}
  1518.  
  1519.  
  1520.  
  1521.   IF(!(XFER&fORMAT)){$7b}
  1522.  
  1523. CSEC=RET=cbmpRErwv(DRIVE,T,SIDE,RETRIES);
  1524.  
  1525.    IF(RET<0) RETURN 0;
  1526.  
  1527.       {$7d}
  1528.  
  1529.  
  1530.  
  1531. ILEAVE%=fdPRM.sECTORS;
  1532.  
  1533. CSEC+=ILEAVE;
  1534.  
  1535. IF(CSEC>fdPRM.sECTORS) CSEC-=fdPRM.sECTORS;
  1536.  
  1537.  
  1538.  
  1539. ILEAVE+=fdPRM.sECTORS-1;// INTERLEAVE IS DECREMENTED BY 1 FOR MULTIPLE
  1540.  
  1541. ILEAVE%=fdPRM.sECTORS;// SECTOR OPERATIONS (DEFAULT 0)
  1542.  
  1543.  
  1544.  
  1545.   IF(XFER&fORMAT){$7b}
  1546.  
  1547. IF(!cbmSEEK(DRIVE,CYL)) RETURN 0;
  1548.  
  1549. CSEC=1;
  1550.  
  1551. {$7d}
  1552.  
  1553.  
  1554.  
  1555. RETRY=RETRIES;
  1556.  
  1557.  
  1558.  
  1559.    WHILE(RETRY-->0){$7b}
  1560.  
  1561.    IF(KBHIT()){$7b}
  1562.  
  1563.       SWITCH(GETCH()){$7b}
  1564.  
  1565.          CASE 0X1b: RETURN -1;
  1566.  
  1567.          CASE 0X00: WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  1568.  
  1569.          {$7d}
  1570.  
  1571.       {$7d}
  1572.  
  1573.    PRINTF("%2D %1D ",CYL,SIDE);
  1574.  
  1575. IF(XFER&rEAD){$7b}
  1576.  
  1577.    PRINTF("R  \R");
  1578.  
  1579. #IF (messages >= 2)
  1580.  
  1581.    FPRINTF(STDERR,"%2D %1D R %3D  \N",CYL,SIDE,CSEC);
  1582.  
  1583. #ENDIF
  1584.  
  1585. JOB=0;
  1586.  
  1587.       res=READcbmTRACK(DRIVE,T,SIDE,CSEC,BUFFER);
  1588.  
  1589.       {$7d}
  1590.  
  1591.       ELSE{$7b}
  1592.  
  1593.          res=null;
  1594.  
  1595. IF(XFER&fORMAT){$7b}
  1596.  
  1597.    PRINTF("F  \R");
  1598.  
  1599. #IF (messages >= 2)
  1600.  
  1601.    FPRINTF(STDERR,"%2D %1D F      \N",CYL,SIDE);
  1602.  
  1603. #ENDIF
  1604.  
  1605. JOB=4;
  1606.  
  1607. res=FORMATcbmTRACK(DRIVE,T,SIDE);
  1608.  
  1609. IF(XFER&wRvRFY){$7b}
  1610.  
  1611. CSEC=1;
  1612.  
  1613.    PRINTF("%2D %1D ",CYL,SIDE);
  1614.  
  1615.             {$7d}
  1616.  
  1617. {$7d}
  1618.  
  1619. IF(res==null && XFER&wRITE){$7b}
  1620.  
  1621.    PRINTF("W  \R");
  1622.  
  1623. #IF (messages >= 2)
  1624.  
  1625.    FPRINTF(STDERR,"%2D %1D W %3D  \N",CYL,SIDE,CSEC);
  1626.  
  1627. #ENDIF
  1628.  
  1629. JOB=1;
  1630.  
  1631. res=WRITEcbmTRACK(DRIVE,T,SIDE,CSEC,BUFFER);
  1632.  
  1633.             {$7d}
  1634.  
  1635. IF(res==null && XFER&vERIFY){$7b}
  1636.  
  1637. IF(XFER&wRITE){$7b}
  1638.  
  1639. CSEC+=ILEAVE;
  1640.  
  1641. IF(CSEC>fdPRM.sECTORS) CSEC-=fdPRM.sECTORS;
  1642.  
  1643.    PRINTF("%2D %1D ",CYL,SIDE);
  1644.  
  1645.             {$7d}
  1646.  
  1647.    PRINTF("V  \R");
  1648.  
  1649. #IF (messages >= 2)
  1650.  
  1651.    FPRINTF(STDERR,"%2D %1D V %3D  \N",CYL,SIDE,CSEC);
  1652.  
  1653. #ENDIF
  1654.  
  1655. JOB=2;
  1656.  
  1657. res=VERIFYcbmTRACK(DRIVE,T,SIDE,CSEC,BUFFER);
  1658.  
  1659.          {$7d}
  1660.  
  1661.       {$7d}
  1662.  
  1663. IF(res==null) RETURN 1;
  1664.  
  1665.       ELSE{$7b}
  1666.  
  1667. cbmPRINTsTATUS(res,JOBERR[JOB]);
  1668.  
  1669.          IF(res->d.st1&0X02) RETURN -2;
  1670.  
  1671.          IF(JOB==4 && (!cbmRECALIBRATE(DRIVE) {$7c}{$7c} !cbmSEEK(DRIVE,CYL))) BREAK;
  1672.  
  1673.          {$7d}
  1674.  
  1675.  
  1676.  
  1677. CSEC+=ILEAVE;
  1678.  
  1679. IF(CSEC>fdPRM.sECTORS) CSEC-=fdPRM.sECTORS;
  1680.  
  1681.    {$7d}
  1682.  
  1683. PRINTF("%D UNSUCCESSFUL ATTEMPTS TO TRANSFER DATA AT SIDE %1D, CYLINDER %2D, DRIVE %D\N",RETRIES,SIDE,CYL,DRIVE);
  1684.  
  1685. //PRINTF("%D UNSUCCESSFUL ATTEMPTS TO TRANSFER DATA, GIVING UP.\N",RETRIES);
  1686.  
  1687. //PRINTF("\N%S eRROR\N",(XFER&rEAD)?"rEAD":((XFER&wRITE)?"wRITE":"vERIFY"));
  1688.  
  1689. // VERBESSERTES cmdPRINTsTATUS: fdc TIMEOUT (IN/OUT)
  1690.  
  1691. // ODER st0 st1 st2 dchs
  1692.  
  1693. //cbmPRINTsTATUS(res);
  1694.  
  1695. RETURN 0;
  1696.  
  1697. {$7d}
  1698.  
  1699.  
  1700.  
  1701. // FORMAT'N'WRITE A TRACK VIA INTEL'S EXTENDED COMMAND
  1702.  
  1703. //
  1704.  
  1705. // INPUT:  XFER:THE TRANSFER COMMAND (rEAD, wRITE, wRITE&vERIFY)
  1706.  
  1707. //         DRIVE:THE DRIVE, WHERE THE DISK TO IS IN
  1708.  
  1709. //         CYL:THE CYLINDER NUMBER OF THE TRACK TO HANDLE
  1710.  
  1711. //         SIDE:THE DISK SIDE NUMBER OF THE TRACK TO HANDLE
  1712.  
  1713. //         BUFFER:   A POINTER TO THE DATA TRANSFER BUFFER
  1714.  
  1715. //         RETRIES:THE NUMBER OF RETRIES FOR THIS OPERATION
  1716.  
  1717. // OUTPUT: 1 - THE OPERATION WAS SUCCESSFUL
  1718.  
  1719. //         0 - THE OPERATION FAILED
  1720.  
  1721. //        -1 - THE OPERATION WAS ABORTED BY USER INTERACTION
  1722.  
  1723. //        -2 - WRITE PROTECT ERROR
  1724.  
  1725. //
  1726.  
  1727. INT cbmFWVtRACK(XFERm XFER, UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1728.  
  1729.  UINT8 HUGE *BUFFER, UINT RETRIES){$7b}
  1730.  
  1731. RESULTsTRING *res;
  1732.  
  1733.    CONST CHAR *JOBERR[3]={$7b}"fORMAT'N'WRITE ","vERIFY "{$7d};
  1734.  
  1735.  
  1736.  
  1737. UINT RETRY;
  1738.  
  1739. UINT8 T=CYL-1;
  1740.  
  1741. INT JOB;
  1742.  
  1743.  
  1744.  
  1745.    // OPERATIONS ALLOWED:
  1746.  
  1747.       // FORMAT'N'WRITE
  1748.  
  1749.       // FORMAT'N'WRITE WITH VERIFY
  1750.  
  1751.   IF(XFER&{$7e}vERIFY) RETURN -1;
  1752.  
  1753.  
  1754.  
  1755. RETRY=RETRIES;
  1756.  
  1757.  
  1758.  
  1759.    WHILE(RETRY-->0){$7b}
  1760.  
  1761.    IF(KBHIT()){$7b}
  1762.  
  1763.       SWITCH(GETCH()){$7b}
  1764.  
  1765.          CASE 0X1b: RETURN -1;
  1766.  
  1767.          CASE 0X00: WHILE(KBHIT()) GETCH();// EAT UP SPECIAL COMBOS
  1768.  
  1769.          {$7d}
  1770.  
  1771.       {$7d}
  1772.  
  1773.    PRINTF("%2D %1D FW \R",CYL,SIDE);
  1774.  
  1775.       res=null;
  1776.  
  1777. #IF (messages >= 2)
  1778.  
  1779.    FPRINTF(STDERR,"%2D %1D FW     \N",CYL,SIDE);
  1780.  
  1781. #ENDIF
  1782.  
  1783. JOB=0;
  1784.  
  1785. res=FNWRITEcbmTRACK(DRIVE,T,SIDE,BUFFER);
  1786.  
  1787.  
  1788.  
  1789. IF(res==null && XFER&vERIFY){$7b}
  1790.  
  1791. PRINTF("%2D %1D V  \R",CYL,SIDE);
  1792.  
  1793. #IF (messages >= 2)
  1794.  
  1795.    FPRINTF(STDERR,"%2D %1D V      \N",CYL,SIDE);
  1796.  
  1797. #ENDIF
  1798.  
  1799. JOB=1;
  1800.  
  1801. res=VERIFYcbmTRACK(DRIVE,T,SIDE,1,BUFFER);
  1802.  
  1803.       {$7d}
  1804.  
  1805. IF(res==null) RETURN 1;
  1806.  
  1807.       ELSE{$7b}
  1808.  
  1809. cbmPRINTsTATUS(res,JOBERR[JOB]);
  1810.  
  1811.          IF(res->d.st1&0X02) RETURN -2;
  1812.  
  1813.          {$7d}
  1814.  
  1815.    {$7d}
  1816.  
  1817. PRINTF("%D UNSUCCESSFUL ATTEMPTS TO FORMAT'N'WRITE AT SIDE %1D, CYLINDER %2D, DRIVE %D\N",RETRIES,SIDE,CYL,DRIVE);
  1818.  
  1819. RETURN 0;
  1820.  
  1821. {$7d}
  1822.  
  1823.  
  1824.  
  1825. // GENERATE A NEW INDEXED FILENAME FROM THE PREVIOUS ONE
  1826.  
  1827. //
  1828.  
  1829. // INPUT:  INsTR:THE OLD INDEXED OR UNINDEXED FILE NAME
  1830.  
  1831. // OUTPUT: NOT null: THE NEW INDEXED FILE NAME
  1832.  
  1833. //         null:A NEW INDEXED FILE NAME COULDN'T BE GENERATED
  1834.  
  1835. //
  1836.  
  1837. CHAR *BUILDiNXnAME(CHAR *INsTR){$7b}
  1838.  
  1839. CONST INT MAXlENGTH=8;
  1840.  
  1841.  
  1842.  
  1843. REGISTER INT I;
  1844.  
  1845. INT LENGTH,DELIMITER,INDEXsTR;
  1846.  
  1847. UNSIGNED LONG INT INX;
  1848.  
  1849. CHAR OUTsTR[13], INXsTR[11], *PTR, *OP, *RS;
  1850.  
  1851.  
  1852.  
  1853. IF(INsTR==null) RETURN null;
  1854.  
  1855.  
  1856.  
  1857.    RS=fILENAMErETsTR;
  1858.  
  1859.    // SEPARATE FILENAME FROM PATH AND COPY PATH INTO RETsTRING
  1860.  
  1861.    // SEARCH END OF STRING AND COPY PATH
  1862.  
  1863. FOR(PTR=INsTR,OP=fILENAMErETsTR;*PTR!='\0';PTR++,OP++) *OP=*PTR;
  1864.  
  1865.    // SEARCH LAST ':', '\' OR '/'
  1866.  
  1867.    WHILE(PTR>=INsTR && *PTR!=':' && *PTR!='\\' && *PTR!='/') PTR--;
  1868.  
  1869.    IF(PTR>=INsTR){$7b}// THERE HAS BEEN A PATH DELIMITER FOUND
  1870.  
  1871.    PTR++;// THE FOLLOWING CHAR IS THE FIRST OF THE FILENAME
  1872.  
  1873.  
  1874.  
  1875. // SUBRACTION OF TWO POINTERS RESULTS IN AN INTEGER
  1876.  
  1877.          // THE PROBLEM IS, THAT IT IS A LONG INT, BUT THE FIRST
  1878.  
  1879.          // POINTER "RETsTR" IS NO FAR POINTER, SO THAT THE CAST
  1880.  
  1881. // IS NEEDED (PERHAPS THIS CAUSES A BUG?)
  1882.  
  1883.       RS=fILENAMErETsTR+(INT)(PTR-INsTR);
  1884.  
  1885.       INsTR=PTR;
  1886.  
  1887.    {$7d}
  1888.  
  1889.  
  1890.  
  1891. DELIMITER=-1;
  1892.  
  1893. FOR(I=0,PTR=INsTR;*PTR!='\0';I++,PTR++) IF(*PTR=='.') DELIMITER=I;
  1894.  
  1895. LENGTH=I;
  1896.  
  1897. IF(DELIMITER==-1) DELIMITER=LENGTH;
  1898.  
  1899.  
  1900.  
  1901. #IF (messages >= 3)
  1902.  
  1903. FPRINTF(STDERR,"dELIMITER: \"%S\"\N",INsTR+DELIMITER);
  1904.  
  1905. #ENDIF
  1906.  
  1907.  
  1908.  
  1909. // GET INDEX STRING PART (UP TO A MAXIMUM OF 8 CHARS)
  1910.  
  1911. FOR(I=DELIMITER,PTR=INsTR+DELIMITER-1;PTR>=INsTR;I--,PTR--)
  1912.  
  1913. IF(*PTR<'0' {$7c}{$7c} *PTR>'9' {$7c}{$7c} DELIMITER-I>=MAXlENGTH)
  1914.  
  1915. BREAK;
  1916.  
  1917. INDEXsTR=I;
  1918.  
  1919.  
  1920.  
  1921. #IF (messages >= 3)
  1922.  
  1923. FPRINTF(STDERR,"iNDEX: \"%S\"\N",INsTR+INDEXsTR);
  1924.  
  1925. #ENDIF
  1926.  
  1927.  
  1928.  
  1929. // BUILD NEW INDEX NUMBER STRING
  1930.  
  1931. IF(DELIMITER==INDEXsTR){$7b}
  1932.  
  1933. // NEW INDEX NUMBER IS 1
  1934.  
  1935. INXsTR[0]='1';
  1936.  
  1937. INXsTR[1]='\0';
  1938.  
  1939. #IF (messages >= 3)
  1940.  
  1941. FPRINTF(STDERR,"NO OLD INDEX, GENERATING \"1\"\N");
  1942.  
  1943. #ENDIF
  1944.  
  1945. {$7d}
  1946.  
  1947. ELSE{$7b}
  1948.  
  1949.    INX=0l;
  1950.  
  1951.    FOR(PTR=INsTR+INDEXsTR,I=INDEXsTR;I<DELIMITER;PTR++,I++){$7b}
  1952.  
  1953.       INX*=10l;
  1954.  
  1955.          INX+=(*PTR-'0');
  1956.  
  1957.       {$7d}
  1958.  
  1959. //INX=STRTOUL(INsTR+INDEXsTR,null,10);
  1960.  
  1961. #IF (messages >= 3)
  1962.  
  1963. FPRINTF(STDERR,"OLD INDEX NUMBER: \"%LU\"\N",INX);
  1964.  
  1965. #ENDIF
  1966.  
  1967. INX++;// BUILD NEXT INDEX NUMBER
  1968.  
  1969. SPRINTF(INXsTR, "%LU", INX);// WRITE INDEX NUMBER TO STRING
  1970.  
  1971. #IF (messages >= 3)
  1972.  
  1973. FPRINTF(STDERR,"NEW INDEX NUMBER: \"%LU\"\N",INX);
  1974.  
  1975. #ENDIF
  1976.  
  1977. {$7d}
  1978.  
  1979.  
  1980.  
  1981. // DETERMINE THE LENGTH OF THE NEW INDEX STRING
  1982.  
  1983. FOR(I=0,PTR=INXsTR;*PTR!='\0';I++,PTR++);
  1984.  
  1985. LENGTH=I;
  1986.  
  1987. #IF (messages >= 3)
  1988.  
  1989. FPRINTF(STDERR,"NEW INDEX LENGTH: \"%D\"\N",I);
  1990.  
  1991. #ENDIF
  1992.  
  1993. IF(LENGTH>MAXlENGTH) RETURN null;// NEW FILENAME WILL BE INVALID
  1994.  
  1995.  
  1996.  
  1997. // COPYING BASE NAME TO OUTsTR
  1998.  
  1999. FOR(I=0,PTR=INsTR,OP=OUTsTR;I<DELIMITER && I<MAXlENGTH;I++,PTR++,OP++) *OP=*PTR;
  2000.  
  2001.  
  2002.  
  2003. // NEW COMBINED STRING WILL BE TO LONG
  2004.  
  2005. I-=LENGTH;
  2006.  
  2007. IF(I<INDEXsTR) I=INDEXsTR;// DON'T EAT UP FILE NAME CHARS, IF NOT NEEDED
  2008.  
  2009. IF(I+LENGTH>=MAXlENGTH) I=MAXlENGTH-LENGTH;
  2010.  
  2011. OP=OUTsTR+I;
  2012.  
  2013.  
  2014.  
  2015. // COPY INDEX NUMBER STRING ONTO THE BASE NAME
  2016.  
  2017. FOR(PTR=INXsTR;I<MAXlENGTH && *PTR!='\0';I++,PTR++,OP++) *OP=*PTR;
  2018.  
  2019.  
  2020.  
  2021. // COPY EXTENSION ONTO FILE NAME
  2022.  
  2023.    FOR(PTR=INsTR+DELIMITER;*PTR!='\0';PTR++,OP++) *OP=*PTR;
  2024.  
  2025.  
  2026.  
  2027. // SETTING STRING END DELIMITER
  2028.  
  2029. *OP='\0';
  2030.  
  2031.  
  2032.  
  2033.    // COPY OUTsTRING INTO STATIC RETURN sTRING, SO THE STRING CAN
  2034.  
  2035.       // AGAING BE THE INPUT OF THIS FUNCTION WITHOUT CONFLICTS
  2036.  
  2037. FOR(PTR=OUTsTR,OP=RS,I=0;I<MAXlENGTH+5;PTR++,OP++,I++) *OP=*PTR;
  2038.  
  2039.  
  2040.  
  2041. RETURN fILENAMErETsTR;
  2042.  
  2043. {$7d}
  2044.  
  2045.  
  2046.  
  2047. // GENERATE A FILENAME WITH THE FORCED EXTENSION
  2048.  
  2049. //
  2050.  
  2051. // INPUT:  INsTR:THE INPUT FILENAME
  2052.  
  2053. // OUTPUT: NOT null: THE NEW GENERATED FILE NAME
  2054.  
  2055. //         null:A NEW FILE NAME COULDN'T BE GENERATED
  2056.  
  2057. //
  2058.  
  2059. CHAR *CHANGEeXTENSION(CHAR *INsTR, fdPRMsET sET){$7b}
  2060.  
  2061. CONST CHAR *eXTENSIONS[2]={$7b}"d81","d2m"{$7d};
  2062.  
  2063. CHAR *PTR, *OP;
  2064.  
  2065.  
  2066.  
  2067. IF(INsTR==null) RETURN null;
  2068.  
  2069.  
  2070.  
  2071.    IF(sET<0 {$7c}{$7c} sET>1){$7b}
  2072.  
  2073. #IF (messages >= 3)
  2074.  
  2075. FPRINTF(STDERR,"sET INVALID, EXTENSION NOT CHANGED, IT'S \"%S\"\N",INsTR);
  2076.  
  2077. #ENDIF
  2078.  
  2079. RETURN INsTR;// LET IT BE UNCHANGED
  2080.  
  2081.       {$7d}
  2082.  
  2083.  
  2084.  
  2085.    // SEPARATE FILENAME FROM PATH AND COPY PATH INTO RETsTRING
  2086.  
  2087.    // SEARCH END OF STRING AND COPY PATH
  2088.  
  2089. FOR(PTR=INsTR,OP=fILENAMErETsTR;*PTR!='\0';PTR++,OP++) *OP=*PTR;
  2090.  
  2091.    *OP='\0';
  2092.  
  2093.  
  2094.  
  2095.    // SEARCH LAST ':', '\' OR '/' IN THE OUTPUT STRING
  2096.  
  2097. WHILE(OP>=fILENAMErETsTR && *OP!=':' && *OP!='\\' && *OP!='/') OP--;
  2098.  
  2099.    OP++;// SELECT THE FOLLOWING CHAR OF THE DELIMITER
  2100.  
  2101.  
  2102.  
  2103.    PTR=null;// SEARCH THE LAST DELIMITING DOT '.', PTR MARKS THE DOT
  2104.  
  2105. WHILE(*OP!='\0'){$7b}
  2106.  
  2107.    IF(*OP=='.') PTR=OP;
  2108.  
  2109.       OP++;
  2110.  
  2111.    {$7d}
  2112.  
  2113.    IF(PTR!=null){$7b}// IF A DOT WAS FOUND DON'T CHANGE ANYTHING
  2114.  
  2115. #IF (messages >= 3)
  2116.  
  2117. FPRINTF(STDERR,"dOT FOUND, EXTENSION NOT CHANGED, IT'S \"%S\"\N",INsTR);
  2118.  
  2119. #ENDIF
  2120.  
  2121. RETURN INsTR;// LET IT BE UNCHANGED
  2122.  
  2123.       {$7d}
  2124.  
  2125.  
  2126.  
  2127.    *OP++='.';
  2128.  
  2129.    PTR=(CHAR *)eXTENSIONS[sET];
  2130.  
  2131. #IF (messages >= 3)
  2132.  
  2133. FPRINTF(STDERR,"cHANGING EXTENSION TO \"%S\"\N",PTR);
  2134.  
  2135. #ENDIF
  2136.  
  2137.  
  2138.  
  2139.    WHILE(*PTR!='\0') *OP++=*PTR++;
  2140.  
  2141.  
  2142.  
  2143. #IF (messages >= 3)
  2144.  
  2145. FPRINTF(STDERR,"fILENAME CHANGED TO \"%S\"\N",fILENAMErETsTR);
  2146.  
  2147. #ENDIF
  2148.  
  2149. RETURN fILENAMErETsTR;
  2150.  
  2151. {$7d}
  2152.  
  2153.