home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug046.ark / CPM-FDOS.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  10.2 KB  |  401 lines

  1. ; 10/12/79: 1055
  2. ; P.P.H. LEE,
  3. ; ROYAL MELBOURNE INSTITUTE OF TECHNOLOGY,
  4. ; APPLIED PHYSICS DEPARTMENT,
  5. ; 124 LATROBE STREET, MELBOURNE,
  6. ; VICTORIA 3000, AUSTRALIA.
  7.  
  8. ; PROGRAM TO TRANSFER A CP/M FILE IN DRIVE A: TO AN
  9. ; ICOM FDOS II DISK ON DRIVE B:
  10. ; TO USE THE PROGRAM, TYPE CPM-FDOS NFN, WHERE NFN IS AN
  11. ; EXISTING CP/M FILE THAT IS TO BE TRANSFERED TO THE FDOS
  12. ; DISKETE ON DRIVE B:. THE PROGRAM WILL ASK FOR THE NEW
  13. ; FDOS FILENAME, WHICH MUST BE 5 CHRACTERS LONG MAXIMUM,
  14. ; WITHOUT DRIVE NUMBER (IT ASSUMES DRIVE #1 ALLWAYS),
  15. ; FOLLOWED BY A <CR>.
  16. ; AT THE COMPLETION OF THE TRANSFER, IT WILL REBOOT BACK
  17. ; TO CP/M.
  18. ; WARNING: AN FDOS II INITIALIZED DISKETTE MUST BE IN
  19. ;       DRIVE B:.
  20. ;       ALSO THIS PROGRAM DOES NOT CHECK FOR DUPLICATE
  21. ;       FILENAMES.
  22.  
  23. ; EXTERNAL LINKAGES:
  24. BDOS    EQU    5    ; CP/M BDOS VECTOR
  25. BOOT    EQU    0    ; CP/M WARM BOOT
  26. PBUF    EQU    9    ; CP/M PRINT BUFFER CODE
  27. RDBUF    EQU    10    ; CP/M READ BUFFER CODE
  28. DRSEL    EQU    14    ; CP/M DRIVE SELECT CODE
  29. OPEN    EQU    15    ; CP/M OPEN FILE CODE
  30. READ    EQU    20    ; CP/M READ NEXT SECTOR CODE
  31. STDMA    EQU    26    ; CP/M SET DMA ADDRESS CODE
  32. TFCB    EQU    5CH    ; CP/M DEFAULT FCB ADDRESS
  33. ISIZE    EQU    0C434H    ; FDOS II INPUT FILE SIZE
  34. ITRK    EQU    0C436H    ; FDOS II INPUT TRAK NUMBER
  35. ISCTR    EQU    0C437H    ; FDOS II INPUT SECTOR NUMBER
  36. ICNTR    EQU    0C438H    ; FDOS II INPUT COUNTER
  37. OUNIT    EQU    0C432H    ; FDOS II OUTPUT DRIVE NO.
  38. OSIZE    EQU    0C439H    ; FDOS II OUTPUT FILE SIZE
  39. OTRK    EQU    0C43BH    ; FDOS II OUTPUT TRAK NUMBER
  40. OSCTR    EQU    0C43CH    ; FDOS II OUTPUT SECTOR NUMBER
  41. OCNTR    EQU    0C43DH    ; FDOS II OUTPUT COUNTER
  42. FREAD    EQU    0C033H    ; FDOS II READ BYTE
  43. FWRT    EQU    0C036H    ; FDOS II WRITE BYTE INTO FILE
  44. RSTRV    EQU    0C030H    ; FDOS II RESTORE INPUT POINTERS
  45.  
  46.     ORG    100H    ; SET TO BASE OF TPA
  47.  
  48.     LXI    SP,STACK ; SET STACK POINTER
  49.     LXI    D,AFLNM    ; ASK FOR FDOS FILENAME
  50.     MVI    C,PBUF
  51.     CALL    BDOS
  52.     LXI    H,TBUF    ; GET FDOS FILENAME
  53.     LXI    B,0620H    ; INTO OFLNM
  54.     MOV    M,B    ; BUT FIRST SET LENGHT
  55.     INX    H    ; AND CLEAR IT
  56. FNAME:    MOV    M,C    ; WITH SPACES
  57.     INX    H
  58.     DCR    B
  59.     JNZ    FNAME
  60.     LXI    D,TBUF    ; NOW GET IT
  61.     MVI    C,RDBUF    ; USING BDOS
  62.     CALL    BDOS    ; READ BUFFER
  63.     MVI    A,1    ; SET FDOS II OUTPUT
  64.     STA    OUNIT    ; TO DRIVE #1(B:)
  65.     CALL    OPFLS    ; OPEN FDOS FILE
  66.     ORA    A    ; OK?
  67.     JNZ    FULL    ; BRIF NOT
  68.     LXI    D,TFCB    ; OPEN CP/M FILE
  69.     MVI    C,OPEN
  70.     CALL    BDOS
  71.     CPI    0FFH    ; CHECK FOR ERROR
  72.     JNZ    GET    ; BRIF NO ERROR
  73.     LXI    D,ERMSG    ; ELSE PRINT ERROR MESSAGE
  74.     MVI    C,PBUF
  75.     CALL    BDOS
  76.     JMP    BOOT    ; AND REBOOT
  77. GET:    LXI    H,TBUF-128 ; GET BUFFER ADDRESS
  78.     MVI    A,128    ; SET BUFFER SIZE TO 128 SECTORS
  79. GET1:    STA    TBCNT    ; SAVE IT IN BUFFER COUNT
  80.     LXI    D,128    ; CALCULATE NEXT DMA ADDRESS
  81.     DAD    D
  82.     SHLD    TBDMA    ; SAVE IT
  83.     XCHG        ; PUT IN DE
  84.     MVI    C,STDMA    ;  AND SET IT
  85.     CALL    BDOS
  86.     LXI    D,TFCB    ; SET ADDRESS OF FCB
  87.     MVI    C,READ    ; READ A SECTOR TO BUFFER
  88.     CALL    BDOS
  89.     ORA    A    ; CHECK FOR E-O-F
  90.     JNZ    GET2    ; BRIF IS
  91.     LHLD    TBDMA    ; GET LAST DMA ADDRESS
  92.     LDA    TBCNT    ; GET SECTOR COUNT
  93.     DCR    A    ; SUBTACT ONE
  94.     JNZ    GET1    ; BRIF NOT FINISHED
  95.     LXI    H,TBUF+(128*128) ; SET END OF BUFFER
  96.     SHLD    TBDMA    ; ADDRESS
  97.     JMP    LOAD
  98. GET2:    MVI    A,0FFH    ; SET TB FLAG
  99.     STA    TBFLG
  100. LOAD:    LHLD    TBDMA    ; GET END OF BUFFER ADDRESS
  101.     XCHG        ; TO DE
  102.     LXI    H,TBUF    ; GET START OF BUFFER TO HL
  103. LOAD1:    MOV    A,H    ; CHECK IF
  104.     CMP    D    ; END OF
  105.     JNZ    LOAD2
  106.     MOV    A,L    ; BUFFER HAS BEEN
  107.     CMP    E    ; REACHED
  108.     JZ    LOAD3    ; BRIF IS
  109. LOAD2:    MOV    C,M    ; GET BYTE FROM BUFFER
  110.     CALL    FWRT    ; WRITE IT TO FDOS FILE
  111.     INX    H    ; POINT NEXT
  112.     JMP    LOAD1
  113. LOAD3:    LDA    TBFLG    ; GET FLAG
  114.     ORA    A    ; CHECK IT
  115.     JZ    GET    ; GET NEXT LOAD IF SOME MORE
  116.     CALL    CLFLS    ; ELSE CLOSE FDOS FILE
  117.     JMP    BOOT    ; AND REBOOT CP/M
  118.  
  119. FULL:    LXI    D,DSKFL    ; PRINT ERROR MESSAGE
  120.     MVI    C,PBUF
  121.     CALL    BDOS
  122.     JMP    BOOT    ; AND REBOOT CP/M
  123.  
  124. ; MESSAGES:
  125. AFLNM:    DB    'FDOS II NEW FILENAME: $'
  126. ERMSG:    DB    '* NO SUCH CP/M FILE *',0DH,0AH,'$'
  127. DSKFL:    DB    '* FDOS II DISK FULL *',0DH,0AH,'$'
  128.  
  129. ; SUBROUTINE TO SET ITRK, ISCTR, ISIZE & ICNTR READY TO
  130. ; START READING THE DIRECTORY TRAK OF AN FDOS II 
  131. ; DISKETTE.
  132.  
  133. INDEX:    LXI    H,24    ; 23 SECTORS
  134.     SHLD    ISIZE    ; STORE IN ISIZE
  135.     LXI    H,ITRK    ; POINT TO ITRK
  136.     MVI    M,0    ; TRAK # 0
  137.     INX    H
  138.     LDA    OUNIT    ; GET OUTPUT DRIVE NO.
  139. INDX2:    RRC        ; ROTATE TO 2 MSB
  140.     RRC
  141.     ORI    03H    ; INCORPORATE SECTOR # 3
  142.     MOV    M,A    ; LOAD ISCTR
  143.     INX    H    ; POINT TO ICNTR
  144.     MVI    M,0    ; RESET ICNTR
  145.     RET
  146.  
  147. ; SUBROUTINE TO FIND THE END OF DIRECTORY MARK IN THE
  148. ; DIRECTORY TRACK OF THE DISKETTE.
  149. ; RETURNS WITH ISCTR, OSCTR, ITRK, OTRK, ISIZE & OSIZE
  150. ; POINTING TO THE START OF THE FCB THAT CONTAINS THE
  151. ; EOD MARK.
  152.  
  153. EOD:    CALL    CLEAR    ; CLEAR INPUT BUFFER
  154.     XRA    A    ; SET FLAG TO OUTPUT
  155.     STA    OTRK    ; SET OTRK TO INDEX
  156.     CALL    INDEX
  157. EOD1:    MVI    D,11    ; SET 11 FCB
  158. EOD2:    MVI    E,5    ; SKIP FILENAME
  159.     CALL    SKIPR
  160.     CALL    FREAD    ; GET ATTRIBUTE
  161.     CPI    0FFH    ; EOD?
  162.     JZ    EOD3    ; BRIF IS
  163.     MVI    E,5    ; SKIP REST OF FCB
  164.     CALL    SKIPR
  165.     DCR    D    ; DECREMENT FCB COUNT
  166.     JNZ    EOD2    ; BRIF STILL SOME MORE IN SECTOR
  167.     MVI    E,7    ; ELSE SKIP 7 BYTE TAIL
  168.     CALL    SKIPR
  169.     JMP    EOD1
  170. EOD3:    CALL    CLEAR    ; CLEAR INPUT BUFFER
  171.     LDA    ISCTR    ; DECREMENT SECTOR NUMBER
  172.     STA    OSCTR    ; SET OSCTR
  173.     DCR    A
  174.     STA    ISCTR
  175.     LHLD    ISIZE    ; INCREMENT SIZE
  176.     INX    H
  177.     SHLD    ISIZE    ; AND REPLACE
  178.     SHLD    OSIZE    ; SET OSIZE
  179.     MVI    A,11    ; COMPUTE FCB NUMBER
  180.     SUB    D
  181.     MOV    D,A    ; SAVE RESULT IN D
  182.     RZ        ; RIF FIRST FCB ON SECTOR
  183. EOD4:    MVI    E,11    ; ELSE SKIP R/W TO IT
  184.     CALL    SKIPW
  185.     DCR    D
  186.     JNZ    EOD4    ; LOOP UNTIL THERE
  187.     RET
  188.  
  189. ; SUBROUTINE TO SKIP READING N NUMBER OF BYTES,
  190. ; WHERE N IS IN E REGISTER.
  191.  
  192. SKIPR:    CALL    FREAD
  193.     DCR    E
  194.     JNZ    SKIPR
  195.     RET
  196.  
  197. ; SUBROUTINE TO READ & WRITE BACK N NUMBER OF BYTES,
  198. ; WHERE N IS IN E REGISTER.
  199.  
  200. SKIPW:    PUSH    B    ; SAVE BC
  201. SKPW1:    CALL    FREAD    ; READ BYTE
  202.     MOV    C,A    ; AND WRITE OUT
  203.     CALL    FWRT
  204.     DCR    E    ; DECREMENT COUNT
  205.     JNZ    SKPW1
  206.     POP    B    ; RESTORE BC
  207.     RET
  208.  
  209. ; SUBROUTINE TO CLEAR THE INPUT BUFFER
  210. CLEAR:    LDA    ICNTR    ; GET ICNTR
  211.     ORA    A    ; TEST IT
  212.     RZ        ; RET IF EMPTY
  213.     CALL    FREAD    ; DUMMY READ
  214.     JMP    CLEAR    ; LOOP
  215.  
  216.  
  217. ; SUBROUTINE TO FIND THE END OF DIRECTORY FILE CONTROL
  218. ; BLOCK IN THE DIRECTORY TRACK OF THE DISKETTE, GET THE
  219. ; NEW FILE STARTING ADDRESS AND COMPUTE ITS MAXIMUM SIZE.
  220. ; IT WILL THEN LOAD THE FILENAME, ADDRESS AND MAXIMUM
  221. ; SIZE INTO THE FCB, LEAVING THE EOD MARK WHERE
  222. ; IT IS. THE ADDRESS AND MAXIMUM SIZE WILL ALSO BE
  223. ; LOADED INTO OTRK, OSCTR, OSIZE AND OCNTR RESET TO ZERO.
  224. ; EXPECTS FILENAME & DRIVE NUMBER IN OFLNM & OUNIT.
  225. ; REGISTERS USED: ALL
  226.  
  227. OPFLS:    XRA    A    ; RESET OCNTR
  228.     STA    OCNTR
  229.     CALL    EOD    ; FIND END OF DIRECTORY FCB
  230.     MVI    E,6    ; SKIP READ FILENAME & EOD MARK
  231.     CALL    SKIPR
  232.     MVI    E,5    ; WRITE FILENAME ONTO FCB
  233.     LXI    H,OFLNM
  234. OPFL2:    MOV    C,M    ; GET CHARACTER
  235.     CALL    FWRT
  236.     INX    H    ; POINT NEXT
  237.     DCR    E
  238.     JNZ    OPFL2    ; LOOP UNTIL ALL DONE
  239.     MVI    C,0FFH    ; REPLACE EOD MARK
  240.     CALL    FWRT
  241.     CALL    FREAD    ; GET TRACK NUMBER
  242.     MOV    B,A    ; SAVE IT IN B
  243.     MOV    C,A    ; AND REPLACE
  244.     CALL    FWRT
  245.     CALL    FREAD    ; GET SECTOR NUMBER
  246.     MOV    C,A    ; SAVE IT IN C
  247.     PUSH    B    ; SAVE BOTH IN STACK
  248.     CALL    FWRT    ; AND REPLACE SECTOR NUMBER
  249.     CALL    FREAD    ; SKIP READ
  250.     CALL    FREAD    ; THE SIZE
  251.     POP    B    ; RETRIEVE ADDRESS FROM STACK
  252.     PUSH    B    ; AND RESAVE IT
  253.     LXI    H,2000    ; TOTAL SIZE + 1 - 3
  254.     DCR    C    ; SECTOR NUMBER START FROM 1
  255.     MOV    A,C    ; SUBTRACT SECTOR NUMBER
  256.     CMA
  257.     MOV    E,A
  258.     MVI    D,0FFH    ; BY GETTING IT'S 2'S COMPLEMENT
  259.     INX    D    ; IN DE
  260.     DAD    D    ; AND DOUBLE ADD WITH HL
  261.     LXI    D,-26    ; NOW SUBTRACT THE TRACKS
  262. OPFL7:    DAD    D    ; SUBTRACT 1 TRACK (26 SECTORS)
  263.     DCR    B    ; DECREMENT TRACK NUMBER
  264.     JNZ    OPFL7    ; LOOP UNTIL ALL DONE
  265.     MOV    C,H    ; WRITE MAX SIZE ONTO FCB
  266.     CALL    FWRT
  267.     MOV    C,L
  268.     CALL    FWRT
  269.     CALL    SCOPY    ; COPY THE REST OF THE SECTOR
  270.     DCX    H    ; GET ACTUAL SIZE
  271.     MOV    A,H    ; CHECK FOR ZERO SIZE
  272.     ORA    L    ; IE. DISK IS FULL
  273.     JZ    OPFL9    ; BRIF IS
  274.     SHLD    OSIZE    ; ELSE SET OSIZE TO ACTUAL SIZE
  275.     LXI    H,OTRK    ; POINT TO OTRK
  276.     POP    B    ; RESTORE TRACK SECTOR ADDRESS
  277.     MOV    M,B    ; AND SET OTRK
  278.     INX    H    ; POINT TO OSCTR
  279.     MOV    A,M    ; GET THE DRIVE
  280.     ANI    0C0H    ; NUMBER ONLY
  281.     ORA    C    ; INCORPORATE SECTOR NUMBER
  282.     MOV    M,A    ; AND SET IT
  283.     INX    H    ; POINT TO OCNTR
  284.     MVI    M,0    ; AND RESET IT
  285.     CALL    RSTRV    ; RESTORE INPUT FILE
  286.     XRA    A    ; CLEAR FLAG
  287.     RET
  288.  
  289. OPFL9:    MVI    A,0FFH    ; SET FLAG
  290.     RET
  291.  
  292. ; SUBROUTINE TO CLOSE AN OUTPUT FILE, IE. PAD UP
  293. ; THE LAST SECTOR IF NECCESSARY, COMPUTE THE
  294. ; FILE SIZE AND THEN UPDATE THE FILE DIRECTORY
  295. ; REGISTERS USED: ALL
  296.  
  297. CLFLS:    LDA    OCNTR    ; PAD UP REST OF SECTOR WITH 00H
  298.     ORA    A
  299.     JZ    CLFL1    ; BRIF ALL DONE
  300.     MVI    C,0
  301.     CALL    FWRT
  302.     JMP    CLFLS
  303. CLFL1:    LHLD    OSIZE    ; SAVE LAST OSIZE
  304.     PUSH    H    ; IN STACK FOR LATER
  305.     CALL    EOD    ; FIND EOD
  306.     MVI    E,5    ; SKIP THE FILENAME
  307.     CALL    SKIPW
  308.     CALL    FREAD    ; DISCARD EOD MARK
  309.     MVI    C,0    ; SET TO 0 ATTRIBUTE
  310.     CALL    FWRT
  311.     CALL    FREAD    ; GET TRACK NUMBER
  312.     MOV    B,A    ; SAVE IT IN B
  313.     MOV    C,A    ; AND REPLACE
  314.     CALL    FWRT
  315.     CALL    FREAD    ; GET SECTOR NUMBER
  316.     MOV    C,A    ; AND SAVE IT IN C
  317.     POP    D    ; RETRIEVE OSIZE
  318.     PUSH    B    ; SAVE ADDRESS IN STACK
  319.     PUSH    D    ; RESAVE OSIZE ON TOP OF STACK
  320.     CALL    FWRT    ; AND REPLACE SECTOR
  321.     CALL    FREAD    ; GET MAX SIZE
  322.     MOV    H,A    ; INTO HL
  323.     CALL    FREAD
  324.     MOV    L,A
  325.     POP    D    ; GET OSIZE TO DE
  326.     MOV    A,D    ; GET 2'S COMPLEMENT OF IT
  327.     CMA
  328.     MOV    D,A
  329.     MOV    A,E
  330.     CMA
  331.     MOV    E,A
  332.     INX    D
  333.     DAD    D    ; COMPUTE FILE SIZE
  334.     MOV    A,H    ; CHECK FOR EMPTY FILE
  335.     ORA    A
  336.     JNZ    CLFL2    ; BRIF NOT
  337.     MOV    A,L
  338.     CPI    2    ; MINIMUM FILE SIZE = 2
  339.     JNC    CLFL2    ; BRIF NOT MINIMUM
  340.     INX    H    ; ELSE ADD 1
  341. CLFL2:    MOV    C,H    ; AND WRITE IT
  342.     CALL    FWRT
  343.     MOV    C,L
  344.     CALL    FWRT
  345.     POP    B    ; GET STARTING ADDRESS
  346. CLFL3:    DCX    H    ; COMPUTE NEXT FILE STARTING
  347.     MOV    A,L    ; ADDRESS
  348.     ORA    A    ; BY INCREMENTING THE ADDRESS
  349.     JNZ    CLFL4    ; WHILE DECREMENTING THE SIZE
  350.     MOV    A,H
  351.     ORA    A
  352.     JNZ    CLFL4
  353.     JMP    CLFL5
  354. CLFL4:    INR    C    ; INCREMENT SECTOR NUMBER
  355.     MOV    A,C    ; CHECK IF NEW TRACK
  356.     CPI    27
  357.     JC    CLFL3    ; BRIF NOT
  358.     INR    B    ; ELSE INCREMENT TRACK NUMBER
  359.     MVI    C,1    ; AND RESET SECTOR NUMBER
  360.     JMP    CLFL3
  361. CLFL5:    PUSH    B    ; SAVE NEW ADDRESS IN STACK
  362.     MVI    E,1    ; CHECK IF THAT WAS THE
  363.     LDA    ICNTR
  364.     CPI    19    ; LAST FCB ON SECTOR
  365.     JNC    CLFL6    ; BRIF NOT
  366.     MVI    E,8    ; ELSE ADJUST FOR TAIL
  367. CLFL6:    CALL    SKIPW
  368.     MVI    E,8    ; SKIP READ NEW FCB UP TO SIZE
  369.     CALL    SKIPR
  370.     MVI    E,5
  371. CLFL7:    MVI    C,'*'    ; PUT 5 ASTERISK FILENAME
  372.     CALL    FWRT
  373.     DCR    E
  374.     JNZ    CLFL7    ; LOOP UNTIL ALL DONE
  375.     MVI    C,0FFH    ; PUT NEW EOD MARK
  376.     CALL    FWRT
  377.     POP    D    ; RETRIEVE NEW ADDRESS
  378.     MOV    C,D    ; PUT THEM IN
  379.     CALL    FWRT
  380.     MOV    C,E
  381.     CALL    FWRT
  382.  
  383. ; SUBROUTINE TO COPY THE SECTOR UNTIL ICNTR = 0
  384.  
  385. SCOPY:    LDA    ICNTR    ; GET ICNTR
  386.     ORA    A    ; TEST IT
  387.     MOV    E,A    ; SAVE IT IN E
  388.     RZ        ; RET IF ALREADY ZERO
  389.     JMP    SKIPW    ; NOW DO IT
  390.  
  391.  
  392. ; STORAGE AREA:
  393. TBCNT:    DS    1    ; SECTOR COUNT
  394. TBFLG:    DB    0    ; E-O-F FLAG:    00 = SOME MORE
  395.             ;        FF = NO MORE
  396. TBDMA:    DS    2    ; DMA/END OF BUFFER ADDRESS
  397. STACK    EQU    $+64    ; STACK AREA
  398. TBUF    EQU    STACK
  399. OFLNM    EQU    TBUF+2    ; FDOS II OUTPUT FILENAME
  400.     END
  401.