mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 20:35:25 +00:00
4b9382ddbc
push
1315 lines
56 KiB
NASM
1315 lines
56 KiB
NASM
;----------------------------------------------------------------------
|
||
; 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
|
||
|