home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol040 / mds.z80 < prev    next >
Encoding:
Text File  |  1984-04-29  |  13.1 KB  |  637 lines

  1. ; INTEL MDS FDC CARD EMULATOR
  2. ;
  3. ; SOURCED NOV 79 BY TREVOR MARSHALL
  4. ;            Dept E & E Eng
  5. ;            University of West Australia
  6. ;            NEDLANDS, W.A. 6009
  7. ;
  8. ; This version of the source produces, after linking,
  9. ; object code in memory from 600H to A000H to enable
  10. ; a Prom Programmer resident in the host system
  11. ; to directly program the object file
  12. ;
  13. ; A version ORGed at F800H is compiled seperately
  14. ; and is provided on the master disk as MDSABS.Z80
  15. ;
  16. ;
  17. ; REGISTER USAGE DURING READ AND WRITE:
  18. ; D contains the (auto wait) drive control byte
  19. ; IX points to the IOPB base
  20. ; HL points to the current memory DMA address
  21. ; B contains the input byte counter for INI & OUTI
  22. ; C contains DDATA for INI & OUTI
  23. ; B' (alternate) contains the number of records required
  24. ; D' (alternate) contains the current sector address
  25. ; E' (alternate) contains the retry count
  26. ; H' (alternate) contains the previously logged track
  27. ; AF' (alternate) contains the previous drive mask
  28. ; to skip read trk# if it is already logged
  29. ; and allow for fast response without interleaving
  30. ;
  31. ; FDC CONTROLLER DEFINITIONS:
  32. DCONTROL:EQU    63H    ;Control Port
  33. DFLAGS:     EQU    63H    ;FDC Status Port
  34. DDATA:   EQU    67H    ;1793 Data Port
  35. DSTATUS: EQU    64H    ;1793 Status Port
  36. DCOMMAND:EQU    64H    ;1793 Command Port
  37. DTRACK:     EQU    65H    ;1793 Track Port
  38. DSECTOR: EQU    66H    ;1793 Sector Port
  39. DSIDE:    EQU    4    ;Bit 1=0 selects side 1
  40.             ; of D/S drives
  41. ;
  42. ; DISK CONTROL PORT HARDWARE ENVIRONMENT
  43. ; Bits 0-3 select drives 1-4
  44. ; Bit 7 enables auto wait on accesses to DDATA
  45. ; Bit 5 enables dsk drive motors 
  46. ; Bit 4 selects single density (S/D)
  47. ;
  48. ; DISK STATUS PORT HARDWARE REQUIREMENTS
  49. ; Bit 0 is 1793 INTREQ status output
  50. ; Bit 5 indicates head is loaded
  51. ;
  52. ; DISK DENSITY DEFINITIONS
  53. MAXSECTORS: EQU 1AH  ;Single Density
  54. MAXTRACKS:   EQU 4CH  ; 8" Disks
  55. ;
  56. ; PIO DEFINITIONS:
  57. ACOMMAND:EQU    7AH
  58. ADATA:   EQU    78H
  59. BCOMMAND:EQU    7BH
  60. BDATA:   EQU    79H
  61. ;
  62. ; BUS CONTROL:
  63. RELEASE: EQU    7FH    ;I/O To this addr releases bus
  64. HOLD:    EQU    7CH    ;I/O to this addr requests bus
  65. ;
  66. ; MDS PORT DEFINITIONS:
  67. STATUS:  EQU    7EH    ;S100 Bus reads 78H
  68. ;Note that port 78H is referenced directly in ASERVICE
  69. ;TYPE:    Not Implemented
  70. RESULT:  EQU    7DH    ;S100 Bus reads 7BH
  71. ;RESET: Not Implemented
  72. IOPBLOW: EQU    79H
  73. IOPBHIGH:EQU    7AH
  74. ;
  75. ; DISKETTE INSTRUCTION CODES:
  76. NOP:     EQU    0    
  77. SEEK:     EQU    1
  78. FORMAT:     EQU    2
  79. RECALIB: EQU     3
  80. READ:     EQU    4
  81. VERIFY:     EQU    5
  82. WRITE:     EQU    6
  83. WRITEDEL:EQU    7    ;Write deleted data mark;
  84. ;
  85. ; AS THERE IS NO STACK RAM AVAILABLE ALL CODE
  86. ; MUST BE SEQUENTIAL
  87. ;
  88. ; THE PROM PROGRAMMER REQUIRES AN ADDRESS OFFSET
  89. ; OF 0F200H FOR THIS ORG 0F800H CODE
  90. ;
  91. ; THE FOLLOWING MACROS FORM COMMONLY USED ROUTINES
  92. ;
  93. STOP:    MACRO
  94.     LD    SP,STACK; Point at ROM stack
  95.     IN    A,RELEASE
  96.     RETI
  97.     MEND
  98. DONE: MACRO   ;Set up status port & stop
  99.     LD    A,0FH
  100.     OUT    STATUS,A
  101.     STOP
  102.     MEND
  103. ;
  104. INTREQ:    MACRO    ;Wait for intreq
  105. LL#SYM:    IN    A,DFLAGS ;Loop until 1793 INTREQ active
  106.     RRA
  107.     JR    NC,LL#SYM
  108.     MEND
  109. ;
  110. ERRORS: MACRO    #LOOP,#MASK ;Check 1793 for errors
  111.     INTREQ
  112.     IN    A,DSTATUS
  113.     EXX    ;Save working registers
  114.     LD    C,A    ;Save error byte
  115.     AND    80H    ;Not ready mask
  116.     EXX
  117.     JR    NZ,#LOOP    ;Loop until drive ready
  118.     EXX
  119.     LD    A,C
  120.     AND    #MASK    ;General error mask
  121.     JP    NZ,SELECT+OFFSET ;Retry if any errors
  122.     EXX
  123.     MEND
  124. ;
  125. SETUP:    MACRO    ;Set up read and write common parameters
  126. LP:    DL    AA#SYM
  127. AA#SYM:    INC    D    ;Sector #
  128.     LD    A,D
  129.     OUT    DSECTOR,A
  130.     EXX
  131.     LD    A,D
  132.     OUT    DCONTROL,A
  133.     LD    B,80H    ;Input byte count
  134.     IN    A,DFLAGS ;Is head loaded?
  135.     AND    20H
  136.     JR    Z,J2#SYM ;No
  137.     LD    A,0
  138.     JR    J3#SYM
  139. J2#SYM: LD    A,04H    ;Head load mask for 1793
  140. J3#SYM    DL    $
  141.     MEND
  142. ;
  143. CHECK:    MACRO    ;See if read or write is complete
  144.     EXX
  145.     DJNZ    LP
  146.     EXX
  147.     LD    B,0    ;Done
  148.     JP    FINISH+OFFSET
  149.     MEND
  150. ;
  151. ; NOTE THAT THE 1793 NEEDS TIME TO CALCULATE CRC
  152. ; BEFORE THE ERROR STATUS IS AVAILABLE
  153. ; IF THE DRQ IS NOT SERVICED
  154. ; The following delay loop is sufficient (4MHz Z-80)
  155. DELAY:    MACRO
  156.     LD    B,30H    ;12 to 15 give CRC errors
  157. ; 0 to 12 give BUSY flag
  158.     DJNZ    $
  159.     MEND
  160. ;
  161. ; Check for 1793 errors during read and write
  162. DERROR: MACRO    #MASK
  163.     INTREQ
  164.     IN    A,DSTATUS
  165.     EXX
  166.     LD    C,A    ;Save error byte
  167.     EXX
  168. ; Note that we will not check for deleted data marks
  169.     AND    #MASK
  170.     JP    NZ,S2+OFFSET ; Retry errors
  171.     MEND
  172.  
  173. ; LINKER AND PROM PROGRAMMER CODE REQUIREMENTS
  174.     ORG    100H
  175.     JP    0
  176. OFFSET: EQU    0F800H-600H
  177. ; Setup vectors at top of ROM
  178.     ORG    9F4H    ;Effectively FBF4
  179. VEC1:    DW    ASERVICE+OFFSET
  180. VEC2:    DW    BSERVICE+OFFSET
  181. WAIT:    EI
  182.     HALT    ;wait for interrupt
  183. ; STACK: To enable interrupt structure we need a 'stack'
  184.     DW    WAIT+OFFSET
  185. STACK:    EQU    $+OFFSET
  186.     DW    WAIT+OFFSET 
  187.     DW    WAIT+OFFSET
  188. ;
  189. ; Hardware Reset Code
  190.     ORG    600H
  191. START:    JP    0F804H
  192.     NOP
  193. ; The ORG address is now effectively F804H
  194. ; Now setup PIO & Interupts
  195. ;
  196.     IM2
  197.     LD    A,0FBH
  198.     LD    I,A    ;Int vector table near FBF2
  199.     LD    A,0F4H    ;IVEC(A) = FBF4
  200.     OUT    ACOMMAND,A
  201.     LD    A,0F6H    ;IVEC(B) = FBF6
  202.     OUT    BCOMMAND,A
  203.     LD    A,4FH    ;MODE 1
  204.     OUT    ACOMMAND,A
  205.     OUT    BCOMMAND,A
  206.     IN    A,ADATA    ;Set READY handshake
  207.     IN    A,BDATA
  208.     LD    A,87H    ;Enable PIO interrupt mode
  209.     OUT    ACOMMAND,A
  210.     OUT    BCOMMAND,A
  211. ; Now setup output latches
  212.     LD    A,00
  213.     OUT    RESULT,A
  214.     LD    A,0BH    ;:F0:,:F1: ready, not D/D
  215.     OUT    STATUS,A
  216.     EX    AF,AF'
  217.     LD    A,0    ;Clear drive select mask
  218.     EX    AF,AF'
  219.     EXX
  220.     LD    H,0FFH    ;Clear logged trk
  221.     EXX
  222.     LD    SP,STACK
  223.     EI
  224.     HALT
  225. ; Routine to service PIO inputs
  226. ; (79) go to IX lower, (7A) to IX upper
  227. ;
  228. ASERVICE: DI
  229.     OUT    HOLD,A    ; Lock out bus until done
  230.     NOP    ;Allow time for bus control
  231.     NOP
  232.     IN    A,78H ; S100 Status port read (& reset)
  233. ;              ; must be done during bus access
  234.     IN    A,ADATA
  235.     LD    IX,0
  236.     LD    C,A
  237.     LD    B,0
  238.     ADD    IX,BC    ;Now have A in IX
  239.     STOP
  240. BSERVICE: DI
  241.      OUT    HOLD,A    ; Lock out bus until done
  242.     IN    A,BDATA
  243.     LD    B,A
  244.     LD    C,0
  245.     ADD    IX,BC    ; IX now points to IOPB
  246. ; Now select side 0 of disks
  247.     LD    A,2    ;Set bit 1
  248.     OUT    DSIDE,A
  249. ;
  250.     EXX
  251.     LD    E,0AH    ;10 retries
  252.     JR    SELECT
  253. ;
  254. ; NOW BEGIN DECODING COMMAND WORD
  255. ; FIRST SELECT THE DRIVE (:F0:=A:, :F1:=C:)
  256. ;
  257. S2:    EXX
  258.     LD    H,0FFH    ;Log off track if error occurs
  259. ;            ;This will cause a RESTORE cmd
  260. ;            ;To be executed for SEEK errors
  261. SELECT:    LD    A,E
  262.     CP    0    ;Have we retried 10 times?
  263.     LD    A,C    ;Error byte
  264.  
  265.     JP    Z,EXIT+OFFSET
  266.     DEC    E
  267.     EXX
  268.     LD    A,(IX+0)
  269.     AND    3FH ;Check for acceptable channel word
  270.     JP    NZ,CHERROR+OFFSET ; Channel error
  271. ;
  272. ;If the op is NOP,FORMAT or RECALIBRATE 
  273. ;Dont check address field
  274.     LD    A,(IX+1)
  275.     AND    07H    ;Now have opcode field
  276.     CP    1    ;Seek
  277.     JR    Z,DONTSKIP
  278.     SUB    4
  279.     JR    C,SKIP    ; <=3
  280. DONTSKIP:
  281.  
  282. ; Now check for valid IOPB addresses
  283. N12:    LD    A,(IX+3) ;Track address
  284.     SUB    MAXTRACKS+1  ;max track # + 1
  285.     JP    NC,ADDERROR+OFFSET
  286.     LD    A,(IX+4)
  287. ;
  288. ; Must reset bits 4 & 5 of sector byte (a drive select bit)
  289. ; to retain compatibility with S/D MDS systems
  290.     AND    A,09FH
  291.     JP    Z,ADDERROR+OFFSET ;Zero sector #
  292.     SUB    MAXSECTORS+1 ;Max sector # + 1
  293.     JP    NC,ADDERROR+OFFSET
  294.     LD    A,(IX+4) ;Sector addr
  295. ;
  296. ; Must reset bit 5 of sector byte (a drive select bit)
  297. ; to retain compatibility with S/D MDS systems
  298.     AND    A,09FH
  299.     LD    C,(IX+2) ;Number of records requested
  300.     ADD    A,C
  301.     SUB    A,MAXSECTORS+2
  302.     JP    NC,ADDERROR+OFFSET ;Final sector >1AH
  303. ; Address errors trapped, now seek to required track
  304. ;
  305. SKIP:    LD    A,(IX+1) ;Instruction word
  306.     AND    30H    ;Get drive mask
  307.     RRC    A
  308.     RRC    A
  309.     RRC    A
  310.     RRC    A
  311.     CP    3 ; S/D MDS drive #1 mask
  312.     JR    Z,BSELECT ;Select drive B
  313. ; Dont allow for more than 2 drives
  314.     LD    D,0B1H    ;Auto wait,motor on,S/D,A:
  315.     JR    J3
  316. BSELECT: LD    D,0B2H    ;Auto wait,motor on,S/D,B:
  317. ; D contains the drive control byte with auto wait set
  318. ;
  319. ; Now check for recalibrate, nop & format instructions
  320. ;
  321. J3:    LD    A,(IX+1)
  322.     AND    07H
  323.     CP    RECALIB    
  324.     JR    Z,RESTORE
  325.     CP    NOP
  326.     JR    Z,DONOP
  327.     CP    FORMAT
  328.     JR    Z,DONOP
  329.     JR    DOSEEK;Not one of these ops
  330. DONOP:    LD    B,0
  331.     JP    FINISH+OFFSET
  332. RESTORE: LD    A,D    ;Drive control byte
  333.     AND    7FH    ;Reset auto wait
  334.     OUT    DCONTROL,A
  335.      LD    A,0DH    ;1793 Restore command
  336.     OUT    DCOMMAND,A
  337.     ERRORS    RESTORE,99H
  338.     LD    B,0
  339.     JP    FINISH+OFFSET
  340. ;
  341. DOSEEK:     ;Read, write, verify & seek
  342.         ;all require a seek op first
  343. ; Now check if drive is logged
  344. ; trk # will then be available without the read addr op
  345. ;
  346.     EX    AF,AF'
  347.     CP    A,D    ;Is it the same as the last?
  348.     LD    A,D
  349.     JR    NZ,LOG    ;No, log it
  350.     EX    AF,AF'
  351.     EXX
  352.     LD    A,H    ; fetch last trk #
  353.     EXX
  354.     LD    B,A    ;Save it
  355.     CP    (IX+3) ;Is the desired trk the same?
  356.     JR    NZ,LOG2 ;No, read address
  357.     JP    LOGGED+OFFSET
  358. ; Check current track # by reading address from disk
  359. ;NOTE THAT THE 1793 DOES NOT HEAD LOAD ON 'READ ADDRESS'
  360. ; IF THE READY INPUT IS NOT ACTIVE
  361. ; so we must issue a dummy SEEK command first
  362. ;
  363. LOG:    EX    AF,AF'
  364. ; Will first execute a RESTORE command on the new drive
  365. REST1:    LD    A,D
  366.     AND    7FH    ;Reset auto wait
  367.     OUT    DCONTROL,A
  368.     LD    A,0DH    ;1793 Restore command
  369.     OUT    DCOMMAND,A
  370.     ERRORS    REST1,99H
  371. ;
  372. ; Now seek to desired track
  373. LOG2:    LD    A,D
  374.     AND    7FH    ;Reset auto wait
  375.     OUT    DCONTROL,A
  376.     IN    A,DTRACK
  377.     OUT    DDATA,A ;desired trk=current one
  378. L3:    LD    A,1AH   ;Seek, no verify
  379.     OUT    DCOMMAND,A
  380.     ERRORS    LOG2,99H
  381. ;
  382. L2:    LD    A,0C4H    ;1793 Read address cmd
  383.     OUT    DCOMMAND,A
  384.   ;Discard the data bytes
  385.     INTREQ
  386.     DELAY
  387.     IN    A,DSTATUS
  388.     AND    19H    ; status would not be valid
  389.     JR    NZ,L2
  390.     IN    A,DSECTOR   ;where the 1793 puts the trk
  391.     LD    B,A      ;Save it
  392.     EXX
  393.     LD    H,A    ; log it
  394.     EXX
  395. ;
  396. ; Now must clear the data request by reading DDATA
  397.     IN    A,DDATA
  398. ;
  399. LOGGED:    LD    A,B    ;Fetch current track addr
  400.     CP    (IX+3)  ;Is it the same?
  401.     OUT    DTRACK,A
  402.     JR    Z,J11    ;Yes, skip read addr
  403.     LD    A,(IX+3)
  404.     OUT    DDATA,A
  405. S1:    LD    A,D
  406.     AND    7FH
  407.     OUT    DCONTROL,A ;Disable auto wait
  408.     LD    A,1DH    ;Seek with verify
  409.     OUT    DCOMMAND,A
  410.     ERRORS    S1,99H
  411. ; Now have desired track, check to see if op was seek
  412. ;
  413. J11:    LD    A,(IX+1)
  414.     AND    07H
  415.     CP    SEEK
  416.     JP    Z,FINISH+OFFSET ; was seek only
  417. ;
  418. ; Now calculate the number of records
  419. ; and setup dedicated register values
  420. ;
  421.     EXX
  422.     LD    B,(IX+2)  ;Number of records
  423.     LD    A,(IX+4)
  424. ;
  425. ; Must reset bit 5 of sector byte (a drive select bit)
  426. ; to retain compatibility with S/D MDS systems
  427.     LD    D,09FH
  428.     AND    A,D
  429.     LD    D,A
  430.     DEC    D     ;Initial sector (-1 for SETUP)
  431.     EXX
  432. ;
  433.     LD    H,(IX+6) 
  434.     LD    L,(IX+5)
  435.     LD    C,DDATA
  436. ;
  437. ; Was it a read, write or writedel operation?
  438.     LD    A,(IX+1)
  439.     AND    07H
  440.     CP    READ
  441.     JR    Z,DOREAD
  442.     CP    WRITE
  443.     JP    Z,DOWRT+OFFSET
  444.     CP    WRITEDEL
  445.     JP    Z,DOWRTDEL+OFFSET
  446.     CP    VERIFY
  447.     JP    DOVERIFY+OFFSET
  448. ;
  449. DOREAD: EXX
  450.     SETUP
  451.     ADD    A,88H    ;1797 Read command
  452.     OUT    DCOMMAND,A
  453. J13:    IN    A,DFLAGS
  454.     RRA
  455.     JR    C,J12 ;INTREQ = error or read complete
  456.     INI
  457.     JP    NZ,J13+OFFSET ;Fetch next data byte
  458. ; Z set when B=0, ie 128 bytes have been read
  459. J12:    DERROR    9DH
  460.     CHECK
  461. ;
  462. DOVERIFY: EXX    ;Similar to DOREAD
  463.     SETUP
  464.     ADD    88H    ;1797 compatible
  465.     OUT    DCOMMAND,A
  466. J14:    IN    A,DFLAGS
  467.     RRA
  468.     JR    C,J15
  469.     IN A,(C)    ;Discard input data
  470.     JP    J14+OFFSET
  471. J15:    DERROR    9DH
  472.     CHECK
  473. ;
  474. DOWRT:    EXX    ;Similar to read in structure
  475.     SETUP
  476.     ADD    A,0A8H    ;1797 compatible
  477.     OUT    DCOMMAND,A
  478. J16:    IN    A,DFLAGS
  479.     RRA
  480.     JR    C,J17
  481.     OUTI
  482.     JP    NZ,J16+OFFSET
  483. J17:    DERROR 0FDH
  484.     CHECK
  485. ;
  486. DOWRTDEL: EXX
  487.     SETUP
  488.     ADD    A,0A9H    ;1797 compatible
  489.     OUT    DCOMMAND,A
  490. J20:    IN    A,DFLAGS
  491.     RRA
  492.     JR    C,J19
  493.     OUTI
  494.     JP    NZ,J20+OFFSET
  495. J19:    DERROR    0FDH
  496.     CHECK
  497. ;
  498. ; Address and Channel error routines
  499. ;
  500. ;THIS ENTRY IS VALID DURING ERROR TRAPS
  501. A1:    LD    A,08H
  502.     OUT    RESULT,A
  503.     JP    STAT+OFFSET
  504. ;
  505. ; 1793 Error exit routines
  506. ;
  507. ; Will print out error messages for ease of debugging
  508. ; Will use the RST7,RST6 area of RAM for stack
  509. ;
  510. EXIT:    EXX
  511.     LD    SP,0038H ; Out of ISIS area
  512.     PUSH    AF
  513.     CALL    PMSGFOLLOWING+OFFSET
  514.     DB    0DH,'1793',0A0H
  515.     POP    AF
  516.     PUSH    AF
  517.     CALL    P2HEX+OFFSET
  518.     CALL    PRINTIOPB+OFFSET
  519.     POP    AF
  520.     LD    B,0    ;Use B to hold result byte
  521.     BIT    0,A
  522.     JR    Z,J5
  523.     SET    0,B
  524.     SET    7,B
  525. J5    BIT    1,A    ;DRQ error
  526.     JR    Z,J6
  527.     SET    4,B
  528. J6:    BIT    2,A    ;Lost data
  529.     JR    Z,J7
  530.     SET    4,B
  531. J7:    BIT    3,A    ;CRC
  532.     JR    Z,J8
  533.     SET    1,B
  534. J8:    BIT    4,A    ;Seek error
  535.     JR    Z,J9
  536.     SET    2,B
  537. J9:    BIT    6,A
  538.     JR    Z,FINISH
  539.     SET    5,B
  540. FINISH:    LD    A,B
  541.     OUT    RESULT,A
  542. ; The following code has been nulled as it
  543. ; causes the motors to 'cycle' in speed too much.
  544. ; A delayed turnoff is needed
  545. ; Switch off the drive motors
  546. ;    LD    A,D
  547. ;    AND    5FH    ;motors + wait off
  548. ;    OUT    DCONTROL,A
  549. STAT:    DONE
  550. ;
  551. ; OUTPUT MESSAGE ROUTINES
  552. PRINTIOPB: CALL    PMSGFOLLOWING+OFFSET
  553.     DB    ' ERROR, IOPB A',0D4H
  554.     PUSH    IX
  555.     POP    HL
  556.     CALL    SPACE+OFFSET
  557.     CALL    PMSGFOLLOWING+OFFSET
  558.     DB    ', CONTENTS:',0A0H
  559.     LD    A,(IX+0)
  560.     CALL    P2HEX+OFFSET
  561.     LD    A,(IX+1)
  562.     CALL    P2HEX+OFFSET
  563.     LD    A,(IX+2)
  564.     CALL    P2HEX+OFFSET
  565.     LD    A,(IX+3)
  566.     CALL    P2HEX+OFFSET
  567.     LD    A,(IX+4)
  568.     CALL    P2HEX+OFFSET
  569.     LD    L,(IX+6) ;Print in reverse order
  570.     LD    H,(IX+5)
  571.     CALL    SPACE+OFFSET
  572.     CALL    PMSGFOLLOWING+OFFSET
  573.     DB    0DH,8AH
  574.     RET
  575. ADDERROR: LD    SP,0038H ;Not in ISIS area
  576.     CALL    PMSGFOLLOWING+OFFSET
  577.     DB    0DH,'ADDRESS',0A0H
  578.     CALL    PRINTIOPB+OFFSET
  579.     JP    A1+OFFSET
  580. CHERROR: LD    SP,0038H
  581.     CALL    PMSGFOLLOWING+OFFSET
  582.     DB    0DH,'CHANNEL',0A0H
  583.     CALL    PRINTIOPB+OFFSET
  584.     JP    A1+OFFSET
  585. PMSG:    PUSH    AF
  586. PS1:    LD    A,(HL)
  587.     INC    HL
  588.     CALL    PCHR+OFFSET
  589.     RLA
  590.     JR    NC,PS1
  591.     POP    AF
  592.     RET
  593. PMSGFOLLOWING:
  594.     EX    (SP),HL
  595.     CALL    PMSG+OFFSET
  596.     EX    (SP),HL
  597.     RET
  598. PCHR:    PUSH    AF
  599. ;SJ2:    IN    A,0F7H    ;CRT STATUS
  600. ;    AND     1
  601. ;    JR    Z,SJ2
  602. ;    POP    AF
  603. ;    PUSH    AF
  604. ;    OUT    0F6H,A    ;CRT DATA
  605. SJ1:    IN    A,0FBH    ;PRINTER STATUS
  606.     AND    1
  607.     JR    Z,SJ1
  608.     POP    AF
  609.     OUT    0FBH,A    ;PRINT DATA
  610.     RET
  611. SPACE:    LD    A,20H
  612.     CALL    PCHR+OFFSET
  613.     LD    A,H
  614.     CALL    P2HEX+OFFSET
  615.     LD    A,L
  616. P2HEX: PUSH    AF
  617.     LD    A,20H
  618.     CALL    PCHR+OFFSET
  619.     POP    AF
  620.      CALL    P1HEX+OFFSET
  621.     RRA
  622. P1HEX:    RRA
  623.     RRA
  624.     RRA
  625.     RRA
  626.     PUSH    AF
  627.     AND    0FH
  628.     CP    10
  629.     JR    C,PH1
  630.     ADD    7
  631. PH1:    ADD    30H
  632.     CALL    PCHR+OFFSET
  633.     POP    AF
  634.     RET
  635.     END    START
  636.