home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / trs80model4 / m4h191.asm < prev    next >
Assembly Source File  |  1986-10-21  |  15KB  |  584 lines

  1. ;        M4H191/ASM
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;
  4. ;        Heath 19 terminal emulation filter
  5. ;
  6. ;            Written By:  Gregg Wonderly
  7. ;
  8. ;    This program functions as a TRSDOS 6.2 device filter to emulate
  9. ;    the h19 terminal.  It recognizes most of the features of the
  10. ;    H19 that are reasonable to implement on the Model 4.  The items
  11. ;    missing are ALT character set, and some of the <ESC>[xy]n
  12. ;    sequences.
  13. ;
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15. ;
  16. ;    This filter relocates itself to HIGH memory.
  17. ;
  18. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  19. ;
  20.         ORG    3000H
  21. TAB        EQU    9        ;Tab character code
  22. ESC        EQU    27        ;Tab character code
  23. S_OUT        EQU    1        ;Screen on mask
  24. S_IN        EQU    0FEH        ;Screen off mask
  25. R_ON        EQU    8        ;Reverse video on mask
  26. R_OFF        EQU    0F7H        ;Reverse video off mask
  27. FLAGVAL        EQU    17        ;Flags offset from MODDCB
  28. SCR_MASK    EQU    14        ;Offset of screen mask in flags
  29. WRINTMASK    EQU    22        ;Interrupts mask in FLAGS
  30. BITOFFSET    EQU    29
  31. ;
  32. *GET        M4H19/EQU        ;Get the SVC equates
  33. *GET        M4H19/MAC        ;Get the macros
  34. ;
  35. ;        The system enters the driver here with each character
  36. ;
  37. FILTER        JR    H19EMULATOR    ;Go to the start of the driver
  38.         DW     0        ;End of module address goes here
  39.         DB    6        ;Length of the module name
  40.         DB    '$HEATH'    ;The name
  41. MODDCB        DW    0        ;To be filled in later
  42.         DW    0        ;Filler
  43. VSCUR        DB    95        ;Block cursor character
  44. VECUR        DB    95        ;Underscore cursor character
  45. DEF_LEN        DB    20        ;Default duration for the bell
  46. BELLFLAG    DB    0        ;Visual or audible bell
  47. DEF_FREQ    DW    125        ;Default frequency for bell tone
  48. OLDLOW        DW    0        ;The address to restore if we
  49. ;                        remove ourselves
  50. OLDHIGH        DW    0        ;This is where we are loaded at
  51. WHERE_AT    DB    0        ;Flag for high or low mem load
  52. OFFSET        DW    0        ;Offset from load to destination
  53. FVAL        DB    0        ;No flags to start with
  54. BITVAL        DW    BITMASK        ;Offset to 7-bit mask
  55. ;
  56. ;    Start of actual Filter
  57. ;
  58. H19EMULATOR    JR    Z,ISPUT        ;Go to process @PUT requests
  59.         JP    CHAIN_2        ;Ignore other options
  60. R002        EQU    $-2
  61. ;
  62. ;    Do only @PUT requests
  63. ;
  64. ISPUT        EQU    $
  65.         LD    A,@FLAGS    ;Get the flags address into IY
  66.         RST    28H
  67.         LD    A,C        ;Character is in A and C now
  68.         AND    07FH        ;Strip any 8th bit if STRIP8 set
  69. BITMASK        EQU    $-FILTER-1
  70.         LD    C,A
  71.         LD    (NEWCHAR),A    ;Save the character to display
  72. R003        EQU    $-2
  73.         LD    HL,(OLDSTATE)    ;Get any preexisting state
  74. R004        EQU    $-2
  75.         LD    A,H        ;Check for on, NZ means yes
  76.         OR    L
  77.         JR    Z,NOSTATE    ;Go if no state
  78.         PUSH    HL        ;Put the address on the stack
  79.         LD    HL,0        ;Wipe out the state value
  80.         LD    (OLDSTATE),HL    ;by storing zero in it
  81. R005        EQU    $-2
  82.         RET            ;Go to the address on the stack
  83. ;
  84. ;    Look for what we should do with the character...
  85. ;
  86. NOSTATE        LD    A,C        ;Get the character
  87.         CP    ESC        ;Is it the escape character?
  88.         JP    Z,DOESCAPE    ;Go do it if so
  89. R006        EQU    $-2
  90.         CP    ' '        ;Check for a Control Character
  91.         JP    C,DOCONTROL    ;Go do it if so
  92. R007        EQU    $-2
  93.         CALL    INSERT_A    ;Put the character on the screen
  94. R008        EQU    $-2
  95.         JP    RETOUT        ;Return to caller
  96. R009        EQU    $-2
  97. ;
  98. ;    Process all of the control characters between 0-31 inclusive
  99. ;
  100. DOCONTROL    EQU    $
  101.         LD    A,(NEWCHAR)    ;Get the character
  102. R010        EQU    $-2
  103.         ADD    A,A        ;Times 2 for word offset
  104.         LD    C,A        ;Get a copy of A for the offset
  105.         LD    B,0        ;Make BC a 16 bit offset
  106.         LD    HL,CTL_JMP_TBL    ;Get the jump table
  107. R011        EQU    $-2
  108.         ADD    HL,BC        ;Get the address in the table
  109.         LD    E,(HL)        ;Get LSB of the address
  110.         INC    HL        ;Point at next byte of address
  111.         LD    D,(HL)        ;Get the MSB
  112.         EX    DE,HL        ;Swap the jump address into HL
  113.         LD    A,H        ;Is there a special routine?
  114.         OR    L        ;Set the flags
  115.         LD    A,(NEWCHAR)    ;Get the character back
  116. R012        EQU    $-2
  117.         JP    Z,RETOUT    ;If not recognized, throw it out.
  118. R013        EQU    $-2
  119.         JP    (HL)        ;Go to the special routine
  120. ;
  121. ;    Control character jump table.  Each word is the address of a
  122. ;    routine that processes the specfic character.
  123. ;
  124. CTL_JMP_TBL    DW    0,0,0,0,0,0,0    ;Throw these out.
  125.         DW    SET_BELL    ;Start the buzzer.
  126. R014        EQU    $-2
  127.         DW    BACK_SPACE    ;Backup a character NON-destruct.
  128. R015        EQU    $-2
  129.         DW    SHOW_TAB    ;Skip a physical tab.
  130. R016        EQU    $-2
  131.         DW    LINE_FEED    ;Down one line.
  132. R017        EQU    $-2
  133.         DW    0        ;Throw this one out.
  134.         DW    FORM_FEED    ;Clear the screen on FF.
  135. R018        EQU    $-2
  136.         DW    CARRIAGE    ;Carriage return.
  137. R019        EQU    $-2
  138.         DW    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    ;Not used.
  139. ;
  140. SET_BELL    LD    A,(BELLFLAG)    ;Is the bell function valid?
  141. R020        EQU    $-2
  142.         OR    A
  143.         JP    Z,FLASH_SCREEN    ;Flash if signaled
  144. R021        EQU    $-2
  145.         LD    A,(DEF_LEN)    ;This is the timer value.
  146. R022        EQU    $-2
  147.         LD    L,A
  148.         LD    DE,(DEF_FREQ)
  149. R023        EQU    $-2
  150. BELL01        EQU    $
  151.         LD    A,1
  152.         OUT    (90H),A
  153.         LD    B,D
  154.         LD    C,E
  155. BELL02        EQU    $
  156.         DEC    BC
  157.         LD    A,B
  158.         OR    C
  159.         JR    NZ,BELL02
  160.         XOR    A
  161.         OUT    (90H),A
  162.         LD    B,D
  163.         LD    C,E
  164. BELL03        EQU    $
  165.         DEC    BC
  166.         LD    A,B
  167.         OR    C
  168.         JR    NZ,BELL03
  169.         DEC    L
  170.         JR    NZ,BELL01
  171.         JP    RETOUT        ;Exit without chaining
  172. R024        EQU    $-2
  173. ;
  174. BACK_SPACE    EQU    $
  175.         LD    A,24        ;Non-destructive backspace
  176.         JP    STORE_CHAIN    ;Chain into any filters
  177. R025        EQU    $-2
  178. ;
  179. SHOW_TAB    EQU    $
  180.         GET_CURSOR        ;Get the cursor position
  181.         LD    A,79        ;Last column to display in
  182.         SUB    L        ;Compute the difference
  183.         CP    8        ;Do we have enough?
  184.         JP    NC,TABOK    ;If at least 8 then go do it
  185. R026        EQU    $-2
  186.         LD    A,29        ;Send simulated <CR><LF> to *DO
  187.         CALL    CHAIN_IN
  188. R028        EQU    $-2
  189.         LD    A,26
  190.         JP    CHAIN_IN    ;No return
  191. R029        EQU    $-2
  192. TABOK        EQU    $
  193.         LD    A,L        ;Must truncate to even 8 chars
  194.         ADD    A,8
  195.         AND    0F8H
  196.         LD    L,A        ;Get the column back into L
  197. NOSCROLL    EQU    $
  198.         PUT_CURSOR        ;Set the cursor to what is in HL
  199.         JP    RETOUT        ;Return
  200. R030        EQU    $-2
  201. ;
  202. LINE_FEED    EQU    $
  203.         LD    A,26        ;Non-destructive LF
  204.         CALL    STORE_CHAIN    ;Chain into any filters
  205. R031        EQU    $-2
  206.         LD    A,(FVAL)
  207. R131        EQU    $-2
  208.         AND    2        ;Check for auto CR
  209.         LD    A,29        ;Get a CR
  210.         CALL    NZ,STORE_CHAIN
  211. R177        EQU    $-2
  212.         JP    RETOUT        ;Return
  213. R178        EQU    $-2
  214. ;
  215. FORM_FEED    EQU    $
  216.         LD    HL,0        ;Set the cursor to 0,0
  217.         PUT_CURSOR
  218.         JP    CLEAR_TO_EOS    ;Do a clear to end of screen
  219. R032        EQU    $-2
  220. ;
  221. MOVE_HOME    EQU    $
  222.         LD    HL,0        ;Get Row=0, Column=0
  223. STORE_ROW_COL    EQU    $
  224.         PUT_CURSOR        ;Move the cursor to the pos in HL
  225.         JP    RETOUT        ;Return
  226. R033        EQU    $-2
  227. ;
  228. CARRIAGE    EQU    $
  229.         LD    A,29        ;True carriage return
  230.         CALL    STORE_CHAIN
  231. R034        EQU    $-2
  232.         LD    A,(FVAL)
  233. R174        EQU    $-2
  234.         AND    1
  235.         LD    A,26        ;Get a line_feed
  236.         CALL    NZ,STORE_CHAIN    ;Display it conditionally
  237. R175        EQU    $-2
  238.         JP    RETOUT
  239. R176        EQU    $-2
  240. ;
  241. ;    Process the ESCAPE character sequences
  242. ;
  243. DOESCAPE    EQU    $
  244.         LD    HL,ESCAPE_1    ;Set the next state to go to
  245. R035        EQU    $-2
  246.         LD    (OLDSTATE),HL
  247. R036        EQU    $-2
  248.         JP    RETOUT        ;Leave with no chain
  249. R037        EQU    $-2
  250. ;
  251. ;    Escape has been seen, now check for a special character
  252. ;
  253. ESCAPE_CHARS    DB    'ABCDEFGHIJKLMNOY@fqpxyjkbol'
  254. ESC_LEN        EQU    $-ESCAPE_CHARS
  255. ;
  256. ESCAPE_1    EQU    $
  257.         LD    A,(NEWCHAR)    ;Get the character sent
  258. R038        EQU    $-2
  259.         LD    HL,ESCAPE_CHARS    ;Get the list of valid ones
  260. R039        EQU    $-2
  261.         LD    B,ESC_LEN    ;Get how many
  262.         LD    DE,ESC_1_JMPS    ;Get the vector table
  263. R040        EQU    $-2
  264. ESC_1_LOOP    LD    C,(HL)        ;Get a character
  265.         CP    C        ;Is it a match?
  266.         JR    Z,ESC_1_FND    ;Found it, so go
  267.         INC    HL        ;Next character
  268.         INC    DE        ;next jump table entry
  269.         INC    DE
  270.         DJNZ    ESC_1_LOOP    ;Loop while still more
  271.         LD    HL,0
  272.         LD    (OLDSTATE),HL
  273. R041        EQU    $-2
  274.         JP    RETOUT        ;Ignore unimplemented or invalid codes
  275. R042        EQU    $-2
  276. ;
  277. ESC_1_FND    EQU    $
  278.         EX    DE,HL        ;Get the vector's address
  279.         LD    E,(HL)        ;Get the table value
  280.         INC    HL
  281.         LD    D,(HL)
  282.         LD    HL,0        ;Reset the state
  283.         LD    (OLDSTATE),HL
  284. R043        EQU    $-2
  285.         EX    DE,HL        ;Get the vector in HL
  286.         LD    A,(NEWCHAR)
  287. R044        EQU    $-2
  288.         JP    (HL)        ;Go do the right thing.
  289. ;
  290. ;    Level 1 escape vector table
  291. ;
  292. ESC_1_JMPS    DW    CURSOR_UP
  293. R045        EQU    $-2
  294.         DW    LINE_FEED
  295. R046        EQU    $-2
  296.         DW    CURSOR_RIGHT
  297. R047        EQU    $-2
  298.         DW    BACK_SPACE
  299. R048        EQU    $-2
  300.         DW    FORM_FEED
  301. R049        EQU    $-2
  302.         DW    START_ALT_SET
  303. R050        EQU    $-2
  304.         DW    END_ALT_SET
  305. R051        EQU    $-2
  306.         DW    MOVE_HOME
  307. R052        EQU    $-2
  308.         DW    REV_INDEX
  309. R053        EQU    $-2
  310.         DW    CLEAR_TO_EOS
  311. R054        EQU    $-2
  312.         DW    CLEAR_TO_EOL
  313. R055        EQU    $-2
  314.         DW    ADD_LINE
  315. R056        EQU    $-2
  316.         DW    DEL_LINE
  317. R057        EQU    $-2
  318.         DW    DEL_CHAR
  319. R058        EQU    $-2
  320.         DW    END_INSERT
  321. R059        EQU    $-2
  322.         DW    SET_ESC_2
  323. R060        EQU    $-2
  324.         DW    BEGIN_INSERT
  325. R061        EQU    $-2
  326.         DW    FLASH_SCREEN
  327. R062        EQU    $-2
  328.         DW    STAND_END
  329. R063        EQU    $-2
  330.         DW    STAND_OUT
  331. R064        EQU    $-2
  332.         DW    SET_ESC_2
  333. R065        EQU    $-2
  334.         DW    SET_ESC_2
  335. R066        EQU    $-2
  336.         DW    SAVE_CURSOR
  337. R001        EQU    $-2
  338.         DW    RESTORE_CURSOR
  339. R027        EQU    $-2
  340.         DW    ERA_BEG_SCR
  341. R141        EQU    $-2
  342.         DW    ERA_BEG_LIN
  343. R142        EQU    $-2
  344.         DW    ERASE_LINE
  345. R143        EQU    $-2
  346. ;
  347. ;    Move the cursor up one line if possible, stopping at the top
  348. ;    of the screen.
  349. ;
  350. CURSOR_UP    EQU    $
  351.         LD    A,27        ;Non-destructive cursor up
  352. STORE_CHAIN    EQU    $
  353.         LD    (NEWCHAR),A    ;Store it
  354. R067        EQU    $-2
  355.         JP    CHAIN        ;Let *DO do the dirty work
  356. R068        EQU    $-2
  357. ;
  358. CURSOR_RIGHT    EQU    $
  359.         LD    A,25        ;Non-destructive cursor right
  360.         JP    STORE_CHAIN    ;Let *DO do it for us
  361. R069        EQU    $-2
  362. ;
  363. START_ALT_SET    JP    RETOUT        ;No defined action
  364. R070        EQU    $-2
  365. ;
  366. END_ALT_SET    JP    RETOUT        ;No defined action
  367. R071        EQU    $-2
  368. ;
  369. ;    This is the reverse scroll.  We use direct screen access to
  370. ;    move one line.  Interrupts are off during the move, but are
  371. ;    restored between each line.  There seems to be quite reasonable
  372. ;    behavior at 9600 baud with this strategy.
  373. ;
  374. REV_INDEX    EQU    $
  375.         GET_CURSOR        ;Make sure we are at the top
  376.         LD    A,H        ;Get the cursor row
  377.         OR    A        ;Is it row zero?
  378.         JP    NZ,CURSOR_UP    ;Go if not, to Cursor up routine
  379. R072        EQU    $-2
  380.         LD    A,15        ;Remove the cursor
  381.         CALL    CHAIN_IN
  382. R127        EQU    $-2
  383.         LD    A,23        ;Move 23 lines down
  384.         LD    HL,23*80+0F7FFH    ;Get the next to last line, last byte
  385.         LD    DE,24*80+0F7FFH    ;Get the last byte on the screen
  386. REV_LOOP    LD    BC,80        ;Get the byte count
  387.         PUSH    AF        ;Save the line count
  388.         SWAP_IN            ;Screen in, interrupts off
  389.         LDDR            ;Move a line
  390.         SWAP_OUT        ;Screen out, interrupts on
  391.         POP    AF        ;Get line count
  392.         DEC    A        ;One less to move
  393.         JR    NZ,REV_LOOP    ;Loop if not done
  394. REV_DONE    EQU    $
  395.         LD    DE,SCR_BUFF    ;Get the buffer address
  396. R073        EQU    $-2
  397.         PUSH    DE        ;Save it
  398.         PUSH    DE        ;Copy it into HL
  399.         POP    HL
  400.         INC    DE        ;Point one ahead for the copy
  401.         LD    (HL),' '    ;Store one blank
  402.         LD    BC,79        ;Copy it into the remaining 79
  403.         LDIR            ;Do the copy
  404.         LD    H,0        ;Get the top row
  405.         POP    DE        ;Get the buffer address back
  406.         PUT_LINE        ;Put a blank line there
  407.         LD    A,14        ;Turn the cursor back on
  408.         JP    CHAIN_IN
  409. R074        EQU    $-2
  410. ;
  411. ;    Flash the screen, by inverting all of the msb's of the characters
  412. ;    twice.  The result is a fair approximation to a flash.
  413. ;
  414. FLASH_SCREEN    EQU    $
  415.         LD    A,16        ;Turn reverse video on
  416.         CALL    CHAIN_IN
  417. R128        EQU    $-2
  418.         LD    C,0        ;Get the loop counter
  419. FLASH_LOOP_1    EQU    $
  420.         PUSH    BC        ;Save it
  421.         LD    H,0        ;Get the first line
  422. FLASH_LOOP_2    EQU    $
  423.         LD    DE,SCR_BUFF    ;Get the buffer to put it in
  424. R075        EQU    $-2
  425.         GET_LINE        ;Get the line from @VDCTL
  426.         PUSH    HL        ;Save the line number for PUT_LINE
  427.         LD    H,D        ;Copy DE into HL
  428.         LD    L,E
  429.         LD    B,80        ;Get the BYTE count
  430. FLASH_LOOP_3    EQU    $
  431.         LD    A,(HL)        ;Get a BYTE
  432.         XOR    080H        ;Invert the HIGH BIT
  433.         LD    (HL),A        ;Put it back
  434.         INC    HL        ;Point to the next
  435.         DJNZ    FLASH_LOOP_3    ;Loop until line is done
  436.         POP    HL        ;Restore the Line number
  437.         PUT_LINE        ;Put the line back
  438.         INC    H        ;Point to next line
  439.         LD    A,H        ;Test for last
  440.         CP    24        ;END?
  441.         JR    NZ,FLASH_LOOP_2    ;Loop if not done
  442.         EI            ;Make sure interrupts are back on
  443.         POP    BC        ;Restore the FLASH counter
  444.         LD    A,C        ;Get the original value
  445.         INC    C        ;Increment the counter
  446.         OR    A        ;Test OLD value
  447.         JR    Z,FLASH_LOOP_1    ;Loop if just finished first time
  448.         LD    A,17        ;Set reverse video OFF
  449.         JP    STORE_CHAIN    ;Chain to *DO
  450. R076        EQU    $-2
  451. ;
  452. ;    Save the current cursor position
  453. ;
  454. SAVE_CURSOR    EQU    $
  455.         LD    DE,(LASTPUSH)    ;Get the nextplace available
  456. R132        EQU    $-2
  457.         GET_CURSOR        ;Get the cursor
  458.         EX    DE,HL        ;Swap push address for screen pos
  459.         PUSH    HL        ;Save push address
  460.         LD    BC,ENDPUSH    ;Get the first illeagal address
  461. R133        EQU    $-2
  462.         OR    A        ;Reset the carry
  463.         SBC    HL,BC        ;Compute difference
  464.         POP    HL        ;Restore real address
  465.         JR    Z,NO_SAVE    ;Jump if can't save
  466.         LD    (HL),E        ;Put in column
  467.         INC    HL        ;Point to next pos
  468.         LD    (HL),D        ;Put in the row
  469.         INC    HL        ;Point past it to next position
  470.         LD    (LASTPUSH),HL    ;Save the new address
  471. R134        EQU    $-2
  472. NO_SAVE        EQU    $
  473.         JP    RETOUT
  474. R135        EQU    $-2
  475. ;
  476. ;    Restore the previously pushed cursor position.
  477. ;
  478. RESTORE_CURSOR    EQU    $
  479.         LD    HL,(LASTPUSH)    ;Get the next store position
  480. R136        EQU    $-2
  481.         LD    BC,PUSHAREA    ;Get the start of the area
  482. R137        EQU    $-2
  483.         OR    A        ;Reset carry
  484.         PUSH    HL        ;Save the address
  485.         SBC    HL,BC        ;See if anything to pop
  486.         POP    HL
  487.         JR    Z,NO_RESTORE    ;Jump if not
  488.         DEC    HL        ;Point back to row
  489.         LD    D,(HL)        ;Get it
  490.         DEC    HL        ;Point back to column
  491.         LD    E,(HL)        ;Get it
  492.         LD    (LASTPUSH),HL    ;Save the next position
  493. R138        EQU    $-2
  494.         EX    DE,HL        ;Put the Row/Column into HL
  495.         PUT_CURSOR        ;Set the cursor position
  496. NO_RESTORE    EQU    $
  497.         JP    RETOUT        ;Return without calling *DO
  498. R139        EQU    $-2
  499. ;
  500. ;    Erase the current line
  501. ;
  502. ERASE_LINE    EQU    $
  503.         GET_CURSOR        ;Get the current position
  504.         PUSH    HL        ;Save it
  505.         LD    L,0        ;Move to beginning of line
  506.         PUT_CURSOR        ;Store the new cursor position
  507.         CALL    CLEAR_TO_EOL
  508. R144        EQU    $-2
  509.         POP    HL
  510.         PUT_CURSOR
  511.         JP    RETOUT
  512. R145        EQU    $-2
  513. ;
  514. ;    Erase to beginning of screen
  515. ;
  516. ERA_BEG_SCR    EQU    $
  517.         GET_CURSOR        ;Get the current screen position
  518.         CALL    GET_RC_ADDR    ;Convert it to a memory address
  519. R146        EQU    $-2
  520.         LD    DE,0F800H    ;Get the start of the screen
  521.         OR    A        ;Reset the carry
  522.         SBC    HL,DE        ;Compute number to blank
  523.         LD    B,H        ;Put the count into BC
  524.         LD    C,L
  525.         LD    A,B        ;See if at start of screen
  526.         OR    C
  527.         JR    Z,NO_ERA_SCR    ;Jump if so, nothing to erase
  528.         LD    HL,0F800H    ;Get the start
  529.         LD    DE,0F801H    ;Get the start + 1
  530.         SWAP_IN            ;Make the screen visible
  531.         LD    (HL),20H    ;Blank one position
  532.         SWAP_OUT        ;Swap the screen back out
  533.         DEC    BC        ;Decrement remaining places
  534.         LD    A,B        ;See if only one needed blanking
  535.         OR    C
  536.         JR    Z,NO_ERA_SCR    ;Jump it that was all
  537.         SWAP_IN            ;Swap the screen back in
  538.         LDIR            ;Blank the characters
  539.         SWAP_OUT        ;Swap the screen back out
  540. NO_ERA_SCR    EQU    $
  541.         JP    RETOUT        ;Return without chaining
  542. R147        EQU    $-2
  543. ;
  544. ;    Clear to the beginning of the line
  545. ;
  546. ERA_BEG_LIN    EQU    $
  547.         GET_CURSOR        ;Get current position
  548.         PUSH    HL        ;Save it
  549.         CALL    GET_RC_ADDR    ;Convert to memory address
  550. R148        EQU    $-2
  551.         EX    DE,HL        ;Swap current to DE
  552.         POP    HL        ;Get the row/column back
  553.         LD    L,0        ;Set row to start of screen
  554.         CALL    GET_RC_ADDR    ;Get the address there
  555. R149        EQU    $-2
  556.         EX    DE,HL        ;Swap it back
  557.         OR    A        ;Reset the carry
  558.         PUSH    DE        ;Save starting address
  559.         SBC    HL,DE        ;Compute length
  560.         LD    B,H        ;Put it into BC
  561.         LD    C,L
  562.         LD    A,B        ;Check if no characters
  563.         OR    C
  564.         JR    Z,NO_ERA_LIN    ;Jump if at start of line
  565.         POP    HL        ;Get start of line address back
  566.         LD    D,H        ;Make DE=HL+1
  567.         LD    E,L
  568.         INC    DE
  569.         SWAP_IN            ;Swap the screen in
  570.         LD    (HL),20H    ;Store a space
  571.         SWAP_OUT        ;Swap the screen out
  572.         DEC    BC        ;Decrement the count for prev inst
  573.         LD    A,B        ;Check for zero
  574.         OR    C        ;Set the flags
  575.         JR    Z,NO_ERA_LIN
  576.         SWAP_IN            ;Fold the screen into memory
  577.         LDIR            ;Blank the screen
  578.         SWAP_OUT        ;Swap the screen back out
  579. NO_ERA_LIN    EQU    $
  580.         JP    RETOUT        ;Return to caller
  581. R150        EQU    $-2
  582. *GET        M4H192/ASM
  583.         END    LOAD
  584.