13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-28 09:52:32 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.bedtime.asm
2021-01-12 17:31:39 -06:00

1315 lines
57 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;----------------------------------------------------------------------
; Fontedit - Loads the current screen font and lets you modify it.
; Saves font in a COM file with integral loader. Requires EGA or VGA.
; Syntax: FONTEDIT [filespec]
; PC Magazine September 13, 1988
;----------------------------------------------------------------------
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT
ASSUME ES:_TEXT,SS:_TEXT
ORG 100H
START: JMP MAIN
; DATA AREA
; ---------
DB CR,SPACE,SPACE,SPACE,CR,LF
COPYRIGHT DB "FONTEDIT 1.0 (C) 1988 Ziff Communications Co. ",BOX
PROGRAMMER1 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
CR EQU 13
LF EQU 10
CTRL_Z EQU 26
SPACE EQU 32
BOX EQU 254
ESC_SCAN EQU 1
ENTER_SCAN EQU 1CH
UP_ARROW EQU 48H
DN_ARROW EQU 50H
LEFT_ARROW EQU 4BH
RIGHT_ARROW EQU 4DH
Y_SCAN EQU 15H
BS_SCAN EQU 0EH
TAB_CHAR EQU 9
MAX_POINTS EQU 16
PIXEL_OFF EQU 177
PIXEL_ON EQU 219
EDIT_COL EQU 32
EDIT_ROW EQU 8
EDIT_TOP EQU EDIT_ROW SHL 8 + EDIT_COL
TEMPLATE_TOP EQU EDIT_TOP - 28
CHAR_TOP EQU EDIT_TOP + 28
BOX_TOP EQU EDIT_TOP + 1 - 400H
INTENSITY EQU 1000B
MICKEY EQU 20
BUTTONS LABEL WORD
LEFT_BUTTON DB 0
RIGHT_BUTTON DB 0
SHIFT_KEYS EQU 3
SHIFT_STATE DB ?
HORIZONTAL DW 0
VERTICAL DW 0
NORMAL EQU 07H
ATTRIBUTE DB 07H
INVERSE DB 70H
ROWS DB ?
MAX_LINES DW 16
MOUSE_FLAG DB 0
MODIFY_FLAG DB 0
BLANKS DB 0,32,255
FILE_FLAG DB 0
FILE_HANDLE DW ?
FILENAME DW ?
LAST_PIXEL DB ?
;format: reg,value SEQUENCER REGISTERS GRAPHICS CONTROLLER REGISTERS
; MAP MASK MEMORY MODE MODE REG MISC READ MAP SELECT
ACCESS_A000H DB 2,4, 4,7, 5,0, 6,4, 4,2
PROTECT_A000H DB 2,3, 4,3, 5,10H, 6,0AH, 4,0
MENU LABEL BYTE
DB "F1 Del row F2 Ins row F3 Dup row F4 Save $"
MENU1 LABEL BYTE
DB "F5 Copy template char. Tab = select edit/char box"
DB " Use: arrow keys or mouse",CR,LF
DB "Hold Shift key or mouse button to drag. Esc to exit"
DB " Rows displayed = ",CR,LF
DB "Left button = pixel on",CR,LF
DB "Right button = pixel off",CR,LF
DB "Space bar = toggle pixel$"
MENU2 LABEL BYTE
DB "Enter = select char.",0
DB "Button = select char.",0
DB "PgUp/PgDn prev./next char.",0
CAPTIONS DW TEMPLATE_TOP - 2
DB "Template Char",0
DW EDIT_TOP - 2
DB " Edit Char",0
DW CHAR_TOP - 2
DB "Character Set",0
CURRENT_BOX DB 218, 5 DUP (196), 194, 5 DUP (196), 191
DB 179, 5 DUP (SPACE), 179, 5 DUP (SPACE), 179
DB 192, 5 DUP (196), 193, 5 DUP (196), 217
NOT_ENOUGH DB "Not enough memory$"
NOT_SUPPORTED DB "Font too tall$"
NOT_EGA_VGA DB "Ega/Vga not found$"
SAVE_MSG DB CR,LF,"Save ",0
FILE_MSG DB "file",0
CREATE_MSG DB CR,LF,"Create ",0
EXIST_MSG DB CR,LF,"Write over existing ",0
YES_NO DB "? Y/N",0
FAILED_MSG DB CR,LF,"Failed$"
FILENAME_MSG DB CR,LF,"Enter filename",CR,LF,"$"
NOT_FONT_MSG DB " not font$"
COM DB ".COM",0
WARNING_MSG DB LF,"Warning! The cursor row will be deleted in"
DB " EVERY character in this font.",CR,LF,"Continue$"
DISPATCH_KEY DB 1, 4BH, 4DH, 48H, 50H, 49H
DB 51H, 0FH, 39H, 1CH, 3BH, 53H
DB 3CH, 52H, 3DH, 3EH, 3FH
DISPATCH_CNT EQU $ - DISPATCH_KEY
DISPATCH_TABLE DW EXIT, LEFT, RIGHT, UP, DOWN, PGUP
DW PGDN, TAB, SPACE_BAR, ENTER, DEL_ROW, DEL_ROW
DW INS_ROW, INS_ROW, DUP_ROW, SAVE, COPY_TEMP
DISPATCH_END EQU $ - 2
; CODE AREA
; ---------
MAIN PROC NEAR
CLD ;All string operations forward.
MOV BX,1024 ;Allocate 1024 paragraphs; 16K.
MOV AH,4AH
INT 21H
MOV DX,OFFSET NOT_ENOUGH ;Exit with message if not enough.
JC ERROR_MSG
MOV AX,500H ;Make sure zero video page.
INT 10H
MOV AX,40H ;Point to BIOS data area.
MOV ES,AX
MOV AX,1A00H ;Get display info.
INT 10H
CMP AL,1AH ;Function supported?
JNZ CK_EGA ;If no, not VGA; check EGA.
CMP BL,7 ;Else, monochrome VGA?
JZ GET_CRT_MODE ;If yes, OK.
CMP BL,8 ;Else, color VGA?
JZ GET_CRT_MODE ;If yes, OK.
CK_EGA: MOV MAX_LINES,14 ;Else, use 14 max lines for EGA.
MOV BL,10H ;Get EGA information.
MOV AH,12H
INT 10H
MOV DX,OFFSET NOT_EGA_VGA
CMP BL,10H ;Is there an EGA?
JZ ERROR_MSG ;If no, exit with message.
TEST ES:BYTE PTR [87H],8 ;Is EGA active?
JNZ ERROR_MSG ;If no, exit with message.
GET_CRT_MODE: MOV BL,ES:[49H] ;Retrieve CRT_MODE.
CALL INFORMATION ;Get font information.
MOV DX,OFFSET NOT_SUPPORTED
CMP CX,MAX_POINTS ;Font greater than 16 points?
JBE CK_MODE ;If no, OK.
ERROR_MSG: CALL PRINT_STRING ;Print error message.
ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1
JMP TERMINATE ;Exit.
CK_MODE: CMP BL,7 ;CRT_MODE mono?
JZ SAVE_MODE ;If yes, skip.
MOV BYTE PTR PROTECT_A000H + 7,0EH ;Else, change parameter.
CMP BL,2 ;Is mode BW80?
JZ SAVE_MODE ;If yes, defaults.
MOV ATTRIBUTE,17H ;Else, use color attributes.
MOV INVERSE,71H
CMP BL,3 ;Are we in CO80?
JZ SAVE_MODE ;If yes, done here.
MOV AX,3 ;Else, change to CO80.
INT 10H
MOV BL,3
SAVE_MODE: MOV CRT_MODE,BL ;Save CRT_MODE in loader.
CALL SETUP ;Setup the display.
;************************** MAIN LOOP **************************;
; User input dispatcher. AH = ASCII character; AL = Scan Code. ;
;***************************************************************;
INPUT: CALL HIDE_CURSOR ;Park cursor off screen.
CALL GET_INPUT ;Get some input from user.
CMP BUTTONS,0 ;Was a mouse button pressed?
JZ CK_ASCII ;If no, check keyboard input.
CALL BUTTON_PRESS ;Else, process button press.
JMP SHORT INPUT ;Next input.
CK_ASCII: OR AL,AL ;Scan code zero?
JZ ALT_INPUT ;If yes, ALT keypad entry.
MOV DI,OFFSET DISPATCH_KEY ;Else, check dispatch table.
MOV CX,DISPATCH_CNT
REPNZ SCASB
JNZ ALT_INPUT ;If no match, keyboard char.
SHL CX,1 ;Else, look up subroutine
MOV DI,OFFSET DISPATCH_END
SUB DI,CX
CALL [DI] ; and process command.
JMP SHORT INPUT ;Next input.
ALT_INPUT: OR AH,AH ;ASCII zero?
JZ INPUT ;If yes, skip.
MOV EDIT_CHAR,AH ;Else, store as new character.
CALL SETUP_END ;Display new edit character.
JMP SHORT INPUT ;Next input.
;---------------------------------------------------;
; Exit. If font was modified, prompt user to save. ;
;---------------------------------------------------;
EXIT: CALL CLS ;Clear the screen.
CMP MODIFY_FLAG,1 ;Font modified?
JNZ GOOD_EXIT ;If no, return to DOS.
MOV SI,OFFSET FILE_MSG
CMP FILE_FLAG,1 ;If there a filename?
JZ DO_FILE ;If yes, display it.
MOV FILENAME,SI ;Else, display "file".
DO_FILE: MOV SI,OFFSET SAVE_MSG
CALL PROMPT ;Prompt user to save.
JNZ GOOD_EXIT ;If "Y"es not pressed, exit.
CMP FILE_FLAG,1 ;Else, is there a filename?
JZ DO_SAVE ;If yes, save it.
CALL GET_NAME ;Else, get a filename.
JC GOOD_EXIT ;If aborted, exit.
DO_SAVE: CALL SAVE_FILE ;Save the font COM file.
GOOD_EXIT: CALL CLS ;Clear the screen.
XOR AL,AL ;ERRORLEVEL zero.
TERMINATE: MOV AH,4CH ;Return to DOS.
INT 21H
MAIN ENDP
; ***************
; * SUBROUTINES *
; ***************
;-------------------------------------------------------------;
; What follows is the user input command processing routines. ;
;-------------------------------------------------------------;
BUTTON_PRESS: CALL GET_CURSOR ;Is cursor in character box?
JNZ DO_ENTER ;If yes, process as if Enter.
CMP LEFT_BUTTON,0 ;Else, left button press
JZ TURN_OFF ; will turn on pixel.
CALL GET_PIXEL ;Get the pixel.
OR [DI],AH ;Turn it on.
JMP SHORT BUTTON_END
TURN_OFF: CALL GET_PIXEL ;Right button will turn off pixel
XOR AH,0FFH ;Invert bit mask.
AND [DI],AH ;Turn it off.
BUTTON_END: CALL UPDATE_CURSOR ;Update the cursor.
CALL LOAD_CHAR ;Load the character.
RET
;--------------------------------;
ENTER: CALL GET_CURSOR ;Is cursor in character box?
JZ ENTER_END ;If no, ignore.
DO_ENTER: CALL GET_CHAR ;Else, get the highlighted char.
MOV EDIT_CHAR,AL ;Store it as new edit char.
CALL NEW_CHAR ;Display the edit character.
ENTER_END: RET
;--------------------------------;
LEFT: MOV BP,0FFH ;Movement = 0 rows; -1 cols.
JMP SHORT ARROWS
RIGHT: MOV BP,1 ;Movement = 0 rows; +1 cols.
JMP SHORT ARROWS
UP: MOV BP,0FF00H ;Movement = -1 rows; 0 cols.
JMP SHORT ARROWS
DOWN: MOV BP,100H ;Movement = +1 rows; 0 cols.
ARROWS: CALL RESTORE ;Restore current cursor position.
CALL GET_CURSOR ;Cursor in edit box?
MOV CX,BP
JNZ CHAR_ARROW ;If no, do character movement.
ADD CL,CL ;Else, double up col. movement.
CALL CK_BOUNDS ;Move cursor; check the boundary.
SUB AX,EDIT_TOP ;AX has position; make relative.
MOV EDIT_CURSOR,AX ;Store as new edit cursor.
MOV BH,LAST_PIXEL ;Retrieve the last pixel.
CALL GET_PIXEL ;Get pixel in new position.
CMP SHIFT_STATE,0 ;Button or Shift key depressed?
JZ UPDATE_PIXEL2 ;If no, update new cursor pos.
OR BH,BH ;Else, was last pixel on?
JNZ BIT_ON ;If yes, drag to new position.
XOR AH,0FFH ;Else, invert mask
AND BYTE PTR [DI],AH; ; and drag pixel off.
JMP SHORT UPDATE_PIXEL1
BIT_ON: OR BYTE PTR [DI],AH ;Turn the pixel on.
UPDATE_PIXEL1: CALL LOAD_CHAR ;Load the character.
UPDATE_PIXEL2: CALL UPDATE_CURSOR ;Update the cursor display.
RET
;--------------------------------;
CHAR_ARROW: CALL CK_BOUNDS ;Move cursor; check the boundary.
SUB AX,CHAR_TOP ;Convert to relative position.
MOV CHAR_CURSOR,AX ;Store new character box pos.
CMP SHIFT_STATE,0 ;Button or Shift key depressed?
JZ CHAR_END ;If no, done here.
NEW_CHAR: CALL GET_CHAR ;Else, get the character
MOV EDIT_CHAR,AL ; and use as new edit character.
CALL DISPLAY_FONT ;Display it.
CHAR_END: CALL UPDATE_CURSOR ;Update the cursor display.
RET
;--------------------------------;
PGUP: DEC EDIT_CHAR ;Next lower edit character.
JMP SHORT PAGE_END
PGDN: INC EDIT_CHAR ;Next higher edit character.
PAGE_END: CALL SETUP_END ;Display it.
RET
;--------------------------------;
TAB: CALL RESTORE ;Restore current cursor position.
XOR EDIT_FLAG,1 ;Toggle Edit/char active box.
CALL UPDATE_CURSOR ;Display cursor in new box.
RET
;--------------------------------;
SPACE_BAR: CALL GET_CURSOR ;Is cursor in character box?
JNZ SPACE_END ;If yes, ignore.
CALL GET_PIXEL ;Else, get the pixel.
XOR [DI],AH ;Toggle the pixel.
CALL UPDATE_PIXEL1 ;Update character and cursor.
SPACE_END: RET
;--------------------------------;
DEL_ROW: CALL GET_CURSOR ;Is cursor in character box?
JNZ DELETE_RETURN ;If yes, ignore.
MOV BP,POINTS ;Else, retrieve scan line points.
CMP BP,1 ;Is there only one scan line?
JZ DELETE_RETURN ;If yes, ignore.
MOV AL,AH ;Else, delete position equals
XOR AH,AH ; POINTS - relative ROW.
SUB BP,AX
CALL CLEAR_MENU ;Clear part of the menu and
MOV DX,OFFSET WARNING_MSG ; display warning message.
CALL PRINT_STRING
CALL QUERY ;Should we delete?
JNZ DELETE_END ;If no, done here.
MOV BX,POINTS ;Else, retrieve bytes/char.
MOV SI,OFFSET EDIT_FONT ;Delete edit font.
CALL DELETE
MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font.
CALL DELETE
DEC BX ;One less byte/char.
MOV BH,BL
CMP BYTE PTR EDIT_CURSOR + 1,BL ;Was last row deleted?
JNZ LOAD_IT ;If no, OK.
DEC BL ;Else, move cursor up one
MOV BYTE PTR EDIT_CURSOR + 1,BL ; row so it's on new char.
LOAD_IT: MOV BP,OFFSET EDIT_FONT
CALL USER_LOAD ;Load the new font.
CALL INFORMATION ;Get font information.
MOV MODIFY_FLAG,1 ;Note that font's been modified.
CALL CLS ;Clear the old display.
DELETE_END: XOR DX,DX
CALL SET_CURSOR
CALL DISPLAY_COPY ;Display new font.
DELETE_RETURN: RET
;-----------------;
DELETE: MOV DI,SI ;Destination starts at source.
MOV CX,256 ;256 characters to do.
NEXT_DELETE: PUSH CX ;Save character count.
MOV CX,BX ;BX has bytes/character.
CK_SKIP: CMP CX,BP ;Is this the row to delete?
JZ SKIP_ROW ;If yes, skip it.
MOVSB ;Else, move it down.
JMP SHORT LOOP_DELETE
SKIP_ROW: INC SI ;Skip deletion row.
LOOP_DELETE: LOOP CK_SKIP ;Do all character rows.
POP CX
LOOP NEXT_DELETE ;Do all 256 characters.
RET
;--------------------------------;
INS_ROW: XOR BL,BL ;Insert a zero byte.
JMP SHORT INS_EDIT
;--------------------------------;
DUP_ROW: MOV BL,-1 ;Insert a duplicate byte.
INS_EDIT: CALL GET_CURSOR ;Is cursor in character box?
JNZ INSERT_END ;If yes, ignore.
MOV BH,AH ;Row to be inserted.
INC BH ;Adjust.
MOV BP,POINTS ;Retrieve bytes/char.
CMP BP,MAX_LINES ;Character maxed out?
JZ INSERT_END ;If yes, done here.
STD ;Else, backward moves.
MOV SI,OFFSET EDIT_FONT ;Insert a row.
CALL INSERT
MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font.
CALL INSERT
CLD ;String operation back forward.
MOV BX,BP ;Increment bytes/character.
MOV BH,BL
INC BH
MOV BP,OFFSET EDIT_FONT ;Load the new font.
CALL USER_LOAD
CALL INFORMATION ;Get font information.
MOV MODIFY_FLAG,1 ;Note that font's been modified.
CALL SETUP_END ;Display new font.
INSERT_END: RET
;-----------------;
INSERT: MOV AX,BP ;Go to end of font
MOV CX,256 ; (256 * points) - 1
MUL CX
DEC AX
ADD SI,AX
MOV DI,SI
ADD DI,CX ;New font = old font + 256.
NEXT_INSERT: PUSH CX ;Save character count.
MOV CX,BP ;Retrieve bytes/char.
MOVE_BYTE: MOVSB ;Move a byte.
CMP CL,BH ;Is there an insert row?
JNZ LOOP_INSERT
MOV AL,BL ;If yes, assume zero insert.
OR BL,BL ;Is zero to be inserted?
JZ INSERT_IT ;If yes, guessed right.
MOV AL,[SI+1] ;Else, duplicate with byte below.
INSERT_IT: STOSB ;Insert it.
LOOP_INSERT: LOOP MOVE_BYTE ;Do all bytes/char.
POP CX
LOOP NEXT_INSERT ;Do all 256 characters.
RET
;--------------------------------;
COPY_TEMP: CALL GET_PIXEL ;Get index to current char.
MOV DI,SI ;Destination = Source+(16 * 256).
ADD SI,MAX_POINTS * 256
MOV CX,POINTS ;Bytes/character to copy.
REP MOVSB ;Copy them.
CALL SETUP_END ;Update the display.
CALL LOAD_CHAR ;Load the new character.
RET
;--------------------------------;
SAVE: CMP FILE_FLAG,1 ;Is there a filename?
JZ SAVE_IT ;If yes, save it.
CALL CLS ;Else, clear screen.
CALL GET_NAME ;Get a filename.
PUSHF ;Save results.
CALL DISPLAY_HEAD ;Redisplay menu.
POPF ;Retrieve results.
JC SAVE_END ;If user aborted, skip save.
SAVE_IT: CALL SAVE_FILE ;Save the file.
SAVE_END: RET
;*********** END OF COMMAND PROCESSING ROUTINES ***********;
;---------------------------;
; OUTPUT ;
; If Edit cursor, ZF = 1 ;
; If Char cursor, ZF = 0 ;
; DX = cursor position. ;
; AX = relative position. ;
;---------------------------;
GET_CURSOR: MOV AX,EDIT_CURSOR ;Assume edit cursor; retrieve it.
MOV DX,AX ;Cursor position = relative
ADD DX,EDIT_TOP ; position + top left of edit box
CMP EDIT_FLAG,1 ;Are we in edit box?
JZ CURSOR_END ;If yes, guessed right.
MOV AX,CHAR_CURSOR ;Else, retrieve char. cursor.
MOV DX,AX ;Calculate cursor position.
ADD DX,CHAR_TOP
CURSOR_END: RET
;---------------------------------------------------;
; Return highlighted cursor position to background. ;
;---------------------------------------------------;
RESTORE: MOV BL,ATTRIBUTE ;Background attribute.
CALL GET_CURSOR ;Is cursor in character box?
JNZ CHAR_RESTORE ;If yes, restore char box.
CALL GET_PIXEL ;Else, get pixel and write.
CALL WRITE_PIXEL
RET
CHAR_RESTORE: CALL GET_CHAR ;Get character and write.
CALL WRITE_CHAR
RET
;--------------------------------;
; Highlight new cursor position. ;
;--------------------------------;
UPDATE_CURSOR: MOV BL,ATTRIBUTE ;Retrieve background attribute.
OR BL,INTENSITY ;Turn on intensity bit.
CALL GET_CURSOR ;Is cursor in character box?
JNZ DO_CHAR ;If yes, do character cursor.
FONT_CURSOR: CALL GET_PIXEL ;Else, get pixel and write it.
CALL WRITE_PIXEL
RET
DO_CHAR: CALL GET_CHAR ;Retrieve character.
MOV DI,OFFSET BLANKS ;Use inverse video for invisible
MOV CX,3 ; characters 0, 32 and 255.
REPNZ SCASB
JNZ DO_CURSOR
MOV BL,INVERSE
DO_CURSOR: CALL WRITE_CHAR ;Update the character cursor.
RET
;-----------------------------------;
; INPUT ;
; AX = Relative cursor position. ;
; DX = Actual cursor position. ;
; CX = Direction. ;
; ;
; OUTPUT ;
; DX = New cursor position. ;
; AX = New cursor position. ;
; BX preserved. ;
;-----------------------------------;
CK_BOUNDS: ADD DH,CH ;Add row direction
ADD DL,CL ; and column direction.
PUSH BX ;Save BX.
MOV BL,16 ;Use 16 as bounds for char.
CMP EDIT_FLAG,1 ; box bottom.
JNZ CK_LEFT ;Use bytes/char bounds for edit
MOV BX,POINTS ; box bottom.
CK_LEFT: ADD AL,CL ;Add column to relative pos.
JGE CK_RIGHT
ADD DL,16 ;If too far left,
JMP SHORT BOUNDS_END ; wrap to right.
CK_RIGHT: CMP AL,16 ;If too far right,
JB CK_UP
SUB DL,16 ; wrap to left.
CK_UP: ADD AH,CH ;Add row to relative position.
JGE CK_DOWN
ADD DH,BL ;If too far up,
JMP SHORT BOUNDS_END ; wrap to bottom
CK_DOWN: CMP AH,BL ;If too far down,
JB BOUNDS_END ; wrap to top.
MOV DH,EDIT_ROW
BOUNDS_END: MOV AX,DX ;Return copy of cursor position.
POP BX ;Restore BX.
RET
;----------------------------------;
; INPUT ;
; AX = Relative cursor position. ;
; ;
; OUTPUT ;
; AL = character. ;
;----------------------------------;
GET_CHAR: MOV CL,4 ;Character = row * 16 + column.
SHL AH,CL
ADD AL,AH
RET
;-------------------;
; Font information. ;
;-------------------;
INFORMATION: MOV BH,2 ;Get information.
MOV AX,1130H
INT 10H
PUSH CS ;Restore extra segment.
POP ES
MOV POINTS,CX ;Store bytes/character.
MOV ROWS,DL ;Store rows on screen.
RET
;----------------------------------------------------------------;
; Filename is parsed of white space and COM extension tacked on. ;
;----------------------------------------------------------------;
PARSE_FILE: MOV SI,81H ;Point to parameter.
NEXT_PARSE: LODSB ;Get a byte.
CMP AL,SPACE ;Is it leading space?
JZ NEXT_PARSE ;If yes, ignore.
CMP AL,TAB_CHAR ;Is it leading tab?
JZ NEXT_PARSE ;If yes, ignore.
DEC SI ;Adjust pointer.
MOV FILENAME,SI ;Store start of filename.
FIND_END: LODSB ;Get a byte.
CMP AL,SPACE ;Is it space or below?
JBE PARSE_END ;If yes, end of filename.
CMP AL,"a" ;Capitalize.
JB CK_DOT
CMP AL,"z"
JA CK_DOT
AND BYTE PTR [SI-1],5FH
CK_DOT: CMP AL,"." ;Is it a dot?
JNZ FIND_END ;If no, continue.
PARSE_END: MOV DI,SI ;Else, if dot or end of filename
DEC DI ; tack on ".COM".
MOV SI,OFFSET COM
MOV CX,5
REP MOVSB
RET
;-----------------------------;
; OUTPUT ;
; If file exists, CY = 0 ;
; If file not found, CY = 1 ;
;-----------------------------;
OPEN_FILE: MOV DX,FILENAME
MOV AX,3D02H ;Open file for reading, writing.
INT 21H
SAVE_HANDLE: MOV FILE_HANDLE,AX ;Save filehandle.
MOV BX,AX
RET
;------------------------;
; OUTPUT ;
; If successful CY = 0 ;
; If failed CY = 1 ;
;------------------------;
CREATE_FILE: MOV DX,FILENAME
XOR CX,CX ;Create normal file.
MOV AH,3CH
INT 21H
JC CREATE_END
CALL SAVE_HANDLE ;If successful, save filehandle
CALL SAVE_FILE ; and save font file.
CREATE_END: RET
;-----------------------------------------------------------------------;
; Read the parsed file. Check if legitimate font file. Load the font. ;
;-----------------------------------------------------------------------;
READ_FILE: MOV BX,FILE_HANDLE ;Retrieve filehandle.
MOV DX,OFFSET LOADER ;Point to loader.
MOV CX,LOADER_LENGTH ;Bytes to read.
MOV AH,3FH ;Read from disk.
INT 21H
MOV SI,OFFSET PROGRAMMER1 ;Use name as legitimate font
MOV DI,OFFSET PROGRAMMER2 ; file signature.
MOV CX,SIGNATURE_LEN / 2
REPZ CMPSW
JZ READ_END
CALL DISP_FILENAME
MOV DX,OFFSET NOT_FONT_MSG ;If not font file, exit
JMP ERROR_MSG ; with message.
READ_END: MOV FILE_FLAG,1 ;Else, note that filename found.
PUSH BX ;Save filehandle.
MOV BP,OFFSET EDIT_FONT ;Point to font.
MOV BH,BYTE PTR POINTS ;Bytes/character.
CALL USER_LOAD ;Load the font.
CALL INFORMATION ;Get font information.
POP BX ;Retrieve filehandle.
;--------------------------------;
CLOSE_FILE: MOV AH,3EH
INT 21H
RET
;--------------------------------;
SAVE_FILE: CALL OPEN_FILE ;Open the file and write
MOV DX,OFFSET LOADER ; font image and loader to disk.
MOV CX,LOADER_LENGTH
MOV AH,40H
INT 21H
MOV MODIFY_FLAG,0 ;Reset modify flag.
MOV FILE_FLAG,1 ;Note that have a filename.
JMP SHORT CLOSE_FILE
;-------------------------------;
; INPUT ;
; SI = first string to write. ;
; ;
; OUTPUT ;
; If "Y"es pressed, ZF = 1 ;
; Else, ZF = 0 ;
;-------------------------------;
PROMPT: CALL TTY_STRING ;Write preface string.
CALL DISP_FILENAME ;Write filename.
QUERY: MOV SI,OFFSET YES_NO ;Write query string.
CALL TTY_STRING
CALL GET_KEY ;Get a response.
CMP AH,Y_SCAN ;Check if "Y" pressed.
RET
;-------------------------------;
; OUTPUT ;
; If name valid, CY = 0 ;
; If invalid or abort, CY = 1 ;
;-------------------------------;
GET_NAME: MOV DX,OFFSET FILENAME_MSG ;Ask for filename.
CALL PRINT_STRING
MOV DI,81H ;Use PSP's DTA for input.
NEXT_NAME: CALL GET_KEY ;Get a keystroke.
CMP AH,ESC_SCAN ;Esc?
STC
JZ NAME_END ;If yes, abort with CY = 1.
CMP AH,LEFT_ARROW ;Backspace with left arrow
JZ DO_BS ; or backspace key.
CMP AH,BS_SCAN
JZ DO_BS
CMP AH,ENTER_SCAN ;If Enter key, done here.
JZ STORE_BYTE
CMP AL,SPACE ;Ignore space and below.
JBE NEXT_NAME
JMP SHORT STORE_BYTE
DO_BS: DEC DI ;TTY Backspace = the characters
MOV AL,8 ; 8, space and 8.
PUSH AX
CALL WRITE_TTY
MOV AL,SPACE
CALL WRITE_TTY
POP AX
JMP SHORT DISPLAY_BYTE
STORE_BYTE: STOSB
CMP AH,ENTER_SCAN ;Done if Enter.
JZ PARSE_IT
DISPLAY_BYTE: CALL WRITE_TTY ;Echo input to screen.
JMP SHORT NEXT_NAME
PARSE_IT: CALL PARSE_FILE ;Parse the filename.
CALL OPEN_FILE ;See if it exists.
JC CREATE_IT ;If no, create it.
MOV SI,OFFSET EXIST_MSG ;Else, ask if should write
CALL PROMPT ; over existing file.
JNZ GET_NAME
CREATE_IT: CALL CREATE_FILE ;Create the file.
JNC NAME_END
MOV DX,OFFSET FAILED_MSG ;If failed, inform user
CALL PRINT_STRING ; and ask for new filename.
JMP SHORT GET_NAME
NAME_END: RET
;--------------------------------------;
; OUTPUT ;
; AH = Bit mask ;
; AL = PIXEL_ON or PIXEL_OFF ;
; SI = Pointer to start of Character ;
; DI = Pointer to start of Scan Line ;
; PIXEL = 0 or -1 ;
;--------------------------------------;
GET_PIXEL: MOV SI,OFFSET EDIT_FONT ;Point to start of edit font.
CALL CHAR_START ;Index to current character.
MOV DI,SI ;Also into DI.
MOV CX,EDIT_CURSOR ;Retrieve edit cursor.
SHR CL,1 ;Two col/bit so divide by two.
MOV AH,10000000B ;Bit starts in most significant.
SHR AH,CL ;Shift bit to column position.
MOV CL,CH ;Row in CL.
XOR CH,CH ;Zero in high half.
ADD DI,CX ;Add to character start.
MOV CL,[DI] ;Retrieve the current byte.
MOV AL,PIXEL_OFF ;Assume it is off.
MOV LAST_PIXEL,0
AND CL,AH ;AND with bit mask.
JZ END_PIXEL ;If off, guessed right.
MOV AL,PIXEL_ON ;Else, pixel is on.
MOV LAST_PIXEL,-1
END_PIXEL: RET
;--------------------------------;
WRITE_PIXEL: CALL WRITE_CHAR ;Two characters/pixel.
INC DL
CALL WRITE_CHAR
INC DL
RET
;----------------------------;
; INPUT ;
; SI = Font start. ;
; ;
; OUTPUT ;
; AX = Edit character. ;
; SI = Start of character. ;
;----------------------------;
CHAR_START: MOV CX,POINTS ;Retrieve bytes/character.
MOV AL,EDIT_CHAR ;Retrieve edit character.
XOR AH,AH ;Zero in high half.
PUSH AX ;Preserve character.
MUL CL ;Char start = bytes/char * char.
ADD SI,AX ;Add to index.
POP AX ;Retrieve character.
RET
;--------------------------------------------;
; OUTPUT ;
; AH = ASCII character. ;
; AL = Scan code. ;
; BUTTONS = button pressed. ;
; SHIFT_STATE = Shift or button depressed. ;
;--------------------------------------------;
GET_INPUT: XOR BP,BP ;Store input in BP; start with 0.
MOV SHIFT_STATE,0 ;Zero in Shift state.
MOV BUTTONS,0 ;Zero in Buttons also.
CMP MOUSE_FLAG,1 ;Is the mouse active?
JNZ CK_KEYBOARD ;If no, skip mouse poll.
XOR BX,BX ;Left button.
MOV AX,5 ;Button press information.
INT 33H
OR SHIFT_STATE,AL ;Store button depressed info.
OR LEFT_BUTTON,BL ;Store button press info.
MOV BX,1 ;Do same for right button.
MOV AX,5
INT 33H
OR RIGHT_BUTTON,BL ;Store button pressed info.
CMP BUTTONS,0 ;Any button pressed?
JNZ INPUT_END ;If yes, done here.
MOUSE_MOTION: MOV AX,0BH ;Read mouse motion.
INT 33H
ADD CX,HORIZONTAL ;Add in last horizontal motion.
ADD DX,VERTICAL ; and last vertical motion.
MOV AX,MICKEY ;Retrieve mouse unit of motion.
MOV SI,RIGHT_ARROW ;Assume right movement.
CMP CX,AX ;Is horizontal > mickey?
JG HORIZ ;If yes, guessed right.
MOV SI,DN_ARROW ;Assume down movement.
CMP DX,AX ;Is vertical > mickey?
JG VERT ;if yes, guessed right.
NEG AX ;Else, negate mickey.
MOV SI,LEFT_ARROW ;Assume left movement.
CMP CX,AX ;Is horizontal < mickey?
JL HORIZ ;If yes, guessed right.
MOV SI,UP_ARROW ;Assume up movement.
CMP DX,AX ;Is vertical < mickey?
JGE STORE_MOTION ;If yes, guessed right.
VERT: SUB DX,AX ;Subtract vertical mickey.
JMP SHORT STORE_SCAN ;Update vertical.
HORIZ: SUB CX,AX ;Subtract horizontal mickey.
STORE_SCAN: MOV BP,SI ;Store scan code in BP.
STORE_MOTION: MOV HORIZONTAL,CX ;Update movements.
MOV VERTICAL,DX
CK_KEYBOARD: MOV AH,2 ;Keyboard Shift state.
INT 16H
AND AL,SHIFT_KEYS ;Mask off all but Shift keys.
OR SHIFT_STATE,AL ;Store Shift state.
MOV AH,1 ;Keystroke status.
INT 16H
JZ STORE_INPUT ;If none available, done here.
CALL GET_KEY ;Else, get keystroke
XCHG AL,AH ;Exchange scan/ASCII code.
JMP SHORT INPUT_END
STORE_INPUT: MOV AX,BP ;Return input in AX
OR AX,AX ;Is there input?
JNZ INPUT_END ;If yes, done here.
CMP BUTTONS,0 ;Is there button pressed?
JNZ INPUT_END ;If yes, done here.
JMP GET_INPUT ;Else, wait until input.
INPUT_END: RET
;--------------------------------;
DISPLAY_FONT: MOV AL,ROWS ;Retrieve rows on screen.
INC AL ;Zero based; adjust.
MOV DX,34EH ;Display at Row 2; Col. 77.
MOV CX,3 ;Three bytes to write.
MOV BL,ATTRIBUTE ;Use background attribute.
CALL DIVIDE ;Display the number.
MOV DX,BOX_TOP + 103H ;Point to inside of info box.
MOV AL,EDIT_CHAR ;Retrieve character.
CALL WRITE_CHAR ;Display it.
ADD DL,7 ;Move to end of number col.
MOV CX,3 ;Three bytes to write.
CALL DIVIDE ;Display the number.
MOV BP,TEMPLATE_TOP ;Display template character.
MOV SI,OFFSET TEMPLATE_FONT
CALL UPDATE_FONT
MOV BP,EDIT_TOP ;Display edit character.
MOV SI,OFFSET EDIT_FONT
UPDATE_FONT: CALL CHAR_START ;Retrieve index to character.
NEXT_LINE: LODSB ;Get a byte.
MOV AH,AL ;Store in AH.
MOV DI,AX ;Store in DI.
PUSH CX ;Preserve bytes/char.
MOV CX,8 ;Eight bits/byte.
MOV DX,BP ;Top left of font display.
NEXT_PIXEL: RCL DI,1 ;Get a bit.
MOV AL,PIXEL_ON ;Assume it's on.
JC DISPLAY_IT ;Did bit end up in carry flag?
MOV AL,PIXEL_OFF ;If no, guessed wrong; pixel off.
DISPLAY_IT: CALL WRITE_PIXEL ;Display the pixel.
LOOP NEXT_PIXEL ;Do all 8 pixels.
ADD BP,100H ;Next display row.
POP CX ;Retrieve bytes/char.
LOOP NEXT_LINE ;Do all rows.
RET
;---------------------------;
; INPUT ;
; Entry point = DIVIDE. ;
; AL = Number to display. ;
; BL = Attribute. ;
; CX = Places to display. ;
; DX = Cursor position. ;
;---------------------------;
NEXT_COUNT: MOV AH,SPACE ;Assume zero.
OR AL,AL ;Is it a zero?
JZ ASCII ;If yes, display space instead.
DIVIDE: MOV BH,10 ;Divisor of ten.
XOR AH,AH ;Zero in high half.
DIV BH ;Divide by ten.
ADD AH,"0" ;Convert to ASCII.
ASCII: XCHG AL,AH ;Remainder in AL.
CALL WRITE_CHAR ;Display it.
XCHG AL,AH ;Back to AH.
DEC DL ;Move back one column.
LOOP NEXT_COUNT ;Display all three bytes.
RET
;---------------------;
; INPUT ;
; AL = Character ;
; BL = Attribute ;
; AX, CX preserved. ;
;---------------------;
WRITE_CHAR: PUSH AX
PUSH CX
CALL SET_CURSOR
MOV CX,1
MOV AH,9 ;Write attribute/character.
INT 10H
POP CX
POP AX
RET
;------------------------------------------------------------------------------;
; The Ega/Vga registers are programmed to access segment A000h where the ;
; fonts are stored. The font is retrieved and registers reset back to normal. ;
;------------------------------------------------------------------------------;
RETRIEVE_FONT: MOV SI,OFFSET ACCESS_A000H ;Point to access parameters.
CALL SET_REGISTERS ;Set the registers.
MOV BX,POINTS ;Retrieve bytes/character.
MOV AX,0A000H ;Point to font segment.
MOV DS,AX
MOV DI,OFFSET EDIT_FONT ;Point to destination.
MOV BP,256 ;256 characters.
XOR DX,DX ;Source starting offset of zero.
NEXT_CHAR: MOV SI,DX ;Point to source.
MOV CX,BX ;Bytes/character.
REP MOVSB ;Retrieve the bytes.
ADD DX,20H ;Next character two paragraphs.
DEC BP ;Do all 256 characters.
JNZ NEXT_CHAR
PUSH CS ;Restore data segment.
POP DS
MOV SI,OFFSET EDIT_FONT ;Copy the edit font to template.
MOV DI,OFFSET TEMPLATE_FONT
MOV CX,MAX_POINTS * 256 / 2
REP MOVSW
MOV SI,OFFSET PROTECT_A000H ;Point to normal parameters.
SET_REGISTERS: MOV CX,2 ;Two sequencer registers.
MOV DX,3C4H ;Indexing register.
CALL NEXT_REGISTER
MOV CX,3 ;Three graphics controller regs.
MOV DL,0CEH ;Indexing registers.
NEXT_REGISTER: LODSB ;Get index.
OUT DX,AL
INC DX
LODSB ;Get value.
OUT DX,AL
DEC DX
LOOP NEXT_REGISTER
RET
;-----------------------------------------------------;
; Similar to RETRIEVE_FONT procedure except character ;
; is uploaded instead of entire font down loaded. ;
;-----------------------------------------------------;
LOAD_CHAR: MOV SI,OFFSET ACCESS_A000H
CLI
CALL SET_REGISTERS
MOV SI,OFFSET EDIT_FONT ;Point to character
CALL CHAR_START ; to upload.
PUSH CX ;Preserve bytes/char.
MOV CL,5 ;32 bytes record for A000h font.
SHL AX,CL ;Index to appropriate character.
MOV DI,AX
POP CX
MOV AX,0A000H ;Point to font segment.
MOV ES,AX
REP MOVSB ;Upload the bytes.
PUSH CS ;Restore extra segment.
POP ES
MOV SI,OFFSET PROTECT_A000H
CALL SET_REGISTERS
STI
MOV MODIFY_FLAG,1 ;Note that font modified.
RET
;--------------------------------;
SET_CURSOR: PUSH AX
XOR BH,BH
MOV AH,2 ;Set cursor position.
INT 10H
POP AX
RET
;--------------------------------;
HIDE_CURSOR: MOV DH,ROWS
INC DH
XOR DL,DL ;Hide cursor one row below
CALL SET_CURSOR ; displayable rows.
RET
;--------------------------------;
CLEAR_MENU: MOV CX,100H ;Row 1; column zero.
MOV DX,34FH ;Row 3; column 79.
JMP SHORT SCROLL
CLS: XOR CX,CX ;Row zero; column zero.
MOV DH,ROWS ;Rows.
MOV DL,79 ;Column 79.
SCROLL: MOV BH,7 ;Attribute.
MOV AX,600H ;Scroll window of active page.
INT 10H
XOR DX,DX
CALL SET_CURSOR
RET
;--------------------------------;
GET_KEY: XOR AH,AH
INT 16H
RET
;--------------------------------;
PRINT_STRING: MOV AH,9
INT 21H
RET
;--------------------------------;
DISP_FILENAME: MOV SI,FILENAME
JMP SHORT TTY_STRING
;-----------------;
DO_WRITE: CALL WRITE_TTY
TTY_STRING: LODSB
OR AL,AL
JNZ DO_WRITE
RET
;-----------------;
WRITE_TTY: MOV AH,0EH
INT 10H
RET
;--------------------------------;
DO_CHAR_ATTR: CALL WRITE_CHAR
INC DL
CHAR_ATTRIB: LODSB
OR AL,AL
JNZ DO_CHAR_ATTR
RET
;--------------------------------;
SETUP: CLI ;No interrupts.
CALL RETRIEVE_FONT ;Retrieve font.
STI ;Interrupts back on.
CMP BYTE PTR DS:[80H],0 ;Command line parameter?
JZ CK_MOUSE ;If no, skip to mouse.
CALL PARSE_FILE ;Else, parse the parameter.
CALL OPEN_FILE ;Try to open the file.
JC CREATE_PROMPT ;If not found, ask to create.
CALL READ_FILE ;Else, read the file.
JMP SHORT CK_MOUSE ;Done here.
CREATE_PROMPT: MOV SI,OFFSET CREATE_MSG ;Display create query.
CALL PROMPT
JZ CREATE ;If got thumbs up, create it.
JMP ERROR_EXIT ;Else, exit.
CREATE: CALL CREATE_FILE ;Create the file.
MOV DX,OFFSET FAILED_MSG ;If failed, exit with message.
JNC CK_MOUSE
JMP ERROR_MSG
CK_MOUSE: XOR AX,AX ;Mouse reset and status.
INT 33H
OR AX,AX ;Is mouse active?
JZ DISPLAY_HEAD ;If no, skip.
MOV MOUSE_FLAG,1 ;Else, flag.
DISPLAY_HEAD: CALL CLS ;Clear the screen.
DISPLAY_COPY: MOV SI,OFFSET COPYRIGHT ;Display copyright in
MOV BL,INVERSE ; inverse video.
CALL CHAR_ATTRIB
MOV DX,100H ;Row 1; column 0.
CALL SET_CURSOR
MOV DX,OFFSET MENU ;Display menu.
CALL PRINT_STRING
CMP FILE_FLAG,1 ;If filename, display it.
JNZ DISPLAY_MENU
CALL DISP_FILENAME
DISPLAY_MENU: MOV DX,200H ;Row 2; column 0.
CALL SET_CURSOR
MOV DX,OFFSET MENU1 ;Display more menu.
CALL PRINT_STRING
MOV SI,OFFSET MENU2
MOV BL,NORMAL
MOV DX,436H
CALL CHAR_ATTRIB
MOV DX,536H
CALL CHAR_ATTRIB
MOV DX,636H
CALL CHAR_ATTRIB
MOV SI,OFFSET CAPTIONS ;Display three captions.
MOV CX,3
NEXT_CAPTION: LODSW
MOV DX,AX ;Caption starting cursor pos.
NEXT_CAP: LODSB
CMP AL,0 ;End of string?
JZ END_CAPTION
CALL WRITE_CHAR ;Write the caption.
INC DH ;Next row.
JMP SHORT NEXT_CAP
END_CAPTION: LOOP NEXT_CAPTION ;Do all three captions.
MOV BL,ATTRIBUTE ;Background attribute.
MOV SI,OFFSET CURRENT_BOX ;Display char/ASCII box.
MOV DX,BOX_TOP ;Starting position.
MOV BP,3 ;Three rows.
NEXT_BOX: MOV CX,13 ;13 characters/row.
NEXT_BOX_CHAR: LODSB
CALL WRITE_CHAR
INC DL ;Next column.
LOOP NEXT_BOX_CHAR
MOV DL,LOW BOX_TOP ;Starting column.
INC DH ;Next row.
DEC BP
JNZ NEXT_BOX
MOV DX,CHAR_TOP ;Display character set.
XOR AL,AL ;Start with ASCII zero.
NEXT_SET: MOV CX,16 ;16 bytes/row.
NEXT_BYTE: CALL WRITE_CHAR
INC AL ;Next character.
JZ SETUP_END
INC DL ;Next row.
LOOP NEXT_BYTE
MOV DL,LOW CHAR_TOP ;Starting column.
INC DH
JMP NEXT_SET
SETUP_END: CALL DISPLAY_FONT ;Display the edit and template.
CALL UPDATE_CURSOR ;Display the cursor.
RET
;**************** FONTLOADER ****************;
; This is the code to load the font and ;
; is followed by the edit and template font ;
;********************************************;
LOADER LABEL BYTE
LOADER_OFFSET EQU 100H - LOADER
JMP BEGINNING
; DATA AREA
; ---------
DB CR,SPACE,SPACE,SPACE,CR,LF
PROGRAMMER2 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
SIGNATURE_LEN EQU $ - PROGRAMMER2
CRT_MODE DB ?
EDIT_CURSOR DW 102H
CHAR_CURSOR DW 401H
EDIT_CHAR DB 65
POINTS DW ?
EDIT_FLAG DB 1
; CODE AREA
; ---------
BEGINNING: MOV AX,500H ;Active page zero
INT 10H
MOV AH,0FH ;Current video state.
INT 10H
MOV DI,OFFSET CRT_MODE + LOADER_OFFSET ;Font CRT_MODE.
MOV AH,[DI]
CMP AL,AH ;Same mode?
JZ LOAD_FONT ;If yes, skip.
MOV AL,AH ;Else, change video mode.
XOR AH,AH
INT 10H
LOAD_FONT: MOV BP,OFFSET EDIT_FONT + LOADER_OFFSET
MOV DI,OFFSET POINTS + LOADER_OFFSET
MOV BH,[DI]
USER_LOAD: MOV CX,256
XOR DX,DX
XOR BL,BL
MOV AX,1110H ;User alpha load.
INT 10H
RET ;Terminate.
;--------------------------------;
EVEN
EDIT_FONT LABEL BYTE
TEMPLATE_FONT EQU EDIT_FONT + MAX_POINTS * 256
LOADER_END EQU TEMPLATE_FONT + MAX_POINTS * 256
LOADER_LENGTH EQU LOADER_END - LOADER
_TEXT ENDS
END START