home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / C128CPM / KEY128-3.LBR / LOADKEY3.MZC / LOADKEY3.MAC
Encoding:
Text File  |  2019-04-13  |  9.4 KB  |  330 lines

  1. ;
  2. ; LOADKEY.MAC -- Version 3 -- January 16, 1988
  3. ;
  4. ; Loads key definitions from a disk file.  For Commodore 128 CP/M only.
  5. ;
  6. ; USAGE:
  7. ;
  8. ;    LOADKEY {{d:}<fn>}
  9. ;
  10. ; The file must have a .KEY filetype.  If a filename is not given
  11. ; in the command line, it will be requested.  If a drive is not
  12. ; given, the drive search chain in the System Control Block will be
  13. ; followed to locate it.  If a drive is supplied, only that drive
  14. ; will be searched.  This program will abort on any error.
  15. ;
  16. ; HISTORY:
  17. ;
  18. ; Version 1 -- February 25, 1987 -- Original release.
  19. ;
  20. ; Version 2 -- May 23, 1987 -- Converted some opcodes to Intel Z80 extensions.
  21. ;    Removed my name from sign-on message.  Now sends "failure" code to
  22. ;    BDOS (for conditional SUBMIT's) if the KEY file is not found.
  23. ;
  24. ; Version 3 -- January 16, 1988 -- Added trapping for illegal filenames.
  25. ;    Now makes primitive checks for an invalid KEY file.  BIOS calls
  26. ;    changed from direct addresses to offsets for compatibility
  27. ;    with revised BIOS's.  Sends "failure" code to BDOS on any error,
  28. ;    including illegal filename, invalid KEY file, etc.  Now checks
  29. ;    drive search chain in SCB and follows it to locate KEY file, if
  30. ;    no drive specification is given with the filename.
  31. ;
  32. ;    Eugene L. Pizzetta        CompuServe:  72060,505
  33. ;    481 Revere Street        GEnie:  E.Pizzetta
  34. ;    Revere, MA  02151        Q-Link:  GeneP
  35. ;    Voice:  (617) 284-0891
  36. ;
  37. ; Developed with SLRMAC.  May be assembled with MAC by changing the
  38. ; filetype to ASM.  Z80.LIB required.
  39. ;
  40. ;
  41. WBoot    equ    00h        ; warm boot
  42. Bdos    equ    05h        ; BDOS entry
  43. CpmBuf    equ    80h        ; default DMA buffer
  44. TPA    equ    100h        ; program load address
  45. DskBuf    equ    1000h        ; disk DMA address (Bank 1)
  46. KeyBuf    equ    1000h        ; key table address (Bank 0)
  47. DrvChSt    equ    04Ch        ; drive chain in SCB
  48. DrvChEn    equ    04Fh        ; end of drive chain
  49. Fail    equ    0FF00h        ; program failure return code
  50. ;
  51. ; File control block
  52. ;
  53. Fcb    equ    05Ch        ; default file control block
  54. FcbDr    equ    Fcb        ; drive
  55. FcbEx    equ    Fcb+0Ch        ; extent
  56. FcbName    equ    Fcb+1        ; filename
  57. FcbType    equ    Fcb+9        ; filetype
  58. ;
  59. ; BDOS service functions
  60. ;
  61. PrtStr    equ    9        ; print string on console
  62. GetStr    equ    10        ; get string from console
  63. FOpen    equ    15        ; open file
  64. FClose    equ    16        ; close file
  65. FRead    equ    20        ; read sequential file
  66. SetDma    equ    26        ; set DMA address
  67. FMulti    equ    44        ; set multi-sector count
  68. GetSCB    equ    49        ; get value from System Control Block
  69. BdosRet    equ    108        ; set BDOS return code
  70. FParse    equ    152        ; parse a filename
  71. ;
  72. ; BIOS service functions
  73. ;
  74. BiosMv    equ    25        ; block move
  75. BiosXmv    equ    29        ; set source and destination banks
  76. ;
  77. BEL    equ    07h        ; bell
  78. LF    equ    0Ah        ; linefeed
  79. CR    equ    0Dh        ; carriage return
  80. ;
  81. ;
  82. ; Macros . . .
  83. ;
  84.     MACLIB    Z80
  85. ;
  86.     org    TPA
  87. ;
  88.     jmp    MAIN
  89. ;
  90. ; Tables and messages . . .
  91. ;
  92. MsgSOn:    db    'LOADKEY    Commodore 128    Version 3$'
  93. MsgNFN:    db    CR,LF,LF,'Load key definitions from file: $'
  94. MsgFNF:    db    BEL,CR,LF,LF,'File Not Found.$'
  95. MsgIll:    db    BEL,CR,LF,LF,'Illegal filename.$'
  96. MsgAmb:    db    BEL,CR,LF,LF,'Ambiguous filename not allowed.$'
  97. MsgBad:    db    BEL,CR,LF,LF,'Bad KEY file.$'
  98. MsgDne:    db    CR,LF,LF,'DONE$'
  99. KType:    db    'KEY'        ; key table filetype
  100. PFcb:    dw    CpmBuf+2    ; parameter block for FParse
  101.     dw    Fcb
  102. ScbPb    db    0,0,0,0        ; parameter block for GetSCB
  103. ;
  104. ; Start of program . . .
  105. ;
  106. MAIN:    lxi    d,MsgSOn    ; print sign-on
  107.     call    PRINT
  108. ;
  109. ; First we check for a filename or request one.
  110. ;
  111.     lda    FcbName        ; check for command tail
  112.     cpi    '#'
  113.     jrnc    IsFile        ; tail found
  114.     lxi    d,MsgNFN    ; if not, print message
  115.     call    PRINT
  116.     lxi    d,CpmBuf    ; clear buffer
  117.     mvi    b,20
  118.     mvi    a,0
  119.     call    FILL
  120.     mvi    a,14
  121.     sta    CpmBuf
  122.     lxi    d,CpmBuf
  123.     call    GETS        ; get filename
  124.     call    PARSE        ; parse it, and
  125.     lda    FcbName        ; ..check for error
  126.     cpi    '#'
  127.     jrc    BadNam        ; (there is)
  128.     mvi    a,0FFh        ; ..check for error
  129.     cmp    l
  130.     jrnz    IsFile        ; (none)
  131.     cmp    h
  132.     jrnz    IsFile        ; (none)
  133. Badnam:    lxi    d,MsgIll    ; say it's illegal
  134.     call    PRINT
  135.     jmp    Error        ; ..and abort
  136. ;
  137. IsFile:    lda    KType        ; move .KEY filetype
  138.     lhld    KType+1
  139.     sta    FcbType        ; ..to FCB
  140.     shld    FcbType+1
  141.     mvi    a,'?'        ; check for ambiguous filename
  142.     lxi    h,FcbName
  143.     lxi    b,8
  144.     ccir
  145.     jrnz    FindIt        ; (filename okay)
  146.     lxi    d,MsgAmb    ; say "be more definite"
  147.     call    PRINT
  148.     jmp    Error        ; ..and abort
  149. ;
  150. ; Now we find the file.
  151. ;
  152. FindIt:    lxi    h,Fcb        ; put FCB in HL
  153.     call    SEARCH        ; find the file
  154.     jrnz    RdFile        ; file exists, so read it
  155.     lxi    d,MsgFNF    ; say file doesn't exist
  156.     call     PRINT
  157.     jmp    Error        ; ..and abort
  158. ;
  159. ; Then we load it from disk.
  160. ;
  161. RdFile:    mvi    c,SetDma    ; set DMA for disk read
  162.     lxi    d,DskBuf
  163.     call    Bdos
  164.     mvi    c,FMulti    ; set multi-sector read
  165.     lxi    d,9        ; ..9 sectors
  166.     call    Bdos
  167.     call    READ
  168. ;
  169. ; After the read, we try to check for a bad file before we move the key
  170. ; table to the BIOS and possibly crash the system.  In the code above
  171. ; we tried to load 9 sectors, but the key table file should be only 8
  172. ; sectors long.  Register A should contain an error 1 (reading unwritten
  173. ; data), if the file is shorter than 9 sectors.  Register H should contain
  174. ; the number of sectors read before the error occurred.  That number
  175. ; should be 8.  Any other values in A or H would indicate a file that is
  176. ; too long or too short, so we don't move it.
  177. ;
  178.     cpi    01h        ; check for read error
  179.     jrnz    BadFil        ; (no error?  something's wrong!)
  180.     mov    a,h
  181.     cpi    08h
  182.     jrnz    BadFil        ; (no error?  another problem!)
  183.     call    CLOSE
  184. ;
  185. ; Finally we move the key table to the BIOS in bank 0.
  186.     lxi    d,DskBuf    ; source address, bank 1
  187.     lxi    h,KeyBuf    ; target address, bank 0
  188.     mvi    a,0        ; set count to 0
  189. Again:    push    psw        ; store count
  190.     mvi    c,1        ; set source bank
  191.     mvi    b,0        ; set destination bank
  192.     call    BNKSET        ; set for interbank move
  193.     lxi    b,128        ; number of bytes to move
  194.     call    BNKMOV        ; then move it
  195.     pop    psw        ; get count
  196.     inr    a        ; increment it
  197.     cpi    8        ; eight times yet?
  198.     jrnz    Again        ; if not, go again
  199.     lxi    d,MsgDne    ; say goodbye
  200.     call    PRINT
  201.     jmp    EXIT
  202. ;
  203. ; We come here if the file loaded is shorter or longer than eight sectors.
  204. ; This is the only check made on KEY file validity.
  205. ;
  206. BadFil:    lxi    d,MsgBad    ; report bad file
  207.     call    PRINT        ; ..and fall through to Error
  208. ;
  209. ; We come here if an error has occurred, such as file not found, illegal
  210. ; filename, etc.
  211. ;
  212. Error:    lxi    d,Fail        ; send failure code to BDOS
  213.     mvi    c,BdosRet
  214.     call    Bdos
  215. ;
  216. EXIT:    jmp    WBoot        ; return to CCP
  217. ;
  218. ; Subroutines . . .
  219. ;
  220. ; BNKSET calls BIOS XMOVE function to set up for interbank move.
  221. ; Source bank is expected in C; destination bank in B.  This routine
  222. ; must be called before each call to BNKMOVE, but it doesn't change
  223. ; the pointer registers DE and HL.
  224. ;
  225. BNKSET:    push    h        ; save HL on stack
  226.     lhld    WBoot+1        ; get BIOS address
  227.     mvi    l,BiosXmv*3    ; set XMOVE address
  228.     xthl            ; exchange HL with stack
  229.      ret            ; jump to BIOS & return to caller
  230. ;
  231. ; BNKMOV calls BIOS MOVE function to move a block of memory between
  232. ; two banks.  The number of bytes to move should be in B (128 bytes
  233. ; maximum), the source starting address in DE, and the destination
  234. ; starting address in HL.  On return DE and HL are incremented past
  235. ; the block moved, allowing multiple calls to move large blocks.
  236. ;
  237. BNKMOV:    push    h        ; save HL on stack
  238.     lhld    WBoot+1        ; get BIOS address
  239.     mvi    l,BiosMv*3    ; set MOVE address
  240.     xthl            ; exchange HL with stack
  241.     ret            ; jump to BIOS & return to caller
  242. ;
  243. ; FILL fills an area of memory with the byte in A.  The starting address
  244. ; is expected in DE and the number of bytes in B.
  245. ;
  246. FILL:    stax    d        ; store the byte
  247.     inx    d        ; increment the pointer
  248.     djnz    FILL
  249.     ret
  250. ;
  251. ; SEARCH looks for a file on the given drive or, if no drive is given, it
  252. ; looks on each drive of drive chain in the System Control Block.  If the
  253. ; file is found, SEARCH opens it.  The address of the File Control Block
  254. ; is expected in HL.  If the file is not found, SEARCH returns with the
  255. ; zero flag set.
  256. ;
  257. ; To use this routine in another program, you must initialize a parameter
  258. ; block (ScbPb) of 4 null bytes, and you must include the equates for Bdos,
  259. ; FOpen, GetSCB, DrvChSt, and DrvChEn.
  260. ;
  261. SEARCH:    mvi    a,0        ; see if a drive was given
  262.     cmp    m
  263.     jrz    NoDrv        ; (none given)
  264.     xchg            ; put FCB address in DE
  265.     mvi    c,FOpen        ; and try to open it
  266.     call    Bdos
  267.     inr    a        ; does it exist?
  268.     ret            ; zero flag set if not
  269. ;
  270. NoDrv:    mvi    a,DrvChSt    ; get SCB offset
  271. SLoop:    push    h        ; save FCB address
  272.     sta    ScbPb        ; store offset for BDOS
  273.     lxi    d,ScbPb        ; point to parameter block
  274.     mvi    c,GetSCB    ; get next drive
  275.     call    Bdos
  276.     cpi    0FFh        ; end of drive chain?
  277.     pop    h        ; recover FCB pointer
  278.     rz            ; (yes, return with zero set)
  279. ;
  280.     mov    m,a        ; put drive in FCB
  281.     push    h        ; save FCB pointer
  282.     xchg            ; move pointer to DE
  283.     mvi    c,FOpen        ; and try to open file
  284.     call    Bdos
  285.     inr    a        ; did it exist?
  286.     pop    h        ; recover pointer
  287.     rnz            ; (yes, return without zero set)
  288.     lda    ScbPb        ; get back drive chain offset
  289.     cpi    DrvChEn        ; end of drive chain?
  290.     rz            ; (yes, return with zero set)
  291.     inr    a        ; increment chain offset
  292.     jr    SLoop        ; ..and continue searching
  293. ;
  294. ; CLOSE closes a disk file.
  295. ;
  296. CLOSE:    mvi    c,FClose
  297.     lxi    d,Fcb
  298.     call    Bdos
  299.     ret
  300. ;
  301. ; GETS gets a string from the console.  The string is placed in the buffer
  302. ; pointed to by DE.
  303. ;
  304. GETS:    mvi    c,GetStr
  305.     call    Bdos
  306.     ret
  307. ;
  308. ; PARSE parses a filename in CpmBuf and puts it into Fcb.
  309. ;
  310. PARSE:    lxi    d,PFcb
  311.     mvi    c,FParse
  312.     call    Bdos
  313.     ret
  314. ;
  315. ; PRINT prints string on console.  String address is in DE.
  316. ;
  317. PRINT:    mvi    c,PrtStr
  318.     call    Bdos
  319.     ret
  320. ;
  321. ; READ reads a block of data from a disk file.
  322. ;
  323. READ:    mvi    c,FRead
  324.     lxi    d,Fcb
  325.     call    Bdos
  326.     ret
  327. ;
  328.     end
  329.