;CP/M Disk Sector Editor ;For my 8080 Computer ; ;Version 1.0 ;08-19-2024 ;Jerry Davis ; CPU 8080 ;Specify architecture PAGE 0 ;Turn off page breaks in listings ; ; ;CP/M Return Vector ; ccp equ 0df00h ; ; ;CPM Current Drive cdrive equ 4 ; ; ;BIOS Routines ; wboot equ 0f503h ;warm start const equ 0f506h ;console status conin equ 0f509h ;console character in conout equ 0f50ch ;console character out seldsk equ 0f51bh ;select disk settrk equ 0f51eh ;set track number setsec equ 0f521h ;set sector number setdma equ 0f524h ;set dma address read equ 0f527h ;read disk write equ 0f52ah ;write disk ; ; ;BIOS Write Types wrall equ 0 ;write to allocated wrdir equ 1 ;write to directory wrual equ 2 ;write to unallocated ; ; org 0100h ; ; start: lda cdrive ;Start with the current drive sta current_drive ;Save it in current drive mvi a, 0h ;Start with default values sta current_track ;Save it in current track sta current_sector ;Save it in current sector sta current_emode ;Save it in current edit mode lxi b, secbuf ;Get sector buffer address call setdma ;Set for sector buffer address call hide_cursor ;Hide the cursor until needed call linewrap_off ;Turn off auto line wrap call header_top ;Print top app header lines call print_nl ;New line ; ; navmode: call hide_cursor ;Hide the cursor until needed call print_navmode ;Print nav mode controls call print_navfun ;Print navigation function controls call print_navsubfun ;Print navigation sub-function controls jmp nav_exec ;Get initial sector, display, and parse keys until exit navkeys: call flush_console ;Start with clean console call conin ;Get a key from the keyboard cpi 1bh ;Is it ESC? jnz navkeys_norm ;If not, parse regular character call conin ;Get rest of escape sequence cpi '[' ;Is it '['? jnz navkeys ;If not, do input over again call conin ;Get last sequence character cpi 'A' ;Nav key UP? jz nav_nextsec ;Do next sector cpi 'B' ;Nav key DN? jz nav_prevsec ;Do previous sector cpi 'C' ;Nav key RT? jz nav_nexttrk ;Do next track cpi 'D' ;Nav key LF? jz nav_prevtrk ;Do previous track cpi '1' ;Nav key HOM? jz nav_firstsec ;Do first sector/track cpi '4' ;Nav key END? jz nav_lastsec ;Do last sector/track jmp navkeys ;Start again navkeys_norm: cpi 5h ;Enter edit mode? jz editmode ;Do edit mode cpi 18h ;Exit to CPM? jz nav_exit ;Do it ani 0dfh ;Make upper case cpi 'D' ;Change Disk? jz nav_chgdsk ;Do it cpi 'T' ;Change Track? jz nav_chgtrk ;Do it cpi 'S' ;Change Sector? jz nav_chgsec ;Do it cpi 'B' ;Change Sector? jz nav_chgblk ;Do it jmp navkeys nav_nextsec: lda current_sector ;Get current sector cpi 0ffh ;Last sector? jz navkeys ;no action inr a ;Point to next sector sta current_sector ;Save it jmp nav_exec ;Execute key nav_prevsec: lda current_sector ;Get current sector cpi 0h ;First sector? jz navkeys ;no action dcr a ;Point to next sector sta current_sector ;Save it jmp nav_exec ;Execute key nav_nexttrk: lda current_track ;Get current track cpi 0ffh ;Last track? jz navkeys ;no action inr a ;Point to next track sta current_track ;Save it jmp nav_exec ;Execute key nav_prevtrk: lda current_track ;Get current track cpi 0h ;First track? jz navkeys ;no action dcr a ;Point to next track sta current_track ;Save it jmp nav_exec ;Execute key nav_firstsec: mvi a, 0h ;Start with zero sta current_track ;Save the track sta current_sector ;Save the sector jmp nav_exec ;Execute key nav_lastsec: mvi a, 0ffh ;Start with FF sta current_track ;Save the track sta current_sector ;Save the sector jmp nav_exec ;Execute key nav_exec: call print_params ;Update param display lda current_track ;Get current track mov c, a ;Put it in C call settrk ;Set for track 0 lda current_sector ;Get current track mov c, a ;Put it in C call setsec ;Set for track 0 call read ;Get sector call print_buffer ;Print sector jmp navkeys ;Get next command from console nav_chgdsk: lxi d, 0307h ;Move to disk field call move_cursor ;Move the cursor call show_cursor ;Show the cursor call set_intense ;Set to bright video call conin ;Get one character ani 0dfh ;Make upper case sui 'A' ;Change to drive number mov c, a ;Put drive number in C call seldsk ;Select the disk mov a, h ;valid drive? ora l ;valid drive? jz nav_chgdsk01 ;Invalid. Just do parameters. mov a, c ;Put drive number in A sta current_drive ;Save drive number call hide_cursor ;Hide the cursor call print_params ;Print parameters jmp nav_exec ;Get disk sector nav_chgdsk01: call hide_cursor ;Hide the cursor call print_params ;Print parameters jmp navkeys ;Get next command from console nav_chgtrk: lxi d, 0317h ;Move to track field call move_cursor ;Move the cursor call show_cursor ;Show the cursor call set_intense ;Set to bright video call get_hexbyte ;Get hex byte into A sta current_track ;Save it call hide_cursor ;Hide the cursor call print_params ;Print parameters jmp nav_exec ;Get disk sector nav_chgsec: lxi d, 0329h ;Move to sector field call move_cursor ;Move the cursor call show_cursor ;Show the cursor call set_intense ;Set to bright video call get_hexbyte ;Get hex byte into A sta current_sector ;Save it call hide_cursor ;Hide the cursor call print_params ;Print parameters jmp nav_exec ;Get disk sector nav_chgblk: lxi d, 0340h ;Move to block field MSB call move_cursor ;Move the cursor call show_cursor ;Show the cursor call set_intense ;Set to bright video call get_hexbyte ;Get hex byte into A mov h, a ;Save it in B call get_hexbyte ;Get hex byte into A mov l, a ;Save it in C shld current_block ;Save it ani 07h ;Get sector count rrc ;Put lower 3 bits into upper 3 bits rrc ;aka, multiply by 32 rrc sta current_sector ;Save beginning sector number mov a, l ;Get LSB of block ani 0f8h ;Mask off lower 3 bits rrc ;Move upper 5 bits 3 places to the right rrc ;aka divide by 8 rrc mov l, a ;Save it in L mov a, h ;Get MSB of block ani 07h ;Mask off upper 5 bits rrc ;Move lower 3 bits 5 places to the left rrc rrc ora l ;Bring in the lower bits inr a ;Increment it sta current_track ;Save track number call hide_cursor ;Hide the cursor call print_params ;Print parameters jmp nav_exec ;Get first sector of block nav_exit: call clear_screen ;Clean up the screen call show_cursor ;Enable cursor call linewrap_on ;Turn on auto line wrap jmp wboot ;Hand control back CP/M ; ; editmode: call hide_cursor ;Hide the cursor until needed call print_editmode ;Print edit navigation controls call print_editsubfun ;Print edit sub-function controls call edit_statline ;Update the hex/text edit mode lxi h, secbuf ;Point to sector buffer shld current_buf ;Save it lxi h, 0607h ;Top left cursor position shld current_pos ;Save cursor position lxi h, 0658h ;Top left text cursor position shld current_tpos ;Save cursor position xra a ;Hex edit mode sta current_emode ;Save it jmp edit_firstbyte ;Init editor editkeys: call show_cursor ;Show the cursor call flush_console ;Start with clean console lda current_emode ;Get current edit mode ana a ;Is it text mode? jnz editkeys01 ;If so then get text call edit_hex ;Edit byte or get edit navigation gey jmp editkeys02 ;Check input editkeys01: call get_char ;Get text character editkeys02: cpi 0h ;Valid hex or ascii input? jz edit_nextcol ;If so, move to next buffer byte cpi 1bh ;Is it ESC? jnz editkeys_norm ;If not, parse regular character call conin ;Get rest of escape sequence cpi '[' ;Is it '['? jnz editkeys ;If not, do input over again call conin ;Get last sequence character push psw call hide_cursor pop psw cpi 'A' ;Nav key UP? jz edit_prevline ;Do next sector cpi 'B' ;Nav key DN? jz edit_nextline ;Do previous sector cpi 'C' ;Nav key RT? jz edit_nextcol ;Do next track cpi 'D' ;Nav key LF? jz edit_prevcol ;Do previous track cpi '1' ;Nav key HOM? jz edit_firstbyte ;Do first sector/track cpi '4' ;Nav key END? jz edit_lastbyte ;Do last sector/track jmp editkeys ;Start again editkeys_norm: push psw call hide_cursor pop psw cpi 0eh ;Enter navigation mode? jz navmode ;Do edit mode cpi 18h ;Exit to CPM? jz nav_exit ;Do it cpi 13h ;Save sector? jz edit_savesec ;Do it cpi 12h ;Reload sector? jz edit_rldsec ;Do it cpi 09h ;Text mode? jz edit_txtmode ;Do it jmp editkeys edit_nextline: lhld current_pos ;Get current cursor position mvi a, 13h ;Max line position cmp h ;Already at max? jz editkeys ;Get next command from console call edit_clearattr ;Update the sector display lhld current_buf ;Get the buffer pointer lxi d, 10h ;Next 'row' buffer position dad d ;Adjust buffer pointer shld current_buf ;Save buffer pointer lhld current_pos ;Get current hex position mov a, h ;Move line value into A adi 1h ;Increment it daa ;Decimal adjust it mov h, a ;Put it back in line value shld current_pos ;Save cursor position lhld current_tpos ;Get current cursor text position mov h, a ;Put it in text line value shld current_tpos ;Save cursor text position call edit_setattr ;Update the sector hex display jmp editkeys ;Get next command from console edit_prevline: lhld current_pos ;Get current cursor position mvi a, 6h ;Min row position cmp h ;Already at max? jz editkeys ;Get next command from console call edit_clearattr ;Update the sector display lhld current_buf ;Get the buffer pointer lxi d, 0fff0h ;Previous 'row' buffer position dad d ;Adjust buffer pointer shld current_buf ;Save buffer pointer lhld current_pos ;Get current hex position mov b, h ;Move line value into B mvi c, 1h ;But decrement in C call sub_daa ;Decimal subtract mov h, b ;Put it back in line value shld current_pos ;Save cursor position lhld current_tpos ;Get current cursor text position mov h, b ;Put it in text line value shld current_tpos ;Save cursor text position call edit_setattr ;Update the sector hex display jmp editkeys ;Get next command from console edit_nextcol: lhld current_pos ;Get current cursor position mvi a, 54h ;Max col position cmp l ;Already at max? jz edit_wrapleft ;Try wraparound call edit_clearattr ;Update the sector display lhld current_buf ;Get the buffer pointer inx h ;Next 'col' buffer position shld current_buf ;Save buffer pointer lhld current_pos ;Get current hex position mov a, l ;Move col value into A adi 3h ;Increment it daa ;Decimal adjust it cpi 31h ;Center column break? jnz edit_nxcol01 ;Do normal increment adi 2h ;Increment again daa ;Decimal adjust it edit_nxcol01: mov l, a ;Move new col value into L shld current_pos ;Save cursor position lhld current_tpos ;Get current text position mov a, l ;Put test column in A adi 1h ;Increment it daa ;Decimal adjust it mov l, a ;Put it back in L shld current_tpos ;Save cursor position call edit_setattr ;Update the sector hex display jmp editkeys ;Get next command from console edit_prevcol: lhld current_pos ;Get current cursor position mvi a, 7h ;Min col position cmp l ;Already at min? jz edit_wrapright ;Try wraparound call edit_clearattr ;Update the sector display lhld current_buf ;Get the buffer pointer dcx h ;Previous 'col' buffer position shld current_buf ;Save buffer pointer lhld current_pos ;Get current hex position mov b, l ;Move col value into B mvi c, 3h ;Put decrement in C call sub_daa ;Decimal subtract mvi a, 30h ;Column spacer cmp b ;Check it jnz edit_pvcol01 ;Move along if not mvi c, 2h ;Additional decrement call sub_daa ;Decimal subtract edit_pvcol01: mov l, b ;Move new col value into L shld current_pos ;Save cursor position lhld current_tpos ;Get current text position mov b, l ;Put text column position in b mvi c, 1h ;Put decrement in C call sub_daa ;Decimal subtract mov l, b ;Put new text column position in L shld current_tpos ;Save cursor text position call edit_setattr ;Update the sector hex display jmp editkeys ;Get next command from console edit_firstbyte: call edit_clearattr ;Update the sector display lxi h, secbuf ;Point to the sector buffer shld current_buf ;save buffer pointer lxi h, 0607h ;Top left cursor position shld current_pos ;Save cursor position lxi h, 0658h ;Top left text cursor position shld current_tpos ;Save cursor position call edit_setattr ;Update the sector display jmp editkeys ;Get next command from console edit_lastbyte: call edit_clearattr ;Update the sector display lxi h, secbuf ;Point to the sector buffer lxi b, 7fh ;End of buffer dad b ;Point to end of buffer shld current_buf ;save buffer pointer lxi h, 1354h ;Cursor end position in text sector display shld current_pos ;Save cursor position lxi h, 1373h ;Cursor end position in text sector display shld current_tpos ;Save cursor position call edit_setattr ;Update the sector display jmp editkeys ;Get next command from console edit_savesec: mvi c, wrdir ;Write immediately to sector call write ;Write sector call read ;Get sector call print_buffer ;Print sector jmp editmode ;Start over edit_rldsec: call read ;Get sector call print_buffer ;Print sector jmp editmode ;Start at first byte edit_txtmode: call edit_clearattr ;Update the sector display lda current_emode ;Get edit mode xri 1 ;Flip it sta current_emode ;Save new mode call edit_statline ;Update the edit mode status line call edit_setattr ;Update the sector display jmp editkeys ;Do next key edit_wrapleft: mvi a, 13h ;Max line position cmp h ;Already at max? jz edit_firstbyte ;Start over at the top call edit_clearattr ;Update the sector display lhld current_pos ;Get current hex position mvi l, 07h ;Set to far left column shld current_pos ;Save current position lhld current_tpos ;Get current text position mvi l, 58h ;Set to far left column shld current_tpos ;Save current text position lhld current_buf ;Get the buffer pointer lxi d, 0fff1h ;Point to far left 'column' buffer position dad d ;Adjust buffer pointer shld current_buf ;Save buffer pointer jmp edit_nextline ;Do next line edit_wrapright: mvi a, 06h ;Min line position cmp h ;Already at min? jz edit_lastbyte ;Move to the end call edit_clearattr ;Update the sector display lhld current_pos ;Get current hex position mvi l, 54h ;Set to far right column shld current_pos ;Save current position lhld current_tpos ;Get current text position mvi l, 73h ;Set to far left column shld current_tpos ;Save current text position lhld current_buf ;Get the buffer pointer lxi d, 0fh ;Point to far right 'column' buffer position dad d ;Adjust buffer pointer shld current_buf ;Save buffer pointer jmp edit_prevline ;Do previous line ; ; ;Clear attributes from current hex and text cells ;according to current_pos and current_tpos ;Modifies a, c, hl, de edit_clearattr: call set_normal ;Set normal intensity lhld current_pos ;Get current hex position xchg ;Put it in DE call move_cursor ;Move cursor lhld current_buf ;Point to sector buffer mov c, m ;Get buffer byte call print_hex ;Write it lhld current_tpos ;Get current text position xchg ;Put it in DE call move_cursor ;Move cursor lhld current_buf ;Point to sector buffer mov c, m ;Put it in C call print_chr ;Write it call edit_cursupd ;Update the cursor position ret ; ; ;Set attributes from current hex and text cells ;according to current_pos and current_tpos ;and state of text edit mode ;Modifies a, c, hl, de edit_setattr: call set_normal ;Set normal intensity lda current_emode ;Get text edit mode ana a ;Set flags jz edit_satr01 ;Print with normal video call set_reverse ;Otherwise print with reverse video edit_satr01: lhld current_pos ;Get current hex position xchg ;Put it in DE call move_cursor ;Move cursor lhld current_buf ;Point to sector buffer mov c, m ;Get buffer byte call print_hex ;Write it lda current_emode ;Get text edit mode ana a ;Set flags jz edit_satr02 ;Change to reverse video call set_normal ;Set normal video jmp edit_satr03 ;Print with normal video edit_satr02: call set_reverse ;Print with reverse video edit_satr03: lhld current_tpos ;Get current text position xchg ;Put it in DE call move_cursor ;Move cursor lhld current_buf ;Point to sector buffer mov c, m ;Put it in C call print_chr ;Write it call set_normal ;Reset to normal intensity call edit_cursupd ;Update the cursor position ret ; ; ;Update cursor position for hex or text display ;depending on edit mode ;Modifies a, c, hl, de edit_cursupd: lda current_emode ;Get text edit mode ana a ;Check it jnz edit_csup01 ;Move to text position lhld current_pos ;Get current hex cursor position jmp edit_csupex ;Move and return edit_csup01: lhld current_tpos ;Get current text cursor position edit_csupex: xchg call move_cursor ;Move cursor ret ; ; ;Update the status line with HEX or TEXT mode edit_statline: call set_reverse ;Set to inverse video lxi d, 2533h ;Point to edit mode status call move_cursor ;move the cursor lda current_emode ;Get edit mode ana a ;Check it jnz edit_stln01 ;Text mode update lxi d, edit_stlnhex ;Point to HEX status call print_objects ;Print it call set_normal ;Set to normal text ret edit_stln01: lxi d, edit_stlntext ;Point to HEX status call print_objects ;Print it call set_normal ;Set to normal text ret edit_stlnhex: db 2h, 25h, 33h, 'HEX ', 0h, 0ffh edit_stlntext: db 2h, 25h, 33h, 'TEXT', 0h, 0ffh ; ; ; ;Print the top header lines ; header_top: call clear_screen ;Clear the screen lxi d, header_objs ;Point to object list call print_objects ;Print it ret header_objs: db 0h, 01h, 24h, 'JWD 8080 Disk Editor v1.0', 0h db 0h, 03h, 01h, 'DISK: TRACK: SECTOR: BLOCK: RELSEC:', 0h db 0h, 05h, 07h, '0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF', 0h db 0ffh ; ; ;Print current disk, track, and sector ; print_params: call set_intense ;Set to bright video lxi d, 0307h ;Point to disk field call move_cursor ;Move the cursor lda current_drive ;Get current drive adi 'A' ;Make drive letter mov c, a ;Put it in C call print_chr ;Print it lxi d, 0317h ;Point to track field call move_cursor ;Move the cursor lda current_track ;Get current drive push psw ;Save A mov c, a ;Put it in C call print_hex ;Print it lxi d, 0329h ;Point to track field call move_cursor ;Move the cursor lda current_sector ;Get current drive mov c, a ;Put it in C call print_hex ;Print it lxi d, 0340h ;Point to block field call move_cursor ;Move the cursor pop psw ;Restore A cpi 0 ;Is it track 0? jnz print_par01 ;Calculate and display block number lxi d, print_parnb ;Point to no block string call print_string ;Print it lxi d, 0354h ;Point to relative sector field call move_cursor ;Move the cursor lxi d, print_parrs ;Point to no block string call print_string ;Print it jmp print_parex ;Exit print_par01 lda current_track ;Get the track number dcr a ;Subtract 1 push psw ;Save it ani 0e0h ;Mask on upper 3 bits rlc ;Put upper 3 bits into lower 3 bits rlc ;aka, multiply by 8 rlc ;but call it MSB mov h, a ;Save it in H pop psw ;Restore A ani 01fh ;Mask off upper 3 bits rlc ;Put lower 5 bits starting at bit 7 rlc ;aka, multiply by 8 rlc ;but call it LSB mov l, a ;Save it in L lda current_sector ;Get the sector number ani 0e0h ;Mask on upper 3 bits rlc ;Put upper 3 bits into lower 3 bits rlc ;aka, divide by 32 drop remainder rlc add l ;Add it to initial block number mov l, a ;Save it in L shld current_block ;Save current block mov c, h ;Get MSB call print_hex ;Print it mov c, l ;Get LSB call print_hex ;Print it lxi d, 0354h ;Point to relative sector field call move_cursor ;Move the cursor lda current_sector ;Get current sector ani 01fh ;Mask off upper bits mov c, a ;Put it in C call print_hex ;Print it print_parex call set_normal ;Set to normal video ret print_parnb: db '----', 0h print_parrs: db '--', 0h ; ; ;Print function controls ; print_navfun: call clear_nav_funzone ;Clear the navigation function zone lxi d, navfun_objs ;Point to object list call print_objects ;Print it ret navfun_objs: db 1h, 15h, 33h, '', 0h db 0h, 15h, 42h, 'Sector Navigation', 0h db 1h, 16h, 33h, '', 0h db 0h, 16h, 42h, 'Sector Edit', 0h db 1h, 17h, 33h, '', 0h db 0h, 17h, 42h, 'Exit to CP/M', 0h db 0ffh ; ; ;Print navigation sub-function controls ; print_navsubfun: call clear_nav_subfunzone ;Clear the sub-function area lxi d, navsubfun_objs ;Point to object list call print_objects ;Print it ret navsubfun_objs: db 1h, 19h, 38h, '', 0h db 0h, 19h, 42h, 'Change Disk', 0h db 1h, 20h, 38h, '', 0h db 0h, 20h, 42h, 'Change Track', 0h db 1h, 21h, 38h, '', 0h db 0h, 21h, 42h, 'Change Sector', 0h db 1h, 22h, 38h, '', 0h db 0h, 22h, 42h, 'Change Block', 0h db 0ffh ; ; print_editsubfun: call clear_nav_subfunzone ;Clear the sub-function area lxi d, editsubfun_objs ;Point to object list call print_objects ;Print it ret editsubfun_objs: db 1h, 19h, 33h, '', 0h db 0h, 19h, 42h, 'Save Sector', 0h db 1h, 20h, 33h, '', 0h db 0h, 20h, 42h, 'Reload Sector', 0h db 1h, 21h, 36h, '', 0h db 0h, 21h, 42h, 'Toggle Edit Mode', 0h db 0ffh ; ; ;Print navigation controls ; print_navmode: call clear_navzone ;Clear the nav control zone lxi d, navmode_objs ;Point to object list call print_objects ;Print it lxi d, nav_modestat ;Point to status line message call print_statline ;Print it ret navmode_objs: db 0h, 15h, 08h, '+Sec', 0h db 0h, 19h, 08h, '-Sec', 0h db 0h, 17h, 15h, '+Trk', 0h db 0h, 17h, 01h, '-Trk', 0h db 0h, 15h, 23h, 'First', 0h db 0h, 19h, 23h, 'Last', 0h db 1h, 16h, 09h, 'UP', 0h db 1h, 18h, 09h, 'DN', 0h db 1h, 17h, 06h, 'LF', 0h db 1h, 17h, 12h, 'RT', 0h db 1h, 16h, 24h, 'HOME', 0h db 1h, 18h, 24h, 'END', 0h db 0ffh nav_modestat: db 'MODE: Sector Navigation' db 0h ; ; ;Print editing controls ; print_editmode: call clear_navzone lxi d, editmode_objs ;Point to object list call print_objects ;Print it lxi d, edit_modestat ;Point to status line message call print_statline ;Print it ret editmode_objs: db 0h, 15h, 08h, '-Row', 0h db 0h, 19h, 08h, '+Row', 0h db 0h, 17h, 15h, '+Col', 0h db 0h, 17h, 01h, '-Col', 0h db 0h, 15h, 23h, 'First', 0h db 0h, 19h, 23h, 'Last', 0h db 1h, 16h, 09h, 'UP', 0h db 1h, 18h, 09h, 'DN', 0h db 1h, 17h, 06h, 'LF', 0h db 1h, 17h, 12h, 'RT', 0h db 1h, 16h, 24h, 'HOME', 0h db 1h, 18h, 24h, 'END', 0h db 0ffh edit_modestat: db 'MODE: Sector Editing' db 0h ; ; ;Clear the navigation button area ; clear_navzone mvi a, 15h ;Start line of nav control area mvi e, 31h ;Center screen column print_nz01: push psw ;Store it on the stack mov d, a ;put it in D call move_cursor ;Move cursor call clear_cursor_bol ;Clear line to left of cursor pop psw ;Get line from stack adi 1h ;Next line daa ;Decimal adjust it cpi 20h ;End of nav section? jnz print_nz01 ;If not do again ret ; ; ;Clear the navigation function area ; clear_nav_funzone mvi a, 15h ;Start line of nav function area mvi e, 31h ;Center screen column print_fnz01: push psw ;Store it on the stack mov d, a ;put it in D call move_cursor ;Move cursor call clear_cursor_eol ;Clear line to right of cursor pop psw ;Get line from stack adi 1h ;Next line daa ;Decimal adjust it cpi 18h ;End of nav section? jnz print_fnz01 ;If not do again ret ; ; ;Clear the sub-function area ; clear_nav_subfunzone mvi a, 19h ;Start line of sub-function area mvi e, 31h ;Start of screen area print_sfz01: push psw ;Store it on the stack mov d, a ;put it in D call move_cursor ;Move cursor call clear_cursor_eol ;Clear line to right of cursor pop psw ;Get line from stack adi 1h ;Next line daa ;Decimal adjust it cpi 23h ;End of nav section? jnz print_sfz01 ;If not do again ret ; ; ;Print Status Line Message print_statline call set_normal ;Set normal intensity xchg ;Swap DE and HL lxi d, 2501h ;Point to mode text call move_cursor ;Move cursor call set_reverse ;Set for reverse video call clear_line ;Clear the line xchg ;Swap DE and HL call print_string ;Print it mvi b, 57 call print_space ;Print spaces call set_normal ;Set normal intensity ret ; ; ;Print disk buffer ; print_buffer: ;Print the contents of the sector buffer call hide_cursor ;Turn off the cursor lxi h, secbuf ;Point to the sector buffer shld current_buf ;save buffer pointer lxi h, 0601h ;Row and column cursor start position shld current_pos ;Save cursor row/col position mvi a,0h ;Clear line counter pb001: sta current_line ;Save it in the line counter xchg ;Put cursor position in DE call move_cursor ;Move to column header position call print_bufhex ;Print line of hex bytes from the sector buffer lhld current_pos ;Get current position mvi l, 58h ;Move cursor right shld current_pos ;Save cursor row/col position xchg ;Put cursor position in DE call move_cursor ;Move to column header position call print_buftxt ;Print line of ascii bytes from the sector buffer lhld current_buf ;Get current buffer position lxi d, 10h ;Get buffer offset dad d ;Add to current buffer position shld current_buf ;Store in current buffer position lhld current_pos ;Get current screen position mov a, h ;Put line number in A inr a ;Point to next line daa ;Decimal adjust it mov h, a ;Put it back in H mvi l, 1 ;Point to first column shld current_pos ;Save it lda current_line ;Get current line inr a ;Next line cpi 8h ;Last line? jnz pb001 ;Do next line ret ; ; ;Print one line of buffer in hex ;Depends on displayed row/col and buffer line variables ; print_bufhex: mvi c, 0h ;Get offset prefix call print_hex ;Print it lda current_line ;Get current line counter rlc ;Move into high nibble rlc rlc rlc mov c, a ;Put it in C call print_hex ;Print it mvi c, ' ' ;Space call print_chr ;Print it call print_chr ;Again lhld current_buf ;Get current buffer position mvi a, 10h ;Set column counter sta current_col ;Get column counter pbh001: mov c, m ;Get character from buffer call print_hex ;Print hex byte lda current_col ;Get column counter dcr a ;Count down sta current_col ;Save it cpi 8h ;Time for extra space? jz pbh002 ;If so then print spacer cpi 0 ;End of line? rz ;Exit mvi c, ' ' ;Spacer call print_chr ;Print space jmp pbh003 ;Test for next pbh002: lxi d, sector_spacer ;Point to spacer string call print_string ;Print it pbh003: inx h ;Point to next buffer character jmp pbh001 ;If not zero do it again sector_spacer: db ' - ' db 0h ; ; ;Print one line of buffer in ascii ;Depends on displayed row/col and buffer line variables ; print_buftxt: lhld current_buf ;Get current buffer position mvi a, 10h ;Set column counter sta current_col ;Get column counter pbt001: mov c, m ;Get character from buffer call print_chr ;Print ascii character inx h ;Point to next buffer character lda current_col ;Get column counter dcr a ;Count down sta current_col ;Save it cpi 0 ;End of line? jnz pbt001 ;If not do it again ret ; ; ;Print objects on screen ;DE points to object in RAM ; db attribute (00 = normal, 01=intense, 02=reverse, 03=blink) ; dw cursor_pos (row, col) ; db string (....) ; db 0 ; db ffh 9? jnc ph_adig ;Print A-F adi 30h ;Make ascii 0-9 jmp ph_ndig ;Print hex digit ph_adig adi 37h ;Make ascii A-F ph_ndig push b ;Save BC mov c, a ;Move A into C call conout ;Print it pop b ;Restore BC ret ; ; ;Print printable character in C with '.' for non-printable ;Modifies: a print_chr: mov a, c ;Move C into A cpi 20h ;Is it lower non-print? jc pc_nonprint ;Change it to a '.' cpi 7fh ;Is it upper non-print? jnc pc_nonprint ;Change it to a '.' pc_print: push b ;Save BC mov c, a ;Move A into C call conout ;Print it pop b ;Restore BC ret pc_nonprint: mvi a, '.' ;Change it to printable jmp pc_print ;Print it ; ; ;Print new line ;Modifies: c print_nl: mvi c, 0dh ;Carriage return call conout ;Print it mvi c, 0ah ;Line feed call conout ;Print it ret ;Exit ; ; ;Send CSI sequence to console ;Modifies: a, c print_csi: mvi c, 1bh ;Escape character call conout ;Print it mvi c, '[' ;Bracket character call conout ;Print it ret ;Exit ; ; ;Clear screen ;Modifies: a (other call), c clear_screen: call print_csi ;Print CSI sequence mvi c, '2' ;First character call print_chr ;Print it mvi c, 'J' ;Erase display call print_chr ;Print it call print_csi ;Print CSI sequence mvi c, 'H' ;Home cursor call print_chr ;Print it ret ;Exit ; ; ;Clear from cursor to bottom of screen ;Modifies: a (other call), c clear_screen_fromcursor: call print_csi ;Print CSI sequence mvi c, '0' ;First character call print_chr ;Print it mvi c, 'J' ;Erase display call print_chr ;Print it call print_csi ;Print CSI sequence mvi c, 'H' ;Home cursor call print_chr ;Print it ret ;Exit ; ; ;Clear from top of screen to cursor ;Modifies: a (other call), c clear_screen_tocursor: call print_csi ;Print CSI sequence mvi c, '1' ;First character call print_chr ;Print it mvi c, 'J' ;Erase display call print_chr ;Print it call print_csi ;Print CSI sequence mvi c, 'H' ;Home cursor call print_chr ;Print it ret ;Exit ; ; ;Clear line ;Modifies c clear_line: call print_csi ;Print CSI sequence mvi c, '2' ;First character call print_chr ;Print it mvi c, 'K' ;Erase display call print_chr ;Print it ret ;Exit ; ; ;Clear line from cursor to end of line ;Modifies c clear_cursor_eol: call print_csi ;Print CSI sequence mvi c, 'K' ;Erase display call print_chr ;Print it ret ;Exit ; ; ;Clear line from beginning of line to cursor ;Modifies c clear_cursor_bol: call print_csi ;Print CSI sequence mvi c, '1' ;First character call print_chr ;Print it mvi c, 'K' ;Erase display call print_chr ;Print it ret ;Exit ; ; ;Move cursor to row/column in D ;Use BCD for row and column positions ;Modifies: a (other call), c move_cursor: call print_csi ;Print CSI sequence mov c, d ;Move row position into C call print_hex ;Print row position in ascii mvi c, ';' ;Get row/col separator call print_chr ;Print it mov c, e ;Move col position into A call print_hex ;Print col position in ascii mvi c, 'H' ;Cursor move terminator call print_chr ;Print it ret ;Exit ; ; ;Move cursor one line up ;Modifies c move_cursor_up: call print_csi ;Print CSI sequence mvi c, 'A' ;Cursor move terminator call print_chr ;Print it ret ;Exit ; ; ;Move cursor one line down ;Modifies c move_cursor_down: call print_csi ;Print CSI sequence mvi c, 'B' ;Cursor move terminator call print_chr ;Print it ret ;Exit ; ; ;Move cursor one place to the right ;Modifies c move_cursor_right: call print_csi ;Print CSI sequence mvi c, 'C' ;Cursor move terminator call print_chr ;Print it ret ;Exit ; ; ;Move cursor one place to the left ;Modifies c move_cursor_left: call print_csi ;Print CSI sequence mvi c, 'D' ;Cursor move terminator call print_chr ;Print it ret ;Exit ; ; ;Hide cursor ;Modifies c hide_cursor: call print_csi ;Print CSI sequence mvi c, '?' ;Control char call print_chr ;Print it mvi c, '2' ;Control char call print_chr ;Print it mvi c, '5' ;Control char call print_chr ;Print it mvi c, 'l' ;Control char call print_chr ;Print it ret ;Exit ; ; ;Show cursor ;Modifies c show_cursor: call print_csi ;Print CSI sequence mvi c, '?' ;Control char call print_chr ;Print it mvi c, '2' ;Control char call print_chr ;Print it mvi c, '5' ;Control char call print_chr ;Print it mvi c, 'h' ;Control char call print_chr ;Print it ret ;Exit ; ; ;Erase from cursor to end of screen ;Modifies c erase_cursor: call print_csi ;Print CSI sequence mvi c, 'J' ;Control char call print_chr ;Print it ret ;Exit ; ; ;Turn wraparound off ;Modifies c linewrap_off: call print_csi ;Print CSI sequence mvi c, '?' ;Control char call print_chr ;Print it mvi c, '7' ;Control char call print_chr ;Print it mvi c, 'l' ;Control char call print_chr ;Print it ret ; ; ;Turn wraparound on ;Modifies c linewrap_on: call print_csi ;Print CSI sequence mvi c, '?' ;Control char call print_chr ;Print it mvi c, '7' ;Control char call print_chr ;Print it mvi c, 'h' ;Control char call print_chr ;Print it ret ; ; ;Change to reverse video ;Modifies c set_reverse: call print_csi ;Print CSI sequence mvi c, '7' ;reverse video attribute call print_chr ;Print it mvi c, 'm' ;Set attribute call print_chr ;Print it ret ;Exit ; ; ;Change to intense video ;Modifies c set_intense: call print_csi ;Print CSI sequence mvi c, '1' ;Intense video attribute call print_chr ;Print it mvi c, 'm' ;Set attribute call print_chr ;Print it ret ;Exit ; ; ;Change to normal video ;Modifies c set_normal: call print_csi ;Print CSI sequence mvi c, '0' ;Reset video attribute call print_chr ;Print it mvi c, 'm' ;Set attribute call print_chr ;Print it ret ;Exit ; ; ;Change to underline video ;Modifies c set_underline: call print_csi ;Print CSI sequence mvi c, '4' ;Underline video attribute call print_chr ;Print it mvi c, 'm' ;Set attribute call print_chr ;Print it ret ;Exit ; ; ;Change to blinking video ;Modifies c set_blinking: call print_csi ;Print CSI sequence mvi c, '5' ;Blink video attribute call print_chr ;Print it mvi c, 'm' ;Set attribute call print_chr ;Print it ret ;Exit ; ; ;Get printable character get_char call conin ;Get single character from console cpi ' ' ;Less than ' '? rc ;Return if < ' ' with carry set lhld current_buf ;Point to sector buffer position mov m, a ;Store it in sector buffer xra a ;Clear A before return ret ;Exit ; ; ;Edit byte value and put in sector buffer ;Assumes cursor is at start position (far left) of byte to be edited ;Assumes current_buf is address of byte to be edited edit_hex: call get_hexdigit ;Get hex digit rc ;If invalid then exit rlc ;Move digit into high bits rlc rlc rlc mov b, a ;Save A in B call get_hexdigit ;Get hex digit (low bits) rc ;If invalid then exit add b ;Add in high bits lhld current_buf ;Point to sector buffer position mov m, a ;Store it in sector buffer xra a ;Clear A before return ret ;Exit ; ; ;Get hex byte from console with echo into A ;Modifies a, b, c get_hexbyte: call get_hexdigit ;Get hex digit (high bits) jc get_hexbyte ;If invalid try again rlc ;Move digit into high bits rlc rlc rlc mov b, a ;Save A in B get_hexbyt01: call get_hexdigit ;Get hex digit (low bits) jc get_hexbyt01 ;If invalid try again add b ;Add in high bits ret ;Exit ; ; ;Get single hex digit from console with echo ;Convert from ascii to binary in A ;Modifies a, c get_hexdigit: call conin ;Get single character from console cpi '0' ;Less than '0'? rc ;Return if < 0 with carry set cpi ':' ;Greater than '9'? jnc get_hexdig01 ;If so, check for A-F mov c, a ;Put A into C call conout ;Print it mov a, c ;Put C into A sui '0' ;Make ascii 0-9 into binary 0-9 ret ;Return hex character, no carry get_hexdig01: ani 0dfh ;Make it upper case cpi 'A' ;Less than 'A'? rc ;Return if less with carry set cpi 'G' ;Greater than 'F'? jc get_hexdig02 ;If not convert to binary stc ;Else, set carry ret ;Return invalid key, carry set get_hexdig02: mov c, a ;Put C into A call conout ;Print it mov a, c ;Put C back in A sui 37h ;Make ascii A-F into binary A-F ret ;Return hex character, no carry ; ; ;Decimal adjust on subtraction ;Good for positive results only. B=minuend, C=subtrahend ;Adjusted result in B ;Modifies a, b sub_daa: mov a, b sub c mov b, a ani 0fh cpi 0ah jnc sub_daa01 ret sub_daa01: mov a, b sbi 6h mov b, a ret ; ; ;Flush Console ;Checks to see if a character is waiting on the console ;and if so dumps that character flush_console: call const ;Flush console if character present rz ;Return if no character call conin ;Get character but don't process it ret ; ; ;Program variables ; current_line ds 1 ;Line counter current_col ds 1 ;Column counter current_pos ds 2 ;Current hex displayed row/col current_tpos ds 2 ;Current text displayed row/col current_buf ds 2 ;Current displayed buffer line current_drive ds 1 ;Current displayed drive current_track ds 1 ;Current displayed track current_sector ds 1 ;Current displayed sector current_block ds 2 ;Current displayed block current_emode ds 1 ;Current edit mode (0=hex, 1=text) ; ; ;Sector buffer ; secbuf ds 128