IMD 1.17: 1/01/1998 2:28:16 Source for 1.4A Video ROMS VTABLE A86.VIDEO A86 VIDEO A86 SXCODES MACSXASCII EQUSXBDOS EQUVID A86-VVARS A86 VTEST0 A86VIDPIP SUBVINIT A864VDISK A86VID BAK,VKEYS A86U !"#$%V TXT&VID SYM1'()*VID CMD%+,-VID LST./012345VID LST6789:;<=VID LST>?@ABCDEVID LSTFGHIJKLMVID LSTNOPQRSTUVID LSTVWXYZ[\]VID LST^_`abcdeVID LSTfghijklmVID LSTnV A86,opqV OBJ*rstV SYM1uvwxVSCREEN A86yz{|}~VSCREEN A86mNORMAL A86BRIGHT A86INVERSE A86UL A86GR CMDiGR BAK%GR C %CTEMP2 CTEMP1 VIDA A86+VID OBJ* cseg GCHAR_SET: db 000H,000H,000H,000H,000H,000H,000H,000H db 07EH,081H,0A5H,081H,0BDH,099H,081H,07EH db 07EH,0FFH,0DBH,0FFH,0C3H,0E7H,0FFH,07EH db 06CH,0FEH,0FEH,0FEH,07CH,038H,010H,000H db 010H,038H,07CH,0FEH,07CH,038H,010H,000H db 038H,07CH,038H,0FEH,0FEH,07CH,038H,07CH db 010H,010H,038H,07CH,0FEH,07CH,038H,07CH db 000H,000H,018H,03CH,03CH,018H,000H,000H db 0FFH,0FFH,0E7H,0C3H,0C3H,0E7H,0FFH,0FFH db 000H,03CH,066H,042H,042H,066H,03CH,000H db 0FFH,0C3H,099H,0BDH,0BDH,099H,0C3H,0FFH db 00FH,007H,00FH,07DH,0CCH,0CCH,0CCH,078H db 03CH,066H,066H,066H,03CH,018H,07EH,018H db 03FH,033H,03FH,030H,030H,070H,0F0H,0E0H db 07FH,063H,07FH,063H,063H,067H,0E6H,0C0H db 099H,05AH,03CH,0E7H,0E7H,03CH,05AH,099H db 080H,0E0H,0F8H,0FEH,0F8H,0E0H,080H,000H db 002H,00EH,03EH,0FEH,03EH,00EH,002H,000H db 018H,03CH,07EH,018H,018H,07EH,03CH,018H db 066H,066H,066H,066H,066H,000H,066H,000H db 07FH,0DBH,0DBH,07BH,01BH,01BH,01BH,000H db 03EH,063H,038H,06CH,06CH,03CH,0CCH,078H db 000H,000H,000H,000H,07EH,07EH,07EH,000H db 018H,03CH,07EH,018H,07EH,03CH,018H,0FFH db 018H,03CH,07EH,018H,018H,018H,018H,000H db 018H,018H,018H,018H,07EH,03CH,018H,000H db 000H,018H,00CH,0FEH,00CH,018H,000H,000H db 000H,030H,060H,0FEH,060H,030H,000H,000H db 000H,000H,0C0H,0C0H,0C0H,0FEH,000H,000H db 000H,024H,066H,0FFH,066H,024H,000H,000H db 000H,018H,03CH,07EH,0FFH,0FFH,000H,000H db 000H,0FFH,0FFH,07EH,03CH,018H,000H,000H db 000H,000H,000H,000H,000H,000H,000H,000H db 030H,078H,078H,030H,030H,000H,030H,000H db 06CH,06CH,06CH,000H,000H,000H,000H,000H db 06CH,06CH,0FEH,06CH,0FEH,06CH,06CH,000H db 030H,07CH,0C0H,078H,00CH,0F8H,030H,000H db 000H,0C6H,0CCH,018H,030H,066H,0C6H,000H db 038H,06CH,038H,076H,0DCH,0CCH,076H,000H db 060H,060H,0C0H,000H,000H,000H,000H,000H db 018H,030H,060H,060H,060H,030H,018H,000H db 060H,030H,018H,018H,018H,030H,060H,000H db 000H,066H,03CH,0FFH,03CH,066H,000H,000H db 000H,030H,030H,0FCH,030H,030H,000H,000H db 000H,000H,000H,000H,000H,030H,030H,060H db 000H,000H,000H,0FCH,000H,000H,000H,000H db 000H,000H,000H,000H,000H,030H,030H,000H db 006H,00CH,018H,030H,060H,0C0H,080H,000H db 07CH,0C6H,0CEH,0DEH,0F6H,0E6H,07CH,000H db 030H,070H,030H,030H,030H,030H,0FCH,000H db 078H,0CCH,00CH,038H,060H,0CCH,0FCH,000H db 078H,0CCH,00CH,038H,00CH,0CCH,078H,000H db 01CH,03CH,06CH,0CCH,0FEH,00CH,01EH,000H db 0FCH,0C0H,0F8H,00CH,00CH,0CCH,078H,000H db 038H,060H,0C0H,0F8H,0CCH,0CCH,078H,000H db 0FCH,0CCH,00CH,018H,030H,030H,030H,000H db 078H,0CCH,0CCH,078H,0CCH,0CCH,078H,000H db 078H,0CCH,0CCH,07CH,00CH,018H,070H,000H db 000H,030H,030H,000H,000H,030H,030H,000H db 000H,030H,030H,000H,000H,030H,030H,060H db 018H,030H,060H,0C0H,060H,030H,018H,000H db 000H,000H,0FCH,000H,000H,0FCH,000H,000H db 060H,030H,018H,00CH,018H,030H,060H,000H db 078H,0CCH,00CH,018H,030H,000H,030H,000H db 07CH,0C6H,0DEH,0DEH,0DEH,0C0H,078H,000H db 030H,078H,0CCH,0CCH,0FCH,0CCH,0CCH,000H db 0FCH,066H,066H,07CH,066H,066H,0FCH,000H db 03CH,066H,0C0H,0C0H,0C0H,066H,03CH,000H db 0F8H,06CH,066H,066H,066H,06CH,0F8H,000H db 0FEH,062H,068H,078H,068H,062H,0FEH,000H db 0FEH,062H,068H,078H,068H,060H,0F0H,000H db 03CH,066H,0C0H,0C0H,0CEH,066H,03EH,000H db 0CCH,0CCH,0CCH,0FCH,0CCH,0CCH,0CCH,000H db 078H,030H,030H,030H,030H,030H,078H,000H db 01EH,00CH,00CH,00CH,0CCH,0CCH,078H,000H db 0E6H,066H,06CH,078H,06CH,066H,0E6H,000H db 0F0H,060H,060H,060H,062H,066H,0FEH,000H db 0C6H,0EEH,0FEH,0FEH,0D6H,0C6H,0C6H,000H db 0C6H,0E6H,0F6H,0DEH,0CEH,0C6H,0C6H,000H db 038H,06CH,0C6H,0C6H,0C6H,06CH,038H,000H db 0FCH,066H,066H,07CH,060H,060H,0F0H,000H db 078H,0CCH,0CCH,0CCH,0DCH,078H,01CH,000H db 0FCH,066H,066H,07CH,06CH,066H,0E6H,000H db 078H,0CCH,0E0H,070H,01CH,0CCH,078H,000H db 0FCH,0B4H,030H,030H,030H,030H,078H,000H db 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0FCH,000H db 0CCH,0CCH,0CCH,0CCH,0CCH,078H,030H,000H db 0C6H,0C6H,0C6H,0D6H,0FEH,0EEH,0C6H,000H db 0C6H,0C6H,06CH,038H,038H,06CH,0C6H,000H db 0CCH,0CCH,0CCH,078H,030H,030H,078H,000H db 0FEH,0C6H,08CH,018H,032H,066H,0FEH,000H db 078H,060H,060H,060H,060H,060H,078H,000H db 0C0H,060H,030H,018H,00CH,006H,002H,000H db 078H,018H,018H,018H,018H,018H,078H,000H db 010H,038H,06CH,0C6H,000H,000H,000H,000H db 000H,000H,000H,000H,000H,000H,000H,0FFH db 030H,030H,018H,000H,000H,000H,000H,000H db 000H,000H,078H,00CH,07CH,0CCH,076H,000H db 0E0H,060H,060H,07CH,066H,066H,0DCH,000H db 000H,000H,078H,0CCH,0C0H,0CCH,078H,000H db 01CH,00CH,00CH,07CH,0CCH,0CCH,076H,000H db 000H,000H,078H,0CCH,0FCH,0C0H,078H,000H db 038H,06CH,060H,0F0H,060H,060H,0F0H,000H db 000H,000H,076H,0CCH,0CCH,07CH,00CH,0F8H db 0E0H,060H,06CH,076H,066H,066H,0E6H,000H db 030H,000H,070H,030H,030H,030H,078H,000H db 00CH,000H,00CH,00CH,00CH,0CCH,0CCH,078H db 0E0H,060H,066H,06CH,078H,06CH,0E6H,000H db 070H,030H,030H,030H,030H,030H,078H,000H db 000H,000H,0CCH,0FEH,0FEH,0D6H,0C6H,000H db 000H,000H,0F8H,0CCH,0CCH,0CCH,0CCH,000H db 000H,000H,078H,0CCH,0CCH,0CCH,078H,000H db 000H,000H,0DCH,066H,066H,07CH,060H,0F0H  db 000H,000H,076H,0CCH,0CCH,07CH,00CH,01EH db 000H,000H,0DCH,076H,066H,060H,0F0H,000H db 000H,000H,07CH,0C0H,078H,00CH,0F8H,000H db 010H,030H,07CH,030H,030H,034H,018H,000H db 000H,000H,0CCH,0CCH,0CCH,0CCH,076H,000H db 000H,000H,0CCH,0CCH,0CCH,078H,030H,000H db 000H,000H,0C6H,0D6H,0FEH,0FEH,06CH,000H db 000H,000H,0C6H,06CH,038H,06CH,0C6H,000H db 000H,000H,0CCH,0CCH,0CCH,07CH,00CH,0F8H db 000H,000H,0FCH,098H,030H,064H,0FCH,000H db 01CH,030H,030H,0E0H,030H,030H,01CH,000H db 018H,018H,018H,000H,018H,018H,018H,000H db 0E0H,030H,030H,01CH,030H,030H,0E3H,000H db 076H,0DCH,000H,000H,000H,000H,000H,000H db 000H,010H,038H,06CH,0C6H,0C6H,0FEH,000H  ;************************************************ ;* 04/08/85 * VIDEO .A86 * VERSION 1.1 * ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* Video Drivers * ;* * ;************************************************ ;********** HANDY SUBROUTINES *************** ;---- CASE: ;---- ;Multi-branch subroutine. Branch depends on the value ;of cl. SI points to table of branches. Each entry has ;a compare byte and subroutine address. If compare ;byte matches cl then that branch is taken. Last entry ;has compare byte 0, last branc address always taken. ;in cl = branch byte ; si = case table C_00: CMP CL,CASE_CODE[SI] JZ C_01 ADD SI,CASE_LEN CMP CASE_CODE[SI],0 JNZ C_00 C_01: JMP CASE_ROUTINE[SI] cdummy cseg common 'empty' ! org 0 CASE_CODE RB 1 CASE_ROUTINE RW 1 CASE_LEN EQU OFFSET $ cseg ;-------- V_COLUMN: ;-------- ;Compute offset from start of row to ax. ;in ax = screen position ;out dx = column offset PUSH AX SUB DX,DX DIV V_ROWSIZE POP AX RET ;------ V_ROW: ;------ ;Compute offset of start of row containing ax ;in ax = screen position ;out dx = column offset CALL V_COLUMN NEG DX ADD DX,AX RET ;------- V_ERASE: ;------- ;Erase a portion of the screen. ;in ax = from ; dx = to + 1 PUSHF CLD PUSH ES MOV CX,DX ;Bytes to clear. SUB CX,AX JCXZ VE_00 MOV ES,V_BUFFER ;Screen buffer MOV DI,AX MOV AL,' ' ;Fill character MOV AH,V_ATTRIBUTES SHR CX,1 TEST V_GRAPHIC,1 JZ VE_01 CALL GR_REP_STOSW JMPS VE_00 VE_01: REP STOSW ;Fill VE_00: POP ES POPF RET ;---------- V_LFSCROLL: ;---------- ;Scroll full screen. SUB DI,DI MOV SI,V_ROWSIZE MOV CX,V_SCRNSIZE SUB CX,SI ; JMP V_SCROLL ;-------- V_SCROLL: ;-------- ;Scroll a portion of the screen. ;in di = to ; si = from ; cx = number PUSHF CLD MOV AX,SI SUB AX,DI ;Number of bytes JZ VS_00 ;None? JNC VS_01 ;Backwards? NEG AX  STD DEC DI DEC SI VS_01: SHR CX,1 PUSH ES ;Save segments MOV ES,V_BUFFER ;Screen JCXZ VS_02 ;Any to move? TEST V_GRAPHIC,1 JZ VS_03 CALL GR_REP_MOVSW JMPS VS_02 VS_03: PUSH DS MOV DS,V_BUFFER REP MOVSW POP DS VS_02: MOV CX,AX ;Fill SHR CX,1 MOV AH,V_ATTRIBUTES MOV AL,' ' TEST V_GRAPHIC,1 JZ VS_04 CALL GR_REP_STOSW JMPS VS_05 VS_04: PUSH DS MOV DS,V_BUFFER REP STOSW POP DS ;Restore segments VS_05: POP ES VS_00: POPF ;and direction RET ;-------- V_SETCUR: ;-------- ;Set cursor position. ;in ax = requested cursor position ;out c set if bad cursor position request CMP AX,V_SCRNSIZE ;Off the screen? JNC VS_10 MOV V_CURSOR,AX ;Record position PUSH DX PUSH AX SHR AX,1 PUSH AX MOV DX,ADR_6845 ;Tell hardware MOV AL,14 OUT DX,AX POP AX MOV AH,AL MOV AL,15 OUT DX,AX POP AX POP DX STC VS_10: CMC RET ;******* ESCAPE FUNCITONS *********************** ;All esc_ routines are called with ;in ax = cursor position ;---------- ESC_CURPOS: ;---------- ;Set cursor position lead in. OR V_FLAGS,VF_ROW + VF_ESC RET ;------ ESC_UP: ;------ ;Move up one line. SUB AX,V_ROWSIZE JMP V_SETCUR ;-------- ESC_DOWN: ;-------- ;Move down one line. ADD AX,V_ROWSIZE JMP V_SETCUR ;-------- VC_BS: ESC_LEFT: ;-------- ;Back up one character. DEC AX DEC AX JMP V_SETCUR ;--------- ESC_RIGHT: ;--------- ;Move ahead one character. INC AX INC AX JMP V_SETCUR ;--------- ESC_ERASE: ;--------- ;Clear screen. SUB AX,AX MOV DX,V_SCRNSIZE JMP V_ERASE ;-------- ESC_HOME: ;-------- ;Put cursor at top left. SUB AX,AX JMP V_SETCUR ;--------- ESC_REVLF: ;--------- ;Move full screen down. SUB AX,V_ROWSIZE CALL V_SETCUR MOV AX,0 JC ESC_INSLINE RET ;----------- ESC_INSLINE: ;----------- ;Insert a line. CALL V_ROW MOV DI,V_SCRNSIZE MOV SI,DI SUB SI,V_ROWSIZE MOV CX,SI SUB CX,DX DEC DI DEC SI JMP V_SCROLL ;----------- ESC_DELLINE: ;----------- ;Delete a line. CALL V_ROW MOV DI,DX MOV SI,DI ADD SI,V_ROWSIZE MOV CX,V_SCRNSIZE SUB CX,SI JMP V_SCROLL ;------- ESC_EOS: ;------- ;Erase to end of screen. MOV DX,V_SCRNSIZE JMP V_ERASE ;------- ESC_EOL: ;------- ;Erase to end of line. CALL V_ROW ADD DX,V_ROWSIZE JMP V_ERASE ;------- ESC_BOS: ;------- ;Erase to beginning of screen. MOV DX,AX SUB AX,AX JMP V_ERASE ;------- ESC_BOL: ;------- ;Erase to beginning of line. CALL V_ROW XCHG AX,DX JMP V_ERASE ;------ ESC_EL: ;------ ;Erase line. CALL V_ROW MOV AX,DX ADD DX,V_ROWSIZE JMP V_ERASE ;---------- ESC_FG_ATT: ESC_BG_ATT: ;---------- ;Next byte is attribute. OR V_FLAGS,VF_ESC + VF_EXT MOV V_ESC_EXT,CL RET ;----- ESC_CURSOR_ON: ;----- MOV AX,0A0Bh MOV DX,ADR_6845 OUT DX,AX RET ;no SETCUR because cursor not moved ;----- ESC_CURSOR_OFF: ;----- MOV AX,0A2Bh MOV DX,ADR_6845 OUT DX,AX RET DSEG CUR_SAVE RW 1 CSEG ;----- ESC_CURSOR_SAVE: ;----- MOV CUR_SAVE,AX RET ;----- ESC_CURSOR_RESTORE: ;----- MOV AX,CUR_SAVE JMP V_SETCUR ;------- ESC_EXT: ;------- ;Multi-byte escape sequences. MOV CH,0F0H AND AL,0FH CMP V_ESC_EXT,'a' JZ EE_00 SLL AL,4 MOV CH,0FH EE_00: AND V_ATTRIBUTES,CH OR V_ATTRIBUTES,AL AND V_FLAGS,NOT ( VF_ESC + VF_EXT ) RET ;********* CONTROL CODES ************************* ;Always ;in ax = cursor position ;------ VC_ESC: ;------ ;Begin escape sequence. OR V_FLAGS,VF_ESC RET ;----- VC_CR: ;----- ;Back to start of line. CALL V_ROW MOV AX,DX JMP V_SETCUR ;----- VC_LF: ;----- ;Next line. Scroll sometimes. ADD AX,V_ROWSIZE CALL V_SETCUR JNC VL_00 CALL V_LFSCROLL VL_00: RET ;------ VC_BEL: ;------ ;Not currently implemented RET ;-------- VID_PUTC: ;-------- MOV AL,CL ;------- VID_PUT: ;------- ;Put character at cursor position. Update cursor ;position. ;in al ( or cl ) = character PUSH ES MOV DI,V_CURSOR ;Put character MOV ES,V_BUFFER MOV AH,V_ATTRIBUTES TEST V_GRAPHIC,1 JZ VP_02 CALL GR_PUT JMPS VP_03 VP_02: MOV ES:[DI],AX VP_03: MOV AX,DI ;New cursor position INC AX INC AX CALL V_SETCUR JNC VP_01 SUB AX,V_ROWSIZE ;Off screen CALL V_SETCUR ;Need scroll CALL V_LFSCROLL VP_01: POP ES RET ;------- V_INESC: ;------- ;Escape sequence handler. Character output is sent ;here if in escape sequnce. ;in al = next character in escape sequence TEST V_FLAGS,VF_ROW ;Getting row position? JZ VI_00 SUB AL,' ' ;Offset SUB AH,AH MUL V_ROWSIZE CALL V_SETCUR ;Set row, then look XOR V_FLAGS,VF_ROW+VF_COL ;for column RET VI_00: TEST V_FLAGS,VF_COL ;Looking for column? JZ VI_01 SUB AL,' ' ;Offset SUB AH,AH SHL AX,1 ADD AX,V_CURSOR ;New position XOR V_FLAGS,VF_ESC+VF_COL ;Exit esc mode JMP V_SETCUR VI_01: TEST V_FLAGS,VF_EXT JZ VI_02 CALL ESC_EXT JMPS VI_03 VI_02: XOR V_FLAGS,VF_ESC ;Other escape char MOV SI,OFFSET ESC_TABLE ;Search table MOV CL,AL MOV AX,V_CURSOR CALL CASE VI_03: RET ;--------- VIDEO_OUT: ;--------- ;Entry point for character output ;in al = char TEST V_FLAGS,VF_ESC ;In escape sequence? JZ VID_01 CALL V_INESC JMPS VID_00 VID_01: CMP AL,' ' ;Control character? JC VID_02 CALL VID_PUT ;In not put charater JMPS VID_00 VID_02: MOV SI,OFFSET CNTL_TABLE ;Else search MOV CL,AL ;control table codes MOV AX,V_CURSOR CALL CASE VID_00: RET ;--------- CNTL_TABLE RB 0 ;--------- ;Case table for special handling of control character ;inputs. DB CR ! DW VC_CR DB LF ! DW VC_LF DB BS ! DW VC_BS DB ESC ! DW VC_ESC DB BEL ! DW VC_BEL DB 0 ! DW VID_PUTC ;-------- ESC_TABLE RB 0 ;-------- ;Case table for escape sequences DB 'Y' ! DW ESC_CURPOS DB 'A' ! DW ESC_UP DB 'B' ! DW ESC_DOWN DB 'C' ! DW ESC_RIGHT DB 'D' ! DW ESC_LEFT DB 'E' ! DW ESC_ERASE DB 'H' ! DW ESC_HOME DB 'I' ! DW ESC_REVLF DB 'J' ! DW ESC_EOS DB 'K' ! DW ESC_EOL DB 'd' ! DW ESC_BOS DB 'l' ! DW ESC_EL DB 'o' ! DW ESC_BOL DB 'L' ! DW ESC_INSLINE DB 'M' ! DW ESC_DELLINE DB 'b' ! DW ESC_FG_ATT DB 'c' ! DW ESC_BG_ATT DB 'm' ! DW ESC_CURSOR_ON DB 'n' ! DW ESC_CURSOR_OFF DB 'j' ! DW ESC_CURSOR_SAVE DB 'k' ! DW ESC_CURSOR_RESTORE DB 0 ! DW VID_00 ;****** IBM ROM EMULATION ******************** CSEG ;Perhaps some other day READ_LPEN: ACT_DISP_PAGE: WRITE_DOT: READ_DOT: V_NULL: RET ;-------- SET_MODE: ;-------- ;Set up video for selected mode. ; 6845 is intialized ; screen is cleared ; cursor set to upper left corner ;in al = desired mode MOV CRT_MODE,AL ;Save mode MOV DL,MD_LEN ;Find mode data MUL DL ADD AX,OFFSET MODE_DATA MOV MD_PTR,AX MOV SI,AX MOV DX,03B4H ;Find 6845 TEST MODE_FLAGS[SI],MF_EXPANSION JZ SM_00 MOV DX,03D4H SM_00: MOV ADR_6845,DX PUSH ES ;Initialize 6845 SUB AX,AX ;for selected mode MOV ES,AX LES BX,ES:dword ptr vp6845 ADD BX,P6845_OFFSET[SI] SM_01: MOV AH,ES:[BX] OUT DX,AX INC BX INC AL CMP AL,P6845_LEN JNZ SM_01 ADD DX,4 MOV AX,CONTROL_REG[SI] OUT DX,AX MOV V_COLOR,AH ADD DX,2 IN AL,DX SUB AL,AL TEST MODE_FLAGS[SI],MF_GRAPHIC JZ SM_02 INC AL SM_02: MOV V_GRAPHIC,AL ;Graphics flag MOV AX,RAM_BASE[SI] MOV V_BUFFER,AX ;Screen buffer segment MOV AX,SCREEN_SIZE[SI] MOV V_SCRNSIZE,AX ;Screen size MOV AX,ROW_SIZE[SI] MOV V_ROWSIZE,AX ;Row size MOV V_CURSOR,0 ;Cursor position MOV V_FLAGS,0 ;Flags MOV AX,INIT_CHAR[SI] ;Clear character MOV V_ATTRIBUTES,AH MOV ES,V_BUFFER SUB DI,DI MOV CX,8000 ;Clear screen REP STOSW POP ES RET ;--------- SET_CTYPE: ;--------- ;Set cursor type ;in cx = cursor type MOV CURSOR_MODE,CX MOV DX,ADR_6845 MOV AL,10 MOV AH,CH OUT DX,AX INC AL MOV AH,CL OUT DX,AX RET ;-------- SET_CPOS: ;-------- ;Set cursor position ;in dx = cursor position (row/column) MOV CX,DX ;Convert to byte offset MOV AL,DH SUB AH,AH MUL V_ROWSIZE SUB CH,CH ADD AX,CX ADD AX,CX CALL V_SETCUR ;Then set RET ;----------- READ_CURSOR: ;----------- ;Return cursor type and position ;out cx = type ; dx = position MOV AX,V_CURSOR ;Convert positon to SUB DX,DX ;row/column DIV V_ROWSIZE SHR DX,1 MOV DH,AL MOV RDX[BP],DX ;Sneak return values MOV AX,CURSOR_MODE ;into stack for later MOV RCX[BP],AX ;pop. RET ;--------------- READ_AC_CURRENT: ;--------------- ;Return character at cursor position ;(text modes only) ;out ax = character PUSH ES MOV AX,V_BUFFER MOV ES,AX MOV SI,V_CURSOR MOV AX,ES:[SI] POP ES RET ;---------------- WRITE_AC_CURRENT: ;---------------- ;Write character / attribute at current cursor ;position. ;in al = character ; bl = attribute ; cx = number of copies ;WARNING: cx not checked. Large cx causes write to ; non-screen area. PUSH ES MOV DI,V_BUFFER MOV ES,DI MOV DI,V_CURSOR MOV AH,BL TEST V_GRAPHIC,1 JZ WC_00 CALL GR_REP_STOSW JMPS WC_01 WC_00: REP STOSW WC_01: POP ES RET ;--------------- WRITE_C_CURRENT: ;--------------- ;Write character at current cursor position ;position. ;in al = character ; cx = number of copies ;WARNING: cx not checked. Large cx causes write to ; non-screen area. PUSH ES MOV DI,V_BUFFER MOV ES,DI MOV DI,V_CURSOR WR_00: TEST V_GRAPHIC,1 JZ WR_01 CALL GR_PUT INC DI JMPS WR_02 WR_01: STOSB WR_02: INC DI LOOP WR_00 POP ES RET ;--------- SET_COLOR: ;--------- ;Set color pallette PUSH AX MOV AL,V_COLOR OR BH,BH JZ SC_20 AND AL,NOT 20H SLL BL,5 OR AL,BL JMPS SC_21 SC_20: AND AL,NOT 1FH OR AL,BL SC_21: MOV DX,ADR_6845 ADD DX,5 OUT DX,AL POP AX RET ;-------- POSITION: ;-------- ;Convert row/column location to byte offset. ;in ax = row / column ;out ax = byte offset PUSH DX PUSH AX MOV AL,AH SUB AH,AH MUL V_ROWSIZE POP DX SUB DH,DH SHL DX,1 ADD AX,DX POP DX RET ;--------- SCROLL_UP: ;--------- ;Scroll up entry. ;in al = number of lines (0=all) ; bh = fill attribute ; cx = upper left corner ; dx = lower right corner PUSH AX MOV AH,AL SUB AL,AL ADD AX,CX CALL POSITION MOV SI,AX MOV AX,CX CALL POSITION MOV DI,AX POP AX PUSHF CLD PUSH BX CALL SCROLL_1 JMP SCROLL_0 ;----------- SCROLL_DOWN: ;----------- ;Scroll down entry. ;in al = number of lines (0=all) ; bh = fill attribute ; cx = upper left corner ; dx = lower right corner PUSH AX MOV AH,AL NEG AH SUB AL,AL ADD AX,DX CALL POSITION MOV SI,AX MOV AX,DX CALL POSITION MOV DI,AX POP AX PUSHF STD PUSH BX CALL SCROLL_1 NEG BX ;Up and down meet here ; ax = rows to blank ; bx = bytes to skip per row ; cx = rows to copy ; dx = bytes to copy per row ; es:si = source ; ds:di = destination ; stack = fill attribute ; = flags ; = return SCROLL_0: PUSH AX MOV ES,V_BUFFER SAR DX,1 JCXZ SC_01 SC_00: PUSH CX MOV CX,DX TEST V_GRAPHIC,1 JZ SC_03 CALL GR_REP_MOVSW JMPS SC_04 SC_03: PUSH DS MOV DS,V_BUFFER REP MOVSW POP DS SC_04: ADD SI,BX ADD DI,BX POP CX LOOP SC_00 SC_01: POP CX POP AX MOV AL,' ' SC_02: PUSH CX MOV CX,DX TEST V_GRAPHIC,1 JZ SC_05 CALL GR_REP_STOSW JMPS SC_06 SC_05: REP STOSW SC_06: ADD SI,BX ADD DI,BX POP CX LOOP SC_02 POPF RET ;Handy subroutine for scrolling ;in: al = number of rows to scroll ; cx = upper left corner ; dx = lower right corner ;out: ax = number of rows to blank ; bx = bytes to skip per row ; cx = number of rows to copy ; dx = bytes to copy per row SCROLL_1: SUB DX,CX ADD DX,101H SUB AH,AH OR AL,AL JNZ SC_10 MOV AL,DH SC_10: SUB CX,CX XCHG CL,DH SUB CX,AX SHL DX,1 MOV BX,V_ROWSIZE SUB BX,DX RET ;--------- WRITE_TTY: ;--------- ;Make display look like serial terminal ;in al = char MOV SI,OFFSET TTY_TABLE MOV CL,AL MOV AX,V_CURSOR CALL CASE RET TTY_TABLE RB 0 DB CR ! DW VC_CR DB LF ! DW VC_LF DB BS ! DW VC_BS DB BEL ! DW V_NULL DB 0 ! DW VID_PUTC ;----------- VIDEO_STATE: ;----------- ;Return current video mode ;out al = mode ; ah = rowsize MOV AX,V_ROWSIZE SHR AL,1 MOV AH,AL MOV AL,CRT_MODE MOV RBX[BP],0 RET ;************************************************** ; GRAPHICS SUBROUTINES ;************************************************** ;------- GR_POSN: ;------- ;Convert DI from a character position ;to a graphic position ;in di = character position (byte offset) ;out di = graphic position ;WARNING: Presently 640x200 expansion slot mode only. PUSH AX PUSH DX MOV AX,DI SUB DX,DX DIV V_ROWSIZE SUB DI,DX SHL DI,1 SHR DX,1 ADD DI,DX POP DX POP AX RET ;------ GR_PUT: ;------ ;Put a character on the graphic screen ;Replaces MOV ES:[DI],AL charater instruction ;in al = character ; es:di = character position ;WARNING: Presently 640x200 expansion slot mode only. PUSH SI ;Don't change any PUSH DI ;registers PUSH AX PUSH BX PUSH CX PUSH DS CALL GR_POSN ;Get graphic byte MOV BX,V_ROWSIZE ;offset and offset shr bx,1 ;between graphic rows ;NOTE: offset between graphic rows depends on mode MOV CX,CS ;Get character MOV DS,CX MOV SI,OFFSET GCHAR_SET TEST AL,80H ;Extended character JZ GP_00 ;Set? SUB CX,CX MOV DS,CX LDS SI,DS:DWORD PTR VCHAR_SET GP_00: MOV CX,AX ;Here ds:si = char AND CX,7FH ;set base. SLL CX,3 ADD SI,CX ;index to char MOV CX,4 ;NOTE screen locations depend on mode. GP_01: MOV AX,DS:[SI] ;move to screen MOV ES:[DI],AL MOV ES:2000H[DI],AH ADD SI,2 ADD DI,BX LOOP GP_01 POP DS POP CX POP BX POP AX POP DI POP SI RET ;------------ GR_REP_STOSW: ;------------ ;Replaces REP STOSW character instruction ;in ax = character ; cx = number to draw ; di = character position PUSH DS MOV DS,DATASEG GS_01: CALL GR_PUT SCASW LOOP GS_01 POP DS RET ;-------- GR_MOVSW: ;-------- ;Replaces MOVSW character instruction ;in si = source character position ; di = destination character position ;WARNING: Presently 640x200 expansion slot mode only. PUSH DS PUSH DI PUSH SI PUSH CX PUSH BX XCHG DI,SI CALL GR_POSN XCHG DI,SI CALL GR_POSN ;NOTE offset between rows depends on mode MOV BX,V_ROWSIZE SHR BX,1 MOV CX,4 MOV AX,ES MOV DS,AX ;NOTE offset between even and odd rows depend on mode GM_00: MOV AL,[SI] MOV [DI],AL MOV AL,2000H[SI] MOV 2000H[DI],AL ADD DI,BX ADD SI,BX LOOP GM_00 POP BX POP CX POP SI POP DI CMPSW POP DS RET ;------------ GR_REP_MOVSW: ;------------ ;Replaces REP MOVSW character instruction ;in cx = number of characters to move ; si = source character position ; di = destination character position ;WARNING: Presently 640x200 expansion slot mode only. PUSH DS PUSH AX MOV DS,DATASEG GM_10: CALL GR_MOVSW LOOP GM_10 POP AX POP DS RET  ;********************************************************** ;*** *** ;*** NEW 80186 CODES *** ;*** *** ;********************************************************** ;Code macro definitions for 80168 instructions which are not ;on the 8086, but may be useful for this program. ; *** PUSH AND POP INSTRUCTIONS *** ; ================================= CODEMACRO PUSH IMM:DW DB 68H DW IMM ENDM CODEMACRO PUSH IMM:DB DB 6AH DB IMM ENDM CODEMACRO PUSHA DB 60H ENDM CODEMACRO POPA DB 61H ENDM ; *** MULTIPLY *** ; ================ CODEMACRO IMUL DST:RW,SRC:EW,IMM:DW DB 69H MODRM DST,SRC DW IMM ENDM CODEMACRO IMUL DST:RW,SRC:EW,IMM:DB DB 6BH MODRM DST,SRC DB IMM ENDM ; *** SHIFT BY COUNT INSTRUCTIONS *** ; =================================== CODEMACRO ROL DST:EB,COUNT:DB DB 0C0H MODRM 0,DST DB COUNT ENDM CODEMACRO ROR DST:EB,COUNT:DB DB 0C0H MODRM 1,DST DB COUNT ENDM CODEMACRO RCL DST:EB,COUNT:DB DB 0C0H MODRM 2,DST DB COUNT ENDM CODEMACRO RCR DST:EB,COUNT:DB DB 0C0H MODRM 3,DST DB COUNT ENDM CODEMACRO SLL DST:EB,COUNT:DB DB 0C0H MODRM 4,DST DB COUNT ENDM ;Assembler uses SHR and SHL as operators, and so does ;not allow them as code macro instructions. Use SLR ;and SLL (Shift Logical Right or Left) CODEMACRO SLR DST:EB,COUNT:DB DB 0C0H MODRM 5,DST DB COUNT ENDM CODEMACRO SAL DST:EB,COUNT:DB DB 0C0H MODRM 4,DST DB COUNT ENDM CODEMACRO SAR DST:EB,COUNT:DB DB 0C0H MODRM 7,DST DB COUNT ENDM CODEMACRO ROL DST:EW,COUNT:DB DB 0C1H MODRM 0,DST DB COUNT ENDM CODEMACRO ROR DST:EW,COUNT:DB DB 0C1H MODRM 1,DST DB COUNT ENDM CODEMACRO RCL DST:EW,COUNT:DB DB 0C1H MODRM 2,DST DB COUNT ENDM CODEMACRO RCR DST:EW,COUNT:DB DB 0C1H MODRM 3,DST DB COUNT ENDM CODEMACRO SLL DST:EW,COUNT:DB DB 0C1H MODRM 4,DST DB COUNT ENDM CODEMACRO SLR DST:EW,COUNT:DB DB 0C1H MODRM 5,DST DB COUNT ENDM CODEMACRO SAL DST:EW,COUNT:DB DB 0C1H MODRM 4,DST DB COUNT ENDM CODEMACRO SAR DST:EW,COUNT:DB DB 0C1H MODRM 7,DST DB COUNT ENDM ;***** STRING OUTPUT ***** CODEMACRO OUTSW DB 06FH ENDM CODEMACRO OUTSB DB 06EH ENDM  ;************************************************ ;* * ;* ASCII CODES * ;* * ;************************************************ nul equ 00h soh equ 01h stx equ 02h etx equ 03h eot equ 04h enq equ 05h ack equ 06h bel equ 07h bs equ 08h ht equ 09h lf equ 0ah vt equ 0bh ff equ 0ch cr equ 0dh so equ 0eh shi equ 0fh dle equ 10h dc1 equ 11h dc2 equ 12h dc3 equ 13h dc4 equ 14h nak equ 15h syn equ 16h etb equ 17h can equ 18h em equ 19h subb equ 1ah esc equ 1bh fs equ 1ch gs equ 1dh us equ 1fh del equ 7fh cntl equ -40h c_assign equ 149 c_attach equ 146 c_cattach equ 162 c_delimit equ 110 c_detach equ 147 c_get equ 153 c_mode equ 109 c_rawio equ 6 c_read equ 1 c_readstr equ 10 c_set equ 148 c_stat equ 11 c_write equ 2 c_writeblk equ 111 c_writestr equ 9 dev_poll equ 131 dev_setflag equ 133 dev_waitflag equ 132 drv_access equ 38 drv_allocvec equ 27 drv_allreset equ 13 drv_dpb equ 31 drv_flush equ 48 drv_free equ 39 drv_get equ 25 drv_getlabel equ 101 drv_loginvec equ 24 drv_reset equ 37 drv_rovec equ 29 drv_set equ 14 drv_setlabel equ 100 drv_setro equ 28 drv_space equ 46 f_attach equ 30 f_close equ 16 f_delete equ 19 f_dmaget equ 52 f_dmaoff equ 26 f_dmaseg equ 51 f_errmode equ 45 f_lock equ 42 f_make equ 22 f_multisec equ 44 f_open equ 15 f_parse equ 152 f_passwd equ 106 f_randrec equ 36 f_read equ 20 f_readrand equ 33 f_rename equ 23 f_sfirst equ 17 f_size equ 35 f_snext equ 18 f_timedate equ 102 f_truncate equ 99 f_unlock equ 43 f_usernum equ 32 f_write equ 21 f_writerand equ 34 f_writexfcb equ 103 f_writezf equ 40 l_attach equ 158 l_cattach equ 161 l_detach equ 159 l_get equ 164 l_set equ 160 l_write equ 5 l_writeblk equ 112 m_alloc equ 128 m_free equ 130 mc_abs equ 54 mc_allfree equ 58 mc_alloc equ 55 mc_allocabs equ 56 mc_free equ 57 p_abort equ 157 p_chain equ 47 p_cli equ 150 p_create equ 144 p_delay equ 141 p_dispatch equ 142 p_load equ 59 p_pdadr equ 156 p_priority equ 145 p_rpl equ 151 p_term equ 143 p_termcpm equ 0 q_cread equ 138 q_cwrite equ 140 q_delete equ 136 q_make equ 134 q_open equ 135 q_read equ 137 q_write equ 139 s_bdosver equ 12 s_bios equ 50 s_osver equ 163 s_serial equ 107 s_sysdat equ 154 t_get equ 105 t_seconds equ 155 t_set equ 104 _bdos equ 224 codemacro bdos fnum:db db 0B1h db fnum ;mov cl,fnum db 0CDH db 224 ;int _bdos endm ;1/24/85 ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* version 1.4A * ;* March 27, 1986 * ;************************************************ ; To assemble: ; RASM86 VID ; LINK86 VID ; ;1.4A - removed infinite retry loop in VINIT.A86 at KLP2 ; gal - 3/27/86 ; ;------------------- ; include files NOLIST include sxcodes.mac include sxascii.equ INCLUDE SXBDOS.EQU LIST INCLUDE VVARS.A86 ;------------------- ;---- notes -------- ;1/24/85 elh added raw_key keyboard interrupt ;------------------- cseg org 0 ;Video Board ID. Software can read this location to ;determine if video board can be used. First two bytes ;identify video board. Next two bytes are the version ;number. At offset 4 is an initialization entry point. DB 'VD' DW 1 WAKE_UP: CALL INIT RETF cseg ;Entry points to video routines. ;Entry is via a software interrupt. At boot a callf to ;wake_up setup interrupt vectors. Each entry is called ;with a function number in ah. Positive ah emulate ;ibm rom calls. Negative ah for Slicer additions ;Branch tables. ;Video (Int 10H ) VID_LOW: DW SET_MODE DW SET_CTYPE DW SET_CPOS DW READ_CURSOR DW READ_LPEN DW ACT_DISP_PAGE DW SCROLL_UP DW SCROLL_DOWN DW READ_AC_CURRENT DW WRITE_AC_CURRENT DW WRITE_C_CURRENT DW SET_COLOR DW WRITE_DOT DW READ_DOT DW WRITE_TTY DW VIDEO_STATE ; DW NO_OP ; DW FILL_WINDOW VID_LLIMIT EQU (OFFSET $ - OFFSET VID_LOW) / 2 VID_HIGH: DW VIDEO_OUT VID_HLIMIT EQU (OFFSET $ - OFFSET VID_HIGH) / 2 ;Disk ( Int 252 ) ;On the IBM PC this interrupt is at 13H. On the 80186 ;13H is reserved for hardware timer interrupt. So the ;Slicer re-routes disk interrupts to 252. DSK_LOW: DW DISK_RESET DW DISK_STATUS DW DISK_READ DW DISK_WRITE DW DISK_VERIFY DW DISK_FORMAT DSK_LLIMIT EQU (OFFSET $ - OFFSET DSK_LOW) / 2 DSK_HIGH: DSK_HLIMIT EQU (OFFSET $ - OFFSET DSK_HIGH) / 2 ;Keyboard ( int 16H ) KBD_LOW: DW KEY_IN DW KEY_STAT DW KEY_SHIFTS KBD_LLIMIT EQU (OFFSET $ - OFFSET KBD_LOW) / 2 KBD_HIGH: DW KEY_8 DW VPORTON DW VPORTOFF DW RAW_KEY KBD_HLIMIT EQU (OFFSET $ - OFFSET KBD_HIGH) / 2 ;Printer ( int 17H ) PRN_LOW: DW PRINTER_OUT DW PRINTER_INIT DW PRINTER_STAT PRN_LLIMIT EQU (OFFSET $ - OFFSET PRN_LOW) / 2 PRN_HIGH: PRN_HLIMIT EQU (OFFSET $ - OFFSET PRN_HIGH) / 2 ;Range checks are made for each interrupt. If ah ;holds a legal value then a jump to the common code ;at enter is made. This save registers, calls ;subroutine, restores registers then returns. ;Video ENTER10: PUSH SI CMP AH,VID_LLIMIT JNC ENTER10A MOV SI,OFFSET VID_LOW JMP ENTER ENTER10A: NOT AH CMP AH,VID_HLIMIT JNC NO_ENTRY MOV SI,OFFSET VID_HIGH JMP ENTER NO_ENTRY: POP SI NOT AH IRET ;Disk (looks like int. 13H but really int. 252 ) ENTER13: PUSH SI CMP AH,DSK_LLIMIT JNC ENTER13A MOV SI,OFFSET DSK_LOW JMP ENTER ENTER13A: NOT AH CMP AH,DSK_HLIMIT JNC NO_ENTRY MOV SI,OFFSET DSK_HIGH JMP ENTER ;Keyboard ENTER16: PUSH SI CMP AH,KBD_LLIMIT JNC ENTER16A MOV SI,OFFSET KBD_LOW JMP ENTER ENTER16A: NOT AH CMP AH,KBD_HLIMIT JNC NO_ENTRY MOV SI,OFFSET KBD_HIGH JMP ENTER ;Printer ENTER17: PUSH SI CMP AH,PRN_LLIMIT JNC ENTER17A MOV SI,OFFSET PRN_LOW JMP ENTER ENTER17A: NOT AH CMP AH,PRN_HLIMIT JNC NO_ENTRY MOV SI,OFFSET PRN_HIGH JMP ENTER ;----- ENTER: ;----- ;Common code for interrupt entry. ;in: ah = routine number (range already checked ) ; si = branch table ;For each subroutines ;in: ah, si = unknown( altered by enter) ; al, bx, cx, dx, di, es, ss = set by caller ; ( unaltered by enter ) ; bp = pointer to register save area (on stack) ; ds = Video board data segment ;out: ax, flags = returned to caller ; other registers = restored from stack. ;If it is necessary to return a value in a register ;other than ax and flags then the saved copy of that ;register on the stack should be altered. ;Flags are not saved so caution should be used when ;altering flags such as I and D. PUSH BP MOV BP,SP PUSH WORD PTR 8[BP] POPF PUSH DI PUSH DX PUSH CX PUSH BX MOV BL,AH SUB BH,BH SHL BX,1 ADD SI,BX POP BX PUSH BX PUSH DS PUSH ES MOV DS,DATASEG MOV BP,SP CALL CS:WORD PTR[SI] POP ES POP DS POP BX POP CX POP DX POP DI POP BP POP SI RETF 2 ;Offsets into stack (relative to bp) for orignal/ ;return register values. SDUMMY SSEG COMMON 'EMPTY' ! ORG 0 RES RW 1 RDS RW 1 RBX RW 1 RCX RW 1 RDX RW 1 RDI RW 1 RBP RW 1 RSI RW 1 CSEG WAIT EQU 1 ;---------------- ;Include files INCLUDE VIDEO.A86 INCLUDE VKEYS.A86 INCLUDE VDISK.A86 include Vinit.a86 include Vtable.a86 ;---------------- LSTOUT EQU 14 CSEG PRINTER_OUT: MOV BL,LSTOUT INT MONITOR RET PRINTER_INIT: PRINTER_STAT: MOV AH,0E0H RET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EEH MEMSIZE RW 1 CSEG MEM: PUSH DS MOV AX,0F800H MOV DS,AX MOV AX,MEMSIZE POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 410H EQUIP RW 1 CSEG EQUIPMENT: PUSH DS SUB AX,AX MOV DS,AX MOV AX,EQUIP POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EAH SECONDS RW 1 CSEG TIME_OF_DAY: PUSH DS CMP AH,1 MOV AX,0F800H MOV DS,AX MOV AX,SECONDS MOV DS,DATASEG JZ SET_TIME SUB AX,T_SECS MOV DX,18 MUL DX ADD AX,T_LOW XCHG AX,DX ADC AX,T_HIGH MOV CX,AX SUB AX,AX POP DS IRET SET_TIME: MOV T_SECS,AX MOV T_LOW,DX MOV T_HIGH,CX POP DS IRET  VSEG dseg common 'vseg' ! org 16000 V_BUFFER RW 1 ;Segment of screen image V_SCRNSIZE RW 1 ;Size of screen image V_ROWSIZE RW 1 ;Bytes per row V_CURSOR RW 1 ;Offset to current cursor pos V_FLAGS RB 1 ;Flags VF_ESC EQU 01H ;In escape sequence VF_ROW EQU 02H ;Looking for row number VF_COL EQU 04H ;Looking for column number VF_EXT EQU 08H ;Line buffered mode V_ATTRIBUTES RB 1 ;Character attribtue V_ESC_EXT RB 1 V_GRAPHIC RB 1 V_COLOR RB 1 ;****** IBM ROM EMULATION ******************** VSEG dseg common 'vseg' CRT_MODE RB 1 MD_PTR RW 1 ADR_6845 RW 1 CURSOR_MODE RW 1 vseg dseg common 'vseg' CONKEY RW 1 ;Last console input key. SHIFTS RB 1 ;Shift status, external keyboard ;Masks for shifts INSSTATE EQU 80H CAPSLOCK EQU 40H NUMLOCK EQU 20H SCROLLLOCK EQU 10H ALTERNATE EQU 08H CNTLSTATE EQU 04H LEFTSHIFT EQU 02H RIGHTSHIFT EQU 01H INSCODE EQU 82 VPORTSTATE RB 1 VSEG DSEG COMMON 'vseg' K_BUFSIZE EQU 50H KBD_DATA RB 0 K_FLAG RB 1 ;dev flag num, neg = no flag K_INDEX RW 1 ;index into buffer K_BUFFER RB 50 ;buf start, length will vary LASTKEY RW 1 VSEG DSEG COMMON 'vseg' I_FLAGS RB 30 WAITING EQU 1 T_SECS RW 1 T_HIGH RW 1 T_LOW RW 1  ESC EQU 1BH SCROLL_UP: MOV AH,6 MOV AL,1 MOV CX,101H MOV DX,0830H MOV BH,7 INT 10H INT 3 NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP SCROLL_DOWN: MOV AH,7 MOV AL,1 MOV CX,101H MOV DX,0830H MOV BH,7 INT 10H INT 3 NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP SET_FG_ATT: MOV AL,ESC MOV AH,-1 INT 10H MOV AL,'a' MOV AH,-1 INT 10H MOV AL,7 MOV AH,-1 INT 10H INT 3 NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP SET_BG_ATT: MOV AL,ESC MOV AH,-1 INT 10H MOV AL,'b' MOV AH,-1 INT 10H MOV AL,8 MOV AH,-1 INT 10H INT 3 NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP ! NOP PIP $1SXCODES.MAC$2 PIP $1SXASCII.EQU$2 PIP $1SXBDOS.EQU$2 PIP $1VID.A86$2 PIP $1VVARS.A86$2 PIP $1VIDEO.A86$2 PIP $1VKEYS.A86$2 PIP $1VDISK.A86$2 PIP $1VINIT.A86$2 PIP $1VTABLE.A86$2 PIP $1VIDPIP.SUB$2  ;************************************************ ;* 07/18/85 * VINIT .A86 * VERSION 1.2 * ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* Initialization * ;* * ;************************************************ ;1.1 original version - 3/28/85 ;1.2 additional retries added to successfully initialize keyboard - 7/18/85 DSEG TRIES DW 1 ;NUMBER OF RESET TRIES ; CSEG INIT: PUSH ES PUSH DS MOV AX,CS MOV DS,AX MOV ES,DATASEG MOV DX,300H MOV AL,0F7H ;Initialize VPORT OUT DX,AL ;(shared by video and MOV ES:VPORTSTATE,AL ;keyboard). MOV DX,3D8H MOV AL,2DH OUT DX,AL INC DX SUB AL,AL OUT DX,AL MOV DX,3B4H MOV ES:ADR_6845,DX ;Set 6845 location MOV ES:CURSOR_MODE,0B0CH ;And cursor MOV DI,OFFSET I_FLAGS ;Clear int. flags MOV CX,30 SUB AX,AX REP STOSB MOV DS,DATASEG MOV T_SECS,0 ;Time = 0 MOV T_HIGH,0 MOV T_LOW,0 MOV SHIFTS,0 ;No shift keys active MOV CONKEY,-1 ;No key waiting MOV K_INDEX,0 ;Empty input buffer MOV K_FLAG,0DH+5 ;Keyboard interrupt flag MOV LASTKEY,-1 CALL KBD_INIT ;Look for keyboard OR AL,VID_ACTIVE ;Return value MOV AH,VPORTSTATE PUSH AX SUB AX,AX MOV ES,AX ;Setup IBM like MOV VXINT,OFFSET XINT_SERV ;int. vectors MOV VXINT+2,CS MOV VINT10,OFFSET ENTER10 MOV VINT10+2,CS MOV VINT16,OFFSET ENTER16 MOV VINT16+2,CS MOV VDSKINT,OFFSET ENTER13 MOV VDSKINT+2,CS MOV VP6845,OFFSET P6845 MOV VP6845+2,CS MOV VINT17,OFFSET ENTER17 MOV VINT17+2,CS MOV VINT12,OFFSET MEM MOV VINT12+2,CS MOV VINT11,OFFSET EQUIPMENT MOV VINT11+2,CS MOV VTIME,OFFSET TIME_OF_DAY MOV VTIME+2,CS MOV ES:EQUIP,40FEH MOV AX,DATASEG MOV ES,AX MOV DS,AX MOV AX,7 ;Set screen mode 7 CALL SET_MODE POP AX POP DS POP ES RET DATASEG DW 0B000H ;Tables for prgramming the 6845. p6845 db 038h,028h,02dh,00ah,01fh,006h,019h db 01ch,002h,007h,006h,007h db 0,0,0,0 p6845_len equ OFFSET $ - p6845 db 071h,050h,05ah,00ah,01fh,006h,019h db 01ch,002h,007h,006h,007h db 0,0,0,0 db 038h,028h,02dh,00ah,07fh,006h,064h db 070h,002h,001h,006h,007h db 0,0,0,0 db 061h,050h,052h,00fh,019h,006h,019h db 019h,002h,00dh,00bh,00ch db 0ffh,0ffh,0,0 ;Mode parameters CDUMMY CSEG COMMON 'empty' ! ORG 0 MODE_FLAGS RB 1 ;Flags MF_EXPANSION EQU 1 ; On expansion slot MF_GRAPHIC EQU 2 ; In graphics mode P6845_OFFSET RW 1 ;Select one of the ; above tables CONTROL_REG RW 1 ;Initial 6845 control/ ; color register value ROW_SIZE RW 1 ;Row size SCREEN_SIZE RW 1 ;Screen size ;NOTE row_size, screen_size are in bytes for character ; modes and 'bytes if this were a character mode' for ; graphic modes. NUM_PAGES RB 1 INIT_CHAR RW 1 ;Clear screen character RAM_BASE RW 1 ;Screen segment MD_LEN EQU OFFSET $ CSEG MODE_DATA RW 0 ;Mode 0 DB 01H ;Flags DW 0*P6845_LEN DB 02CH ;Control register DB 0 ;Color register DW 80 ;Row size DW 2000 ;Screen size DB 8 ;Number of pages DW 0720H ;Initial character DW 0B800H ;RAM base segment ;Mode 1 DB 01H ;Flags DW 0*P6845_LEN DB 028H ;Control register DB 0 ;Color register DW 80 ;Row size DW 2000 ;Screen size DB 8 ;Number of pages DW 0720H ;Initial character DW 0B800H ;RAM base segment ;Mode 2 DB 01H ;Flags DW 1*P6845_LEN DB 02DH ;Control register DB 0 ;Color register DW 160 ;Row size DW 4000 ;Screen size DB 4 ;Number of pages DW 0720H ;Initial character DW 0B800H ;RAM base segment ;Mode 3 DB 01H ;Flags DW 1*P6845_LEN DB 029H ;Control register DB 0 ;Color register DW 160 ;Row size DW 4000 ;Screen size DB 4 ;Number of pages DW 0720H ;Initial character DW 0B800H ;RAM base segment ;Mode 4 DB 03H ;Flags DW 2*P6845_LEN DB 02AH ;Control register DB 0 ;Color register DW 80 ;Row size DW 2000 ;Screen size DB 1 ;Number of pages DW 0000H ;Initial character DW 0B800H ;RAM base segment ;Mode 5 DB 03H ;Flags DW 2*P6845_LEN DB 02EH ;Control register DB 0 ;Color register DW 80 ;Row size DW 2000 ;Screen size DB 1 ;Number of pages DW 0000H ;Initial character DW 0B800H ;RAM base segment ;Mode 6 DB 03H ;Flags DW 2*P6845_LEN DB 01EH ;Control register DB 7 ;Color register DW 160 ;Row size DW 4000 ;Screen size DB 1 ;Number of pages DW 0000H ;Initial character DW 0B800H ;RAM base segment ;Mode 7 DB 00H ;Flags DW 3*P6845_LEN DB 02CH ;Control register DB 7 ;Color register DW 160 ;Row size DW 4000 ;Screen size DB 4 ;Number of pages DW 0720H ;Initial character DW 0B000H ;RAM base segment VID_ACTIVE EQU 2 KBD_ACTIVE EQU 1 ;-------- KBD_INIT: ;-------- ;Keyboard interrupt set up. MOV TRIES,2 ;NUMBER OF KBD RESET TRIES INIT1: MOV DX,IPC+INT2 ;Level trig. interrupt MOV AX,1FH OUT DX,AX MOV AL,KBCLOCK+KBENABLE CALL VPORTOFF MOV AL,KBENABLE CALL VPORTON MOV CH,80 KLP0: LOOP KLP0 MOV AL,KBCLOCK+KBENABLE CALL VPORTON MOV DX,IPC+INTREQ KLP1: IN AX,DX ;Wait for int attempt TEST AL,40H LOOPZ KLP1 JNZ KLP2 ;interrupt received, continue SUB TRIES,1 ;try again if no interrupt JZ NOKEY JMP INIT1 KLP2: MOV TRIES,5 ;reset number of tries KLP8: MOV DX,KBD IN AL,DX CMP AL,0AAH ;look for keyboard response JZ TRYOK ;received SUB TRIES,1 ;no - try again JZ NOKEY ;reset keyboard JMP KLP8 TRYOK: MOV AL,KBENABLE CALL VPORTOFF MOV AL,KBENABLE CALL VPORTON PUSH ES ;Set interrupt vector SUB AX,AX MOV ES,AX MOV VINT2,OFFSET I_KEYBOARD MOV VINT2+2,CS POP ES MOV DX,IPC+INT2 ;And int. controller MOV AX,17H OUT DX,AX MOV AX,KBD_ACTIVE RET NOKEY: SUB AX,AX RET VPORT EQU 300H KBD EQU 300H KBENABLE EQU 80H KBCLOCK EQU 40H ;80186 internal addresses IPC EQU -100H ;Integrated peripherials cntl base INT2 EQU 3CH INTREQ EQU 2EH  EOI EQU 22H XINT EQU 255 DSKINT EQU 252 ;********************* ; INTERRUPT VECTORS ;********************* edummy eseg common 'empty' ORG 14*4 VINT2 RW 2 RW 2 VINT10 RW 2 VINT11 RW 2 VINT12 RW 2 RW 2 RW 2 RW 2 VINT16 RW 2 VINT17 RW 2 RW 2 RW 2 VTIME RW 2 org (01dh*4) vp6845 rw 2 rw 2 vchar_set rw 2 ORG XINT*4 VXINT RW 2 ORG DSKINT*4 VDSKINT RW 2  ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* Disk ROM Calls * ;* * ;************************************************ ;IBM rom disk calls emulation ;Slicer monitor definitions DUMMY DSEG COMMON 'EMPTY' ORG 84F3H DSKSEG RW 1 ;Tranfer Segment DSKMEM RW 1 ;Transfer Offset DSKNUM RB 1 ;Disk number DSKTRACK RW 1 ;Track number DSKSECTOR RB 1 ;Sector num. (bit 7 = side 2) MONITOR EQU 251 ;Monitor entry interrupt READ EQU 8 ;Read sector function number WRITE EQU 9 ;Write sector function number CSEG ;Null operation. ;out ax = 0; ; nc DISK_RESET: DISK_STATUS: DISK_NULL: SUB AX,AX RET ;----------- DISK_FORMAT: ;----------- ;Format track. ;Not implemented. Does verify so error is returned ;unless track is already formatted. MOV CL,1 MOV AL,9 ;----------- DISK_VERIFY: ;----------- ;Verify sector. ;Sectors are read into ROM area. MOV DI,0F800H MOV ES,DI MOV BX,0 ;--------- DISK_READ: ;--------- ;Read sector(s) MOV SI,READ JMP DISK_OP ;---------- DISK_WRITE: ;---------- ;Write sector(s) MOV SI,WRITE ;------- DISK_OP: ;------- ;Common code for reads and writes. MOV DI,0F800H ;Monitor variables MOV DS,DI MOV DSKMEM,BX ;Set disk parameters MOV DSKSEG,ES MOV DSKNUM,DL SHL DL,1 ;Side is hidden in SHR DH,1 ;Sector number RCR CL,1 MOV DSKSECTOR,CL MOV CL,CH SUB CH,CH MOV DSKTRACK,CX MOV CL,AL D_LP: MOV BX,SI ;Call monitor INT MONITOR JNZ D_ERR ADD DSKMEM,512 ;Next sector INC DSKSECTOR LOOP D_LP D_ERR: MOV AH,AL CMP AH,1 ;Set carry by error CMC ;code. RET ;Notes ; Reads / Writes assume IBM type floppies ; 5-1/4", 512 byte sectors. ; These routines should not be used with other formats ; Also it is assumed that the monitor has been set ; up for this disk format. ; Error codes returned are 1797 codes, not nec. ;1/24/85 ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* * ;************************************************ ; To assemble: ; RASM86 VID ; LINK86 VID ;------------------- ; include files NOLIST include sxcodes.mac include sxascii.equ INCLUDE SXBDOS.EQU LIST INCLUDE VVARS.A86 ;------------------- ;---- notes -------- ;1/24/85 elh added raw_key keyboard interrupt ;------------------- cseg org 0 ;Video Board ID. Software can read this location to ;determine if video board can be used. First two bytes ;identify video board. Next two bytes are the version ;number. At offset 4 is an initialization entry point. DB 'VD' DW 1 WAKE_UP: CALL INIT RETF cseg ;Entry points to video routines. ;Entry is via a software interrupt. At boot a callf to ;wake_up setup interrupt vectors. Each entry is called ;with a function number in ah. Positive ah emulate ;ibm rom calls. Negative ah for Slicer additions ;Branch tables. ;Video (Int 10H ) VID_LOW: DW SET_MODE DW SET_CTYPE DW SET_CPOS DW READ_CURSOR DW READ_LPEN DW ACT_DISP_PAGE DW SCROLL_UP DW SCROLL_DOWN DW READ_AC_CURRENT DW WRITE_AC_CURRENT DW WRITE_C_CURRENT DW SET_COLOR DW WRITE_DOT DW READ_DOT DW WRITE_TTY DW VIDEO_STATE ; DW NO_OP ; DW FILL_WINDOW VID_LLIMIT EQU (OFFSET $ - OFFSET VID_LOW) / 2 VID_HIGH: DW VIDEO_OUT VID_HLIMIT EQU (OFFSET $ - OFFSET VID_HIGH) / 2 ;Disk ( Int 252 ) ;On the IBM PC this interrupt is at 13H. On the 80186 ;13H is reserved for hardware timer interrupt. So the ;Slicer re-routes disk interrupts to 252. DSK_LOW: DW DISK_RESET DW DISK_STATUS DW DISK_READ DW DISK_WRITE DW DISK_VERIFY DW DISK_FORMAT DSK_LLIMIT EQU (OFFSET $ - OFFSET DSK_LOW) / 2 DSK_HIGH: DSK_HLIMIT EQU (OFFSET $ - OFFSET DSK_HIGH) / 2 ;Keyboard ( int 16H ) KBD_LOW: DW KEY_IN DW KEY_STAT DW KEY_SHIFTS KBD_LLIMIT EQU (OFFSET $ - OFFSET KBD_LOW) / 2 KBD_HIGH: DW KEY_8 DW VPORTON DW VPORTOFF DW RAW_KEY KBD_HLIMIT EQU (OFFSET $ - OFFSET KBD_HIGH) / 2 ;Printer ( int 17H ) PRN_LOW: DW PRINTER_OUT DW PRINTER_INIT DW PRINTER_STAT PRN_LLIMIT EQU (OFFSET $ - OFFSET PRN_LOW) / 2 PRN_HIGH: PRN_HLIMIT EQU (OFFSET $ - OFFSET PRN_HIGH) / 2 ;Range checks are made for each interrupt. If ah ;holds a legal value then a jump to the common code ;at enter is made. This save registers, calls ;subroutine, restores registers then returns. ;Video ENTER10: PUSH SI CMP AH,VID_LLIMIT JNC ENTER10A MOV SI,OFFSET VID_LOW JMP ENTER ENTER10A: NOT AH CMP AH,VID_HLIMIT JNC NO_ENTRY MOV SI,OFFSET VID_HIGH JMP ENTER NO_ENTRY: POP SI NOT AH IRET ;Disk (looks like int. 13H but really int. 252 ) ENTER13: PUSH SI CMP AH,DSK_LLIMIT JNC ENTER13A MOV SI,OFFSET DSK_LOW JMP ENTER ENTER13A: NOT AH CMP AH,DSK_HLIMIT JNC NO_ENTRY MOV SI,OFFSET DSK_HIGH JMP ENTER ;Keyboard ENTER16: PUSH SI CMP AH,KBD_LLIMIT JNC ENTER16A MOV SI,OFFSET KBD_LOW JMP ENTER ENTER16A: NOT AH CMP AH,KBD_HLIMIT JNC NO_ENTRY MOV SI,OFFSET KBD_HIGH JMP ENTER ;Printer ENTER17: PUSH SI CMP AH,PRN_LLIMIT JNC ENTER17A MOV SI,OFFSET PRN_LOW JMP ENTER ENTER17A: NOT AH CMP AH,PRN_HLIMIT JNC NO_ENTRY MOV SI,OFFSET PRN_HIGH JMP ENTER ;----- ENTER: ;----- ;Common code for interrupt entry. ;in: ah = routine number (range already checked ) ; si = branch table ;For each subroutines ;in: ah, si = unknown( altered by enter) ; al, bx, cx, dx, di, es, ss = set by caller ; ( unaltered by enter ) ; bp = pointer to register save area (on stack) ; ds = Video board data segment ;out: ax, flags = returned to caller ; other registers = restored from stack. ;If it is necessary to return a value in a register ;other than ax and flags then the saved copy of that ;register on the stack should be altered. ;Flags are not saved so caution should be used when ;altering flags such as I and D. PUSH BP MOV BP,SP PUSH WORD PTR 8[BP] POPF PUSH DI PUSH DX PUSH CX PUSH BX MOV BL,AH SUB BH,BH SHL BX,1 ADD SI,BX POP BX PUSH BX PUSH DS PUSH ES MOV DS,DATASEG MOV BP,SP CALL CS:WORD PTR[SI] POP ES POP DS POP BX POP CX POP DX POP DI POP BP POP SI RETF 2 ;Offsets into stack (relative to bp) for orignal/ ;return register values. SDUMMY SSEG COMMON 'EMPTY' ! ORG 0 RES RW 1 RDS RW 1 RBX RW 1 RCX RW 1 RDX RW 1 RDI RW 1 RBP RW 1 RSI RW 1 CSEG WAIT EQU 1 ;---------------- ;Include files INCLUDE VIDEO.A86 INCLUDE VKEYS.A86 INCLUDE VDISK.A86 include Vinit.a86 include Vtable.a86 ;---------------- LSTOUT EQU 14 CSEG PRINTER_OUT: MOV BL,LSTOUT INT MONITOR RET PRINTER_INIT: PRINTER_STAT: MOV AH,0E0H RET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EEH MEMSIZE RW 1 CSEG MEM: PUSH DS MOV AX,0F800H MOV DS,AX MOV AX,MEMSIZE POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 410H EQUIP RW 1 CSEG EQUIPMENT: PUSH DS SUB AX,AX MOV DS,AX MOV AX,EQUIP POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EAH SECONDS RW 1 CSEG TIME_OF_DAY: PUSH DS CMP AH,1 MOV AX,0F800H MOV DS,AX MOV AX,SECONDS MOV DS,DATASEG JZ SET_TIME SUB AX,T_SECS MOV DX,18 MUL DX ADD AX,T_LOW XCHG AX,DX ADC AX,T_HIGH MOV CX,AX SUB AX,AX POP DS IRET SET_TIME: MOV T_SECS,AX MOV T_LOW,DX MOV T_HIGH,CX POP DS IRET  ;************************************************ ;* 03/28/85 * VKEYS .A86 * VERSION 1.1 * ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* Keyboard * ;* * ;************************************************ CSEG ;------- KEYTABLE RB 0 ;------- ;Scan code translation table. ;Four entries for each character ; normal, shift, control, alternate ;Key decoding routine interpets this table as follows: ; 0 Normal extended code, or ASCII null. ; Return ah=scan code, al=0. ; 1-127 ASCII key code. ; Return ah=scan code, al=table value. ; 128-199 Modified extended code. ; Return ah=table value - 44, al=0. ; This is for things like shift-function ; key. Offset of 44 keeps these table ; values distinct from the ASCII codes. ; 200-255 Special handling. ; Table value is negative of index into ; special handling routines. DB 27,27,27,-1,'1!',-1,164 ;Keys 1,2 DB '2@',0,165,'3#',-1,166 ;3,4 DB '4$',-1,167,'5%',-1,168 ;5,6 DB '6^',30,169,'7&',-1,170 ;7,8 DB '8*',-1,171,'9(',-1,172 ;9,10 DB '0)',-1,173,'-_',31,174 ;11,12 DB '=+',-1,175,8,8,127,-1 ;13,14 DB 9,0,-1,-1,'qQ',17,0 ;15,16 DB 'wW',23,0,'eE',5,0,'rR',18,0 ;17,18,19 DB 'tT',20,0,'yY',25,0,'uU',21,0 ;20,21,22 DB 'iI',9,0,'oO',15,0,'pP',16,0 ;23,24,25 DB '[{',27,-1,']}',29,-1 ;26,27 DB 13,13,10,-1,-4,-4,-4,-4 ;28,29 DB 'aA',1,0,'sS',19,0,'dD',4,0 ;30,31,32 DB 'fF',6,0,'gG',7,0,'hH',8,0 ;33,34,35 DB 'jJ',10,0,'kK',11,0,'lL',12,0 ;36,37,38 DB ';:',-1,-1,39,'"',-1,-1 ;39,40 DB '`~',-1,-1,-3,-3,-3,-3 ;41,42 DB '\|',28,-1,'zZ',26,0,'xX',24,0 ;43,44,45 DB 'cC',3,0,'vV',22,0,'bB',2,0 ;46,47,48 DB 'nN',14,0,'mM',13,0,',<',-1,-1 ;49,50,51 DB '.>',-1,-1,'/?',-1,-1 ;52,53 DB -2,-2,-2,-2,'*',-10,158,-1 ;54,55 DB -5,-5,-5,-5,' ',-8,-8,-8,-8 ;56,57,58 DB 0,128,138,148,0,129,139,149 ;59,60 DB 0,130,140,150,0,131,141,151 ;61,62 DB 0,132,142,152,0,133,143,153 ;63,64 DB 0,134,144,154,0,135,145,155 ;65,66 DB 0,136,146,156,0,137,147,157 ;67,68 DB -7,-7,-11,-7,-6,-6,-12,-6 ;69,70 DB 0,'7',163,-1,0,'8',-1,-1 ;71,72 DB 0,'9',176,-1,'--',-1,-1 ;73,74 DB 0,'4',159,-1,-1,'5',-1,-1 ;75,76 DB 0,'6',160,-1,'++',-1,-1 ;77,78 DB 0,'1',161,-1,0,'2',-1,-1 ;79,80 DB 0,'3',162,-1,-9,'0',-1,-1 ;81,82 DB 0,'.',-13,-13 ;83 ;------- LOOK_UP: ;------- ;Scan code look up. ;in al = scan code ;out al = table look up value. ; cl = shift state SUB BX,BX ;bx = al * 4 = index SHL AL,1 MOV BL,AL SHL BX,1 MOV CL,SHIFTS ;Get shift states TEST CL,ALTERNATE ;Alt key pressed? JZ LU_01 ADD BL,3 JMPS LU_00 LU_01: TEST CL,CNTLSTATE ;Control key pressed? JZ LU_02 ADD BL,2 JMPS LU_00 LU_02: TEST CL,LEFTSHIFT+RIGHTSHIFT ;Shift? JZ LU_03 ADD BL,1 LU_03: TEST CL,NUMLOCK ;Num lock? JZ LU_00 CMP AL,142 ;and keypad key? JC LU_00 XOR BL,1 ;toggle shift LU_00: MOV AL,KEYTABLE-4[BX] RET ;-------- SPECIALS: ;-------- ;Table of subroutines for keys which require special ;handling. DW IGNORE DW RIGHTSIDE DW LEFTSIDE DW CONTROLKEY DW ALTKEY DW SCROLLKEY DW NUMKEY DW CAPSKEY DW INSKEY DW PRTSCRN DW PAUSE DW BREAK DW RESET ;--------- KEY_XLATE: ;--------- ;Translate scan code in al to action or return code. ;in al = scan code ;out ax = return code ; or if no return code ax = -1 MOV AH,AL ;Store scan code CALL LOOK_UP ;Table look up CMP AL,133 ;Ascii code or normal JC KX_00 ;scan code? CMP AL,200 ;Special handling? JNC SPECIAL SUB AL,44 ;or modified scan code AND AH,80H ;table offset = 44 OR AH,AL ;save open/close bit SUB AL,AL ;AH=code, AL=0 KX_00: TEST AH,80H ;Release? JNZ KX_01 ;if so ignore TEST CL,CAPSLOCK ;Check for case toggle JZ KX_02 CMP AL,'A' ;check for letter JC KX_02 CMP AL,'Z'+1 JC KX_03 CMP AL,'a' JC KX_02 CMP AL,'z'+1 JNC KX_02 KX_03: XOR AL,20H ;Flip case JMPS KX_02 KX_01: MOV AX,-1 ;-1 = no key KX_02: CMP AX,-1 ;z = no key RET  ;------- SPECIAL: ;------- ;Key just pressed requires special handling. ;(This is not really a subroutine, but an extension ;of key_xlate. Entry is only from a jump from ;key_xlate. All special handlers exit by jumping ;back into key_xlate.) ;in al = negative of special function number. ; cl = shift state NEG AL SHL AL,1 MOV BL,AL SUB BH,BH JMP SPECIALS-2[BX] ;------------------------- ;special function handlers ;------------------------- ;Some are not yet implemented. (Some never will be.) RESET: BREAK: PAUSE: PRTSCRN: IGNORE: JMP KX_01 ;ignore ;Most of these just keep track of shift state RIGHTSIDE: MOV CH,RIGHTSHIFT JMPS SETSHIFT LEFTSIDE: MOV CH,LEFTSHIFT JMPS SETSHIFT CONTROLKEY: MOV CH,CNTLSTATE JMPS SETSHIFT ALTKEY: MOV CH,ALTERNATE JMPS SETSHIFT SCROLLKEY: MOV CH,SCROLLLOCK JMPS TOGSHIFT NUMKEY: MOV CH,NUMLOCK JMPS TOGSHIFT CAPSKEY: MOV CH,CAPSLOCK JMPS TOGSHIFT INSKEY: MOV CH,INSSTATE JMPS TOGSHIFT ;Set shift bit by open/release of key. (For keys such ;as shift, which must be held down.) SETSHIFT: OR CL,CH TEST AH,80H JZ SS_00 JNZ SS_01 ;Toggle shift bit. (For lock type keys) TOGSHIFT: TEST AH,80H JNZ SS_00 ;Ignore release SS_01: XOR CL,CH SS_00: MOV SHIFTS,CL CMP AH,INSCODE ;Ins also returns a JNZ KX_01 ;code, others do not SUB AL,AL JMP KX_02 ;-------- KEY_SCAN: ;-------- ;Check keyboard buffer. ;Out: nz, ah=-1, al=keycode (if key is ready ) ; z, ah=0 ( if no key is ready) ;note: may be called with interrupts on or off. If ; interrupts are on, 'no key ready' means 'no ; key was ready when this routine was called'. ; If interrupts are off 'no key ready' means 'no ; key will be ready until interrupts are turned ; on'. PUSHF CLI SUB AX,AX ;prepare, no key CMP K_INDEX,0 ;Check for empty buf JZ KS_00 DEC AH MOV AL,K_BUFFER ;Grab character DEC K_INDEX JZ KS_00 ;Any other left PUSH ES ;in buffer. MOV CX,DS ;If so move them MOV ES,CX ;up. MOV DI,OFFSET K_BUFFER MOV SI,DI INC SI MOV CX,K_INDEX CLD REP MOVSB POP ES KS_00: POPF OR AH,AH RET ;--------- KEY_CHECK: ;--------- ;Check if key is ready. ;This gobbles up non-return key codes ( key releases, ;shifts ). This routine does not enable interrupts, ;see comment with key_scan. ;out ax = return code ; or if there is no return code ax = -1 KC_01: CALL KEY_SCAN ;Check buffer JZ KC_00 CALL KEY_XLATE ;Translate CMP AX,-1 ;If no return code JZ KC_01 ;try again. KC_00: RET ;-------- KEY_STAT: ;-------- ;PC like status call. Character codes are returned, ;but character is not used up. ;out ax = return code ; or if there is no return code ax = -1 MOV AX,LASTKEY CMP AX,-1 JNZ KS_10 CALL KEY_CHECK JZ KS_10 MOV LASTKEY,AX KS_10: RET ;------ KEY_IN: ;------ ;Yet another way to read keys. This one will not ;return until a valid return code is found. Waiting ;is done by flagwait interrupt. So interrupt may be ;intercepted to avoid a hard wait loop. KI_02: CALL KEY_STAT ;Key ready? JNZ KI_00 CLI ;Try again with CALL KEY_STAT ;interrupts off. JNZ KI_01 ;Still not ready? MOV DL,K_FLAG ;If not do flagwait MOV CL,DEV_WAITFLAG SUB DH,DH INT XINT STI JMPS KI_02 KI_01: STI ;Have key. KI_00: MOV LASTKEY,-1 ;Mark as used RET ;---------- KEY_SHIFTS: ;---------- ;PC like call to check shift status. MOV AL,SHIFTS RET ;----- KEY_8: ;----- ;Split up function keys for programs that can only ;handle 8 bit codes. CALL KEY_IN OR AL,AL ;Function key? JNZ K8_00 ;If so save key code MOV BYTE PTR LASTKEY,AH ;for next time K8_00: RET ;------- RAW_KEY: ;------- ;Read raw keyboard character ;out al = key code MOV DX,300H IN AL,DX PUSH AX MOV AL,KBENABLE ;Keyboard strobe CALL VPORTOFF MOV AL,KBENABLE CALL VPORTON MOV AX,14 ;Tell int. controller MOV DX,IPC+EOI ;I'm done OUT DX,AX POP AX RET ;---------- I_KEYBOARD: ;---------- ;Interrupt driven keyboard input service routine. ;Key is read from keyboard and put into buffer. If ;buffer is full, key is discarded. No decoding is ;done, raw scan code is buffered. If someone is ;waiting for this interrupt then the setflag interrupt ;is called. PUSH AX ;Save registers PUSH BX PUSH CX PUSH DX PUSH BP PUSH SI PUSH DI PUSH DS MOV DS,DATASEG ;Get scan code MOV DX,300H IN AL,DX MOV DI,K_INDEX ;Get buffer index CMP DI,K_BUFSIZE ;full? JNC IK_00 MOV K_BUFFER[DI],AL ;Stuff into buffer INC DI MOV K_INDEX,DI ;New index IK_00: MOV DL,K_FLAG ;Some one waiting? MOV CL,DEV_SETFLAG SUB DH,DH INT XINT IK_01: CALL RAW_KEY POP DS POP DI POP SI POP BP POP DX POP CX POP BX POP AX IRET ;Video port control. ;Vport has bits for both video and keyboard control. ;These routines can turn on/off selected bits on ;this port without disturbing the others. ;-------- VPORTOFF: ;-------- ;Turn off bits on vport. ;in al = bit mask NOT AL AND VPORTSTATE,AL JMPS VP_00 ;------- VPORTON: ;------- ;Turn no bits of vport. ;in al = bit mask OR VPORTSTATE,AL VP_00: MOV DX,VPORT MOV AL,VPORTSTATE OUT DX,AL RET ;--------- XINT_SERV: ;--------- ;Interrupt waiting bookkeeping ;Waiting for interrupts is done as follows: ; Interrupt service routine generates INT 255 with ; cx = 133 and dl = interrupt wait number. ; Routine waiting for an interrupt does an INT 255 ; cx = 132 and dl = interrupt wait number. INT 255 ; returns when interrupt occurs. ;This method helps separate the waiting and service ;routines. All communication between these routines ;are via INT 255. ;Also wait loops are not fixed in ROM. Someone could ;trap interrupt 255 and make better use of the cpu ;while waiting for an interrupt to occur. ;Presently only keyboard input uses this interrupt. ;Keyboard input uses wait flag #18. There is room ;for 30 flags. CMP CL,DEV_SETFLAG ;Setting flag? JNZ XI_01 CALL SET_FLAG JMPS XI_00 XI_01: CMP CL,DEV_WAITFLAG ;Waiting for flag? JNZ XI_02 CALL WAIT_FLAG XI_02: XI_00: IRET ;-------- SET_FLAG: ;-------- ;Set interrupt flag to show interrupt has occured. SUB AX,AX MOV DH,AL MOV BX,DX TEST I_FLAGS[BX],WAITING JNZ SF_00 DEC AX SF_00: AND I_FLAGS[BX],NOT WAITING SUB BX,BX RET ;--------- WAIT_FLAG: ;--------- ;Wait for interrupt to happen SUB AX,AX MOV DH,AL MOV BX,DX TEST I_FLAGS[BX],WAITING JNZ WF_01 OR I_FLAGS[BX],WAITING STI WF_00: TEST I_FLAGS[BX],WAITING JNZ WF_00 INC AX WF_01: STI DEC AX SUB BX,BX RET  ;-------- ESC_TABLE RB 0 ;-------- ;Case table for escape sequences DB 'Y' ! DW ESC_CURPOS DB 'A' ! DW ESC_UP DB 'B' ! DW ESC_DOWN DB 'C' ! DW ESC_RIGHT DB 'D' ! DW ESC_LEFT DB 'E' ! DW ESC_ERASE DB 'H' ! DW ESC_HOME DB 'I' ! DW ESC_REVLF DB 'J' ! DW ESC_EOS DB 'K' ! DW ESC_EOL DB 'd' ! DW ESC_BOS DB 'l' ! DW ESC_EL DB 'o' ! DW ESC_BOL DB 'L' ! DW ESC_INSLINE DB 'M' ! DW ESC_DELLINE DB 'b' ! DW ESC_FG_ATT DB 'c' ! DW ESC_BG_ATT DB 'm' ! DW ESC_CURSOR_ON DB 'n' ! DW ESC_CURSOR_OFF DB 'j' ! DW ESC_CURSOR_SAVE DB 'k' ! DW ESC_CURSOR_RESTORE DB 0 ! DW VID_00  0000 VARIABLES 3E90 ADR_6845 0000 CASE_CODE 0001 CASE_ROUTINE 0332 CNTL_TABLE 3E94 CONKEY 0003 CONTROL_REG 3E8D CRT_MODE 3E92 CURSOR_MODE 0000 CUR_SAVE 0AE9 DATASEG 84F5 DSKMEM 84F7 DSKNUM 84FA DSKSECTOR 84F3 DSKSEG 84F8 DSKTRACK 0410 EQUIP 0344 ESC_TABLE 000A INIT_CHAR 3ECF I_FLAGS 3E98 KBD_DATA 0642 KEYTABLE 3E9B K_BUFFER 3E98 K_FLAG 3E99 K_INDEX 3ECD LASTKEY 3E8E MD_PTR 84EE MEMSIZE 0B2B MODE_DATA 0000 MODE_FLAGS 0009 NUM_PAGES 0AEB P6845 0001 P6845_OFFSET 000C RAM_BASE 000C RBP 0004 RBX 0006 RCX 000A RDI 0002 RDS 0008 RDX 0000 RES 0005 ROW_SIZE 000E RSI 0007 SCREEN_SIZE 84EA SECONDS 3E96 SHIFTS 0002 TRIES 0574 TTY_TABLE 3EEF T_HIGH 3EF1 T_LOW 3EED T_SECS 007C VCHAR_SET 03F0 VDSKINT 0040 VINT10 0044 VINT11 0048 VINT12 0058 VINT16 005C VINT17 0038 VINT2 0074 VP6845 3E97 VPORTSTATE 0068 VTIME 03FC VXINT 3E89 V_ATTRIBUTES 3E80 V_BUFFER 3E8C V_COLOR 3E86 V_CURSOR 3E8A V_ESC_EXT 3E88 V_FLAGS 3E8B V_GRAPHIC 3E84 V_ROWSIZE 3E82 V_SCRNSIZE 0000 NUMBERS 0006 ACK 0008 ALTERNATE 0007 BEL 0008 BS 0018 CAN 0040 CAPSLOCK 0003 CASE_LEN FFC0 CNTL 0004 CNTLSTATE 000D CR 0095 C_ASSIGN 0092 C_ATTACH 00A2 C_CATTACH 006E C_DELIMIT 0093 C_DETACH 0099 C_GET 006D C_MODE 0006 C_RAWIO 0001 C_READ 000A C_READSTR 0094 C_SET 000B C_STAT 0002 C_WRITE 006F C_WRITEBLK 0009 C_WRITESTR 0011 DC1 0012 DC2 0013 DC3 0014 DC4 007F DEL 0083 DEV_POLL 0085 DEV_SETFLAG 0084 DEV_WAITFLAG 0010 DLE 0026 DRV_ACCESS 001B DRV_ALLOCVEC 000D DRV_ALLRESET 001F DRV_DPB 0030 DRV_FLUSH 0027 DRV_FREE 0019 DRV_GET 0065 DRV_GETLABEL 0018 DRV_LOGINVEC 0025 DRV_RESET 001D DRV_ROVEC 000E DRV_SET 0064 DRV_SETLABEL 001C DRV_SETRO 002E DRV_SPACE 00FC DSKINT 0000 DSK_HLIMIT 0006 DSK_LLIMIT 0019 EM 0005 ENQ 0022 EOI 0004 EOT 001B ESC 0017 ETB 0003 ETX 000C FF 001C FS 001E F_ATTACH 0010 F_CLOSE 0013 F_DELETE 0034 F_DMAGET 001A F_DMAOFF 0033 F_DMASEG 002D F_ERRMODE 002A F_LOCK 0016 F_MAKE 002C F_MULTISEC 000F F_OPEN 0098 F_PARSE 006A F_PASSWD 0024 F_RANDREC 0014 F_READ 0021 F_READRAND 0017 F_RENAME 0011 F_SFIRST 0023 F_SIZE 0012 F_SNEXT 0066 F_TIMEDATE 0063 F_TRUNCATE 002B F_UNLOCK 0020 F_USERNUM 0015 F_WRITE 0022 F_WRITERAND 0067 F_WRITEXFCB 0028 F_WRITEZF 001D GS 0009 HT 0052 INSCODE 0080 INSSTATE 003C INT2 002E INTREQ FF00 IPC 0040 KBCLOCK 0300 KBD 0001 KBD_ACTIVE 0004 KBD_HLIMIT 0003 KBD_LLIMIT 0080 KBENABLE 0050 K_BUFSIZE 0002 LEFTSHIFT 000A LF 000E LSTOUT 009E L_ATTACH 00A1 L_CATTACH 009F L_DETACH 00A4 L_GET 00A0 L_SET 0005 L_WRITE 0070 L_WRITEBLK 0036 MC_ABS 003A MC_ALLFREE 0037 MC_ALLOC 0038 MC_ALLOCABS 0039 MC_FREE 000E MD_LEN 0001 MF_EXPANSION 0002 MF_GRAPHIC 00FB MONITOR 0080 M_ALLOC 0082 M_FREE 0015 NAK 0000 NUL 0020 NUMLOCK 0010 P6845_LEN 0000 PRN_HLIMIT 0003 PRN_LLIMIT 009D P_ABORT 002F P_CHAIN 0096 P_CLI 0090 P_CREATE 008D P_DELAY 008E P_DISPATCH 003B P_LOAD 009C P_PDADR 0091 P_PRIORITY 0097 P_RPL 008F P_TERM 0000 P_TERMCPM 008A Q_CREAD 008C Q_CWRITE 0088 Q_DELETE 0086 Q_MAKE 0087 Q_OPEN 0089 Q_READ 008B Q_WRITE 0008 READ 0001 RIGHTSHIFT 0010 SCROLLLOCK 000F SHI 000E SO 0001 SOH 0002 STX 001A SUBB 0016 SYN 000C S_BDOSVER 0032 S_BIOS 00A3 S_OSVER 006B S_SERIAL 009A S_SYSDAT 0069 T_GET 009B T_SECONDS 0068 T_SET 001F US 0004 VF_COL 0001 VF_ESC 0008 VF_EXT 0002 VF_ROW 0002 VID_ACTIVE 0001 VID_HLIMIT 0010 VID_LLIMIT 0300 VPORT 000B VT 0001 WAIT 0001 WAITING 0009 WRITE 00FF XINT 00E0 _BDOS 0000 LABELS 0386 ACT_DISP_PAGE 0839 ALTKEY 082A BREAK 0845 CAPSKEY 00DE CASE 0835 CONTROLKEY 00DE C_00 00EC C_01 0998 DISK_FORMAT 0995 DISK_NULL 09AD DISK_OP 09A4 DISK_READ 0995 DISK_RESET 0995 DISK_STATUS 099C DISK_VERIFY 09AA DISK_WRITE 0036 DSK_HIGH 002A DSK_LOW 09E4 D_ERR 09D2 D_LP 0266 EE_00 00B2 ENTER 004A ENTER10 0056 ENTER10A 0067 ENTER13 0073 ENTER13A 0080 ENTER16 008C ENTER16A 0099 ENTER17 00A5 ENTER17A 1024 EQUIPMENT 0230 ESC_BG_ATT 021D ESC_BOL 0216 ESC_BOS 01A2 ESC_CURPOS 0243 ESC_CURSOR_OFF 023A ESC_CURSOR_ON 0250 ESC_CURSOR_RESTORE 024C ESC_CURSOR_SAVE 01F1 ESC_DELLINE 01AF ESC_DOWN 0224 ESC_EL 020C ESC_EOL 0205 ESC_EOS 01C0 ESC_ERASE 0256 ESC_EXT 0230 ESC_FG_ATT 01C9 ESC_HOME 01DB ESC_INSLINE 01B6 ESC_LEFT 01CE ESC_REVLF 01BB ESC_RIGHT 01A8 ESC_UP 0C11 GCHAR_SET 061A GM_00 063A GM_10 05CA GP_00 05D8 GP_01 05FE GR_MOVSW 0593 GR_POSN 05A8 GR_PUT 0633 GR_REP_MOVSW 05F0 GR_REP_STOSW 05F6 GS_01 082A IGNORE 0922 IK_00 092C IK_01 09EB INIT 0BA1 INIT1 0849 INSKEY 08FF I_KEYBOARD 08E6 K8_00 003C KBD_HIGH 0B9B KBD_INIT 0036 KBD_LOW 08A5 KC_00 0898 KC_01 08DB KEY_8 0898 KEY_CHECK 08B7 KEY_IN 086B KEY_SCAN 08D7 KEY_SHIFTS 08A6 KEY_STAT 07E2 KEY_XLATE 08D0 KI_00 08CF KI_01 08B7 KI_02 0BB4 KLP0 0BBE KLP1 0BCF KLP2 0BD5 KLP8 0894 KS_00 08B6 KS_10 07F8 KX_00 0816 KX_01 0819 KX_02 0812 KX_03 0831 LEFTSIDE 078E LOOK_UP 07C2 LU_00 07A4 LU_01 07AE LU_02 07B6 LU_03 1019 MEM 0C0E NOKEY 0063 NO_ENTRY 0841 NUMKEY 082A PAUSE 04B8 POSITION 1016 PRINTER_INIT 1011 PRINTER_OUT 1016 PRINTER_STAT 004A PRN_HIGH 0044 PRN_LOW 082A PRTSCRN 08E7 RAW_KEY 044F READ_AC_CURRENT 0438 READ_CURSOR 0386 READ_DOT 0386 READ_LPEN 082A RESET 082D RIGHTSIDE 083D SCROLLKEY 0506 SCROLL_0 054B SCROLL_1 04E8 SCROLL_DOWN 04CB SCROLL_UP 050F SC_00 052D SC_01 0531 SC_02 051E SC_03 0526 SC_04 0540 SC_05 0542 SC_06 0559 SC_10 04AA SC_20 04AE SC_21 084D SETSHIFT 0499 SET_COLOR 0424 SET_CPOS 0411 SET_CTYPE 095F SET_FLAG 0387 SET_MODE 1059 SET_TIME 096D SF_00 03A2 SM_00 03B4 SM_01 03D9 SM_02 081D SPECIAL 07C8 SPECIALS 085D SS_00 085B SS_01 102E TIME_OF_DAY 0856 TOGSHIFT 0BE7 TRYOK 028F VC_BEL 01B6 VC_BS 027A VC_CR 0274 VC_ESC 0282 VC_LF 0126 VE_00 0124 VE_01 0311 VIDEO_OUT 0583 VIDEO_STATE 0331 VID_00 031D VID_01 0326 VID_02 0028 VID_HIGH 0008 VID_LOW 0292 VID_PUT 0290 VID_PUTC 02DB VI_00 02F4 VI_01 0300 VI_02 0310 VI_03 028E VL_00 0938 VPORTOFF 0940 VPORTON 0944 VP_00 02C1 VP_01 02AB VP_02 02AE VP_03 0180 VS_00 0144 VS_01 0161 VS_02 0159 VS_03 0177 VS_04 017F VS_05 01A0 VS_10 00F0 V_COLUMN 0101 V_ERASE 02C3 V_INESC 0129 V_LFSCROLL 0386 V_NULL 00F9 V_ROW 0135 V_SCROLL 0182 V_SETCUR 0975 WAIT_FLAG 0004 WAKE_UP 0477 WC_00 0479 WC_01 0988 WF_00 0990 WF_01 045E WRITE_AC_CURRENT 047B WRITE_C_CURRENT 0386 WRITE_DOT 0568 WRITE_TTY 0486 WR_00 0493 WR_01 0494 WR_02 094C XINT_SERV 095E XI_00 0956 XI_01 095E XI_02  V VD ˇ$8O^{h @ 8 Vs\Ԁs(O^Vs*?Ԁs62Vs6&Ԁsо<VsD ԀsJUvWRQS*[S. .[YZ_]^.: t .<u.dP+6>XÜ+> &>>t+6>>+Μ+tCsON>>t>&> >t{>;>s>RPP>XXZÀ>+>>HH@@+>8++>r>>+6>+OND6>>+0>>+>> >ø >ø+ >ãá,$>>at .>>&>À>|>sÊ>>>&>>t&@@s +>h>t, *&>6>>t, *>6>>tX6>Dȡ>>t< rn 2ȡ> z tYABCDEHIJK dl$oLMb0c0m:nCjLkP1â>+ >.t>+&t.\&'C<u.D&>*.t>.D >.D>.D>>>.D &>>+@É>> Ëʊ*&>*Ká>+6>V>F>6>&>>Nj>>>t{>>Nj>>>tGGP> t $ $ Ë>XRP*&>Z*ZP*XSfP*XSGP>Q>t>YYX Q>tY+с* u+Ɇ+>+þtȡ>k z >ࠍ>FPR+6>+ZXVWPSQ>Ɏپ t+Ɏ6|ȁ&& Y[X_^. WVQS>؊ [Y^_P. X1!2@3#4$5%6^7&8*9(0)-_=+ qQwWeErRtTyYuUiI oOpP[{]} aAsSdDfFgGhHjJ kK lL ;:'"`~\|zZxXcCvVbBnNmM ,<.>/?* 789--456++1230.+>ttt t*-159=AEI****Ru*+>>t̠>>tَ>F> tB=tá>=ut>uu >*>à> u&>úPGJ"XPSQRUVW. >>Ps >G>>>*_^]ZY[X >>>Àu u+>uH>++>u>>u@H++ñ ǻ ߉و*ȋu Ȏ. &>-B*&>&> >+. >>>>>>>>B &>P+&L &&@J&B&X&Z&g&&t &v&\&^&H&J&D$&F&h.&j&@. ظX8(- qPZ 8(- dpaPR ,P (P - )  *P .P 0, <P.@u .tB><~~<ffffff{>c8llx00000x xflxlf```bf8ll8ff|``xxff|lfxpx0000xx0l88lx00xƌ2fx`````x`0 xx8l00x |v``|ffxx |vxx8l```v| `lvff0p000x x`flxlp00000x xxff|`v| vf`|x 0|004vx0ll8l| 0d00000000v8lôء+ءء. t+>>>+ϣ>>> CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 1 ;1/24/85 ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* version 1.4A * ;* March 27, 1986 * ;************************************************ ; To assemble: ; RASM86 VID ; LINK86 VID ; ;1.4A - removed infinite retry loop in VINIT.A86 at KLP2 ; gal - 3/27/86 ; ;-------------------  ; include files NOLIST = INCLUDE VVARS.A86 = = = = = = VSEG dseg common 'vseg' ! org 16000 =3E80 V_BUFFER RW 1 ;Segment of screen image =3E82 V_SCRNSIZE RW 1 ;Size of screen image =3E84 V_ROWSIZE RW 1 ;Bytes per row =3E86 V_CURSOR RW 1 ;Offset to current cursor pos =3E88 V_FLAGS RB 1 ;Flags = 0001 VF_ESC EQU 01H ;In escape sequence = 0002 VF_ROW EQU 02H ;Looking for row number = 0004 VF_COL EQU 04H ;Looking for column number = 0008 VF_EXT EQU 08H ;Line buffered mode =3E89 V_ATTRIBUTES RB 1 ;Character attribtue =3E8A V_ESC_EXT RB 1 =3E8B V_GRAPHIC RB 1 =3E8C  V_COLOR RB 1 = = ;****** IBM ROM EMULATION ******************** = = = VSEG dseg common 'vseg' =3E8D CRT_MODE RB 1 =3E8E MD_PTR RW 1 =3E90 ADR_6845 RW 1 =3E92 CURSOR_MODE RW 1 = = = vseg dseg common 'vseg' = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 2 =3E94 CONKEY RW 1 ;Last console input key. =3E96 SHIFTS RB 1 ;Shift status, external keyboard = ;Masks for shifts = 0080 INSSTATE EQU 80H = 0040 CAPSLOCK EQU 40H = 0020 NUMLOCK EQU 20H = 0010 SCROLLLOCK EQU 10H = 0008   ALTERNATE EQU 08H = 0004 CNTLSTATE EQU 04H = 0002 LEFTSHIFT EQU 02H = 0001 RIGHTSHIFT EQU 01H = 0052 INSCODE EQU 82 = =3E97 VPORTSTATE RB 1 = = = VSEG DSEG COMMON 'vseg' = 0050 K_BUFSIZE EQU 50H =3E98 KBD_DATA RB 0 =3E98 K_FLAG RB 1 ;dev flag num, neg = no flag =3E99 K_INDEX RW 1 ;index into buffer =3E9B K_BUFFER RB 50 ;buf start, length will vary =3ECD LASTKEY RW 1 = = = = VSEG DSEG COMMON 'vseg' =3ECF I_FLAGS RB 30 = 0001 WAITING EQU 1 = =3EED T_SECS RW 1 =3EEF T_HIGH  RW 1 =3EF1 T_LOW RW 1 = = ;------------------- ;---- notes -------- ;1/24/85 elh added raw_key keyboard interrupt ;------------------- cseg org 0 ;Video Board ID. Software can read this location to ;determine if video board can be used. First two bytes ;identify video board. Next two bytes are the version ;number. At offset 4 is an initialization entry point. 0000 5644 DB 'VD' 0002 0100 DW 1 WAKE_UP: 0004 E8E409 09EB CALL INIT CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 3 0007 CB  RETF cseg ;Entry points to video routines. ;Entry is via a software interrupt. At boot a callf to ;wake_up setup interrupt vectors. Each entry is called ;with a function number in ah. Positive ah emulate ;ibm rom calls. Negative ah for Slicer additions ;Branch tables. ;Video (Int 10H ) VID_LOW: 0008 8703 R DW SET_MODE 000A 1104 R DW SET_CTYPE 000C 2404 R DW SET_CPOS 000E 3804 R DW READ_CURSOR 0010 8603 R DW READ_LPEN 0012 8603 R DW ACT_DISP_PAGE 0014 CB04 R DW SCROLL_UP 0016 E804 R DW SCROLL_DOWN 0018 4F04 R DW READ_AC_CURRENT 001A 5E04 R DW WRITE_AC_CURRENT 001C 7B04 R DW WRITE_C_CURRENT 001E 9904 R DW SET_COLOR 0020 8603 R DW WRITE_DOT 0022 8603 R DW READ_DOT 0024 6805 R DW WRITE_TTY 0026 8305 R DW VIDEO_STATE ; DW NO_OP ; DW FILL_WINDOW 0010 VID_LLIMIT EQU (OFFSET $ - OFFSET VID_LOW) / 2 VID_HIGH: 0028 1103 R DW VIDEO_OUT 0001 VID_HLIMIT EQU (OFFSET $ - OFFSET VID_HIGH) / 2 ;Disk ( Int 252 ) ;On the IBM PC this interrupt is at 13H. On the 80186 ;13H is reserved for hardware timer interrupt. So the ;Slicer re-routes disk interrupts to 252. DSK_LOW: 002A 9509 R DW DISK_RESET 002C 9509 R DW DISK_STATUS 002E A409 R DW DISK_READ 0030 AA09 R DW DISK_WRITE 0032 9C09 R DW DISK_VERIFY 0034 9809 R DW DISK_FORMAT 0006 DSK_LLIMIT EQU (OFFSET $ - OFFSET DSK_LOW) / 2 DSK_HIGH: 0000 DSK_HLIMIT EQU (OFFSET $ - OFFSET DSK_HIGH) / 2 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 4 ;Keyboard ( int 16H ) KBD_LOW: 0036 B708 R DW KEY_IN 0038 A608 R DW KEY_STAT 003A D708 R DW KEY_SHIFTS 0003 KBD_LLIMIT EQU (OFFSET $ - OFFSET KBD_LOW) / 2 KB D_HIGH: 003C DB08 R DW KEY_8 003E 4009 R DW VPORTON 0040 3809 R DW VPORTOFF 0042 E708 R DW RAW_KEY 0004 KBD_HLIMIT EQU (OFFSET $ - OFFSET KBD_HIGH) / 2 ;Printer ( int 17H ) PRN_LOW: 0044 1110 R DW PRINTER_OUT 0046 1610 R DW PRINTER_INIT 0048 1610 R DW PRINTER_STAT 0003 PRN_LLIMIT EQU (OFFSET $ - OFFSET PRN_LOW) / 2 PRN_HIGH: 0000 PRN_HLIMIT EQU (OFFSET $ - OFFSET PRN_HIGH) / 2 ;Range checks are made for each interrupt. If ah ;holds a legal value then a jump to the common code ;at enter is made. This save registers, calls ;subroutine, restores registers then returns. ;Video ENTER10: 004A 56 PUSH SI 004B 80FC10 CMP AH,VID_LLIMIT 004E 7306 0056 JNC ENTER10A 0050 BE0800 R MOV SI,OFFSET VID_LOW 0053 E95C00 00B2 JMP ENTER ENTER10A: 0056 F6D4 NOT AH 0058 80FC01 CMP AH,VID_HLIMIT 005B 7306 0063 JNC NO_ENTRY 005D BE2800 R MOV SI,OFFSET VID_HIGH 0060 E94F00 00B2 JMP ENTER NO_ENTRY: 0063 5E POP SI 0064 F6D4 NOT AH 0066 CF IRET ;Disk (looks like int. 13H but really int. 252 ) ENTER13: 0067 56 PUSH SI CP/M RASM-86 1.2 SOURCE: VID.A86  PAGE 5 0068 80FC06 CMP AH,DSK_LLIMIT 006B 7306 0073 JNC ENTER13A 006D BE2A00 R MOV SI,OFFSET DSK_LOW 0070 E93F00 00B2 JMP ENTER ENTER13A: 0073 F6D4 NOT AH 0075 80FC00 CMP AH,DSK_HLIMIT 0078 73E9 0063 JNC NO_ENTRY 007A BE3600 R MOV SI,OFFSET DSK_HIGH 007D E93200 00B2 JMP ENTER ;Keyboard ENTER16: 0080 56 PUSH SI 0081 80FC03 CMP AH,KBD_LLIMIT 0084 7306 008C JNC ENTER16A 0086 BE3600 R MOV SI,OFFSET KBD_LOW 0089 E92600 00B2 JMP ENTER ENTER16A: 008C F6D4 NOT AH  008E 80FC04 CMP AH,KBD_HLIMIT 0091 73D0 0063 JNC NO_ENTRY 0093 BE3C00 R MOV SI,OFFSET KBD_HIGH 0096 E91900 00B2 JMP ENTER ;Printer ENTER17: 0099 56 PUSH SI 009A 80FC03 CMP AH,PRN_LLIMIT 009D 7306 00A5 JNC ENTER17A 009F BE4400 R MOV SI,OFFSET PRN_LOW 00A2 E90D00 00B2 JMP ENTER ENTER17A: 00A5 F6D4 NOT AH 00A7 80FC00 CMP AH,PRN_HLIMIT 00AA 73B7 0063 JNC NO_ENTRY 00AC BE4A00 R MOV SI,OFFSET PRN_HIGH 00AF E90000 00B2 JMP ENTER ;----- ENTER: ;----- ;Common code for interrupt entry. ;in: ah = routine number (range already checked ) ; si = branch table ;For each subroutines ;in: ah, si = unknown( altered by enter) ; al, bx, cx, dx, di, es, ss = set by caller ; ( unaltered by enter ) CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 6 ; bp = pointer to register save area (on stack) ; ds = Video board data segment ;out: ax, flags = returned to caller ; other registers = restored from stack. ;If it is necessary to return a value in a register ;other than ax and flags then the saved copy of that ;register on the stack  should be altered. ;Flags are not saved so caution should be used when ;altering flags such as I and D. 00B2 55 PUSH BP 00B3 8BEC MOV BP,SP 00B5 FF7608 PUSH WORD PTR 8[BP] 00B8 9D POPF 00B9 57 PUSH DI 00BA 52 PUSH DX 00BB 51 PUSH CX 00BC 53 PUSH BX 00BD 8ADC MOV BL,AH 00BF 2AFF SUB BH,BH 00C1 D1E3 SHL BX,1 00C3 03F3 ADD SI,BX 00C5 5B POP BX 00C6 53 PUSH BX 00C7 1E PUSH DS 00C8 06 PUSH ES 00C9 2E8E1EE90A R MOV DS,DATASEG 00CE 8BEC MOV BP,SP 00D0 2EFF14 CALL CS:WORD PTR[SI] 00D3 07 POP ES 00D4 1F POP DS 00D5 5B POP BX 00D6 59 POP CX 00D7 5A POP DX 00D8 5F POP DI 00D9 5D POP BP 00DA 5E POP SI 00DB CA0200 RETF 2 ;Offsets into stack (relative to bp) for orignal/ ;return register values. SDUMMY SSEG COMMON 'EMPTY' ! ORG 0 0000 RES RW 1 0002 RDS RW 1 0004 RBX RW 1 0006 RCX RW 1 0008 RDX RW 1 000A RDI RW 1 000C RBP RW 1 000E RSI RW 1 CSEG CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 7 0001 WAIT EQU 1 ;---------------- ;Include files = INCLUDE VIDEO.A86 = = = ;************************************************ = ;* 04/08/85 * VIDEO .A86 * VERSION 1.1 * = ;************************************************ = ;* * = ;* Slicer Video Expansion Board * = ;* Video Drivers * = ;* * = ;************************************************ = = = = ;********** HANDY SUBROUTINES *************** = = = =  ;---- = CASE: = ;---- = = ;Multi-branch subroutine. Branch depends on the value = ;of cl. SI points to table of branches. Each entry has = ;a compare byte and subroutine address. If compare = ;byte matches cl then that branch is taken. Last entry = ;has compare byte 0, last branc address always taken. = ;in cl = branch byte = ; si = case table =00DE 2E3A0C C_00: CMP CL,CASE_CODE[SI] =00E1 7409 00EC JZ C_01 =00E3 83C603 ADD SI,CASE_LEN =00E6 2E803C00 CMP CASE_CODE[SI],0 =00EA 75F2 00DE JNZ C_00 =00EC 2EFF6401 C_01: JMP CASE_ROUTINE[SI] = = cdummy cseg common 'empty' ! org 0 =0000 CASE_CODE  RB 1 =0001 CASE_ROUTINE RW 1 = 0003 CASE_LEN EQU OFFSET $ = = cseg = = = ;-------- = V_COLUMN: = ;-------- = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 8 = ;Compute offset from start of row to ax. = ;in ax = screen position = ;out dx = column offset =00F0 50 PUSH AX =00F1 2BD2 SUB DX,DX =00F3 F736843E DIV V_ROWSIZE =00F7 58 POP AX =00F8 C3 RET = = = ;------ = V_ROW: = ;------ = = ;Compute offset of start of row containing ax = ;in ax  = screen position = ;out dx = column offset =00F9 E8F4FF 00F0 CALL V_COLUMN =00FC F7DA NEG DX =00FE 03D0 ADD DX,AX =0100 C3 RET = = = ;------- = V_ERASE: = ;------- = = ;Erase a portion of the screen. = ;in ax = from = ; dx = to + 1 =0101 9C PUSHF =0102 FC CLD =0103 06 PUSH ES =0104 8BCA MOV CX,DX ;Bytes to clear. =0106 2BC8 SUB CX,AX =0108 E31C 0126 JCXZ VE_00 =010A 8E06803E MOV ES,V_BUFFER ;Screen buffer =010E 8BF8 MOV DI,AX =0110 B020 MOV AL,' ' ;Fill character  =0112 8A26893E MOV AH,V_ATTRIBUTES =0116 D1E9 SHR CX,1 =0118 F6068B3E01 TEST V_GRAPHIC,1 =011D 7405 0124 JZ VE_01 =011F E8CE04 05F0 CALL GR_REP_STOSW =0122 EB02 0126 JMPS VE_00 =0124 F3AB VE_01: REP STOSW ;Fill =0126 07 VE_00: POP ES =0127 9D POPF =0128 C3 RET = = = ;---------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 9 = V_LFSCROLL: = ;---------- = = ;Scroll full screen. =0129 2BFF SUB DI,DI =012B 8B36843E MOV SI,V_ROWSIZE =012F 8B0E823E MOV CX,V_SCRNSIZE =0133 2BCE SUB CX,SI =  ; JMP V_SCROLL = = ;-------- = V_SCROLL: = ;-------- = = ;Scroll a portion of the screen. = ;in di = to = ; si = from = ; cx = number =0135 9C PUSHF =0136 FC CLD =0137 8BC6 MOV AX,SI =0139 2BC7 SUB AX,DI ;Number of bytes =013B 7443 0180 JZ VS_00 ;None? =013D 7305 0144 JNC VS_01 ;Backwards? =013F F7D8 NEG AX =0141 FD STD =0142 4F DEC DI =0143 4E DEC SI =0144 D1E9 VS_01: SHR CX,1 =0146 06 PUSH ES ;Save segments =0147 8E06803E  MOV ES,V_BUFFER ;Screen =014B E314 0161 JCXZ VS_02 ;Any to move? =014D F6068B3E01 TEST V_GRAPHIC,1 =0152 7405 0159 JZ VS_03 =0154 E8DC04 0633 CALL GR_REP_MOVSW =0157 EB08 0161 JMPS VS_02 =0159 1E VS_03: PUSH DS =015A 8E1E803E MOV DS,V_BUFFER =015E F3A5 REP MOVSW =0160 1F POP DS =0161 8BC8 VS_02: MOV CX,AX ;Fill =0163 D1E9 SHR CX,1 =0165 8A26893E MOV AH,V_ATTRIBUTES =0169 B020 MOV AL,' ' =016B F6068B3E01 TEST V_GRAPHIC,1 =0170 7405 0177 JZ VS_04 =0172 E87B04 05F0 CALL GR_REP_STOSW =0175 EB08 017F JMPS VS_05 =0177 1E VS_04: PUSH DS =0178 8E1E803E  MOV DS,V_BUFFER =017C F3AB REP STOSW =017E 1F POP DS ;Restore segments CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 10 =017F 07 VS_05: POP ES =0180 9D VS_00: POPF ;and direction =0181 C3 RET = = = ;-------- = V_SETCUR: = ;-------- = = = ;Set cursor position. = ;in ax = requested cursor position = ;out c set if bad cursor position request =0182 3B06823E CMP AX,V_SCRNSIZE ;Off the screen? =0186 7318 01A0 JNC VS_10 =0188 A3863E MOV V_CURSOR,AX ;Record position =018B 52 PUSH DX =018C 50   PUSH AX =018D D1E8 SHR AX,1 =018F 50 PUSH AX =0190 8B16903E MOV DX,ADR_6845 ;Tell hardware =0194 B00E MOV AL,14 =0196 EF OUT DX,AX =0197 58 POP AX =0198 8AE0 MOV AH,AL =019A B00F MOV AL,15 =019C EF OUT DX,AX =019D 58 POP AX =019E 5A POP DX =019F F9 STC =01A0 F5 VS_10: CMC =01A1 C3 RET = = = ;******* ESCAPE FUNCITONS *********************** = = ;All esc_ routines are called with = ;in ax = cursor position = = = ;---------- = ESC_CURPOS: = ;---------- = =  ;Set cursor position lead in. =01A2 800E883E03 OR V_FLAGS,VF_ROW + VF_ESC =01A7 C3 RET = = ;------ = ESC_UP: = ;------ = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 11 = ;Move up one line. =01A8 2B06843E SUB AX,V_ROWSIZE =01AC E9D3FF 0182 JMP V_SETCUR = = ;-------- = ESC_DOWN: = ;-------- = = ;Move down one line. =01AF 0306843E ADD AX,V_ROWSIZE =01B3 E9CCFF 0182 JMP V_SETCUR = = ;-------- = VC_BS: = ESC_LEFT: = ;-------- = = ;Back up one character. =01B6 48 DEC AX =01B7 48 DEC AX =01B8 E9C7FF 0182 JMP V_SETCUR = = ;--------- = ESC_RIGHT: = ;--------- = = ;Move ahead one character. =01BB 40 INC AX =01BC 40 INC AX =01BD E9C2FF 0182 JMP V_SETCUR = = ;--------- = ESC_ERASE: = ;--------- = = ;Clear screen. =01C0 2BC0 SUB AX,AX =01C2 8B16823E MOV DX,V_SCRNSIZE =01C6 E938FF 0101 JMP V_ERASE = = ;-------- = ESC_HOME: = ;-------- = = ;Put cursor at top left. =01C9 2BC0 SUB AX,AX =01CB E9B4FF 0182  JMP V_SETCUR = = = ;--------- = ESC_REVLF: = ;--------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 12 = = ;Move full screen down. =01CE 2B06843E SUB AX,V_ROWSIZE =01D2 E8ADFF 0182 CALL V_SETCUR =01D5 B80000 MOV AX,0 =01D8 7201 01DB JC ESC_INSLINE =01DA C3 RET = = ;----------- = ESC_INSLINE: = ;----------- = = ;Insert a line. =01DB E81BFF 00F9 CALL V_ROW =01DE 8B3E823E MOV DI,V_SCRNSIZE =01E2 8BF7 MOV SI,DI =01E4 2B36843E SUB SI,V_ROWSIZE =01E8 8BCE MOV CX,SI =01EA 2BCA  SUB CX,DX =01EC 4F DEC DI =01ED 4E DEC SI =01EE E944FF 0135 JMP V_SCROLL = = ;----------- = ESC_DELLINE: = ;----------- = = ;Delete a line. =01F1 E805FF 00F9 CALL V_ROW =01F4 8BFA MOV DI,DX =01F6 8BF7 MOV SI,DI =01F8 0336843E ADD SI,V_ROWSIZE =01FC 8B0E823E MOV CX,V_SCRNSIZE =0200 2BCE SUB CX,SI =0202 E930FF 0135 JMP V_SCROLL = = ;------- = ESC_EOS: = ;------- = = ;Erase to end of screen. =0205 8B16823E MOV DX,V_SCRNSIZE =0209 E9F5FE 0101 JMP V_ERASE = = ;------- =   ESC_EOL: = ;------- = = ;Erase to end of line. =020C E8EAFE 00F9 CALL V_ROW =020F 0316843E ADD DX,V_ROWSIZE =0213 E9EBFE 0101 JMP V_ERASE CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 13 = = ;------- = ESC_BOS: = ;------- = = ;Erase to beginning of screen. =0216 8BD0 MOV DX,AX =0218 2BC0 SUB AX,AX =021A E9E4FE 0101 JMP V_ERASE = = ;------- = ESC_BOL: = ;------- = = ;Erase to beginning of line. =021D E8D9FE 00F9 CALL V_ROW =0220 92 XCHG AX,DX =0221 E9DDFE 0101 JMP V_ERASE = = ;------ = ESC_EL: = ;------ = = ;Erase line. =0224 E8D2FE 00F9 CALL V_ROW =0227 8BC2 MOV AX,DX =0229 0316843E ADD DX,V_ROWSIZE =022D E9D1FE 0101 JMP V_ERASE = = = ;---------- = ESC_FG_ATT: = ESC_BG_ATT: = ;---------- = = ;Next byte is attribute. =0230 800E883E09 OR V_FLAGS,VF_ESC + VF_EXT =0235 880E8A3E MOV V_ESC_EXT,CL =0239 C3 RET = = = ;----- = ESC_CURSOR_ON: = ;----- = =023A B80B0A MOV AX,0A0Bh =023D 8B16903E MOV DX,ADR_6845 =0241 EF OUT DX,AX =0242 C3 RET  ;no SETCUR because cursor not moved = = = ;----- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 14 = ESC_CURSOR_OFF: = ;----- = =0243 B82B0A MOV AX,0A2Bh =0246 8B16903E MOV DX,ADR_6845 =024A EF OUT DX,AX =024B C3 RET = = DSEG = =0000 CUR_SAVE RW 1 = = CSEG = = ;----- = ESC_CURSOR_SAVE: = ;----- = =024C A30000 R MOV CUR_SAVE,AX =024F C3 RET = = = ;----- = ESC_CURSOR_RESTORE: = ;----- = =0250 A10000 R MOV AX,CUR_SAVE =0253 E92CFF 0182 JMP V_SETCUR = = = ;------- = ESC_EXT: = ;------- = = ;Multi-byte escape sequences. =0256 B5F0 MOV CH,0F0H =0258 240F AND AL,0FH =025A 803E8A3E61 CMP V_ESC_EXT,'a' =025F 7405 0266 JZ EE_00 =0261 C0E004 SLL AL,4 =0264 B50F MOV CH,0FH =0266 202E893E EE_00: AND V_ATTRIBUTES,CH =026A 0806893E OR V_ATTRIBUTES,AL =026E 8026883EF6 AND V_FLAGS,NOT ( VF_ESC + VF_EXT ) =0273 C3 RET = = = ;********* CONTROL CODES ************************* = = ;Always = ;in ax = cursor position = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 15 = ;------ =  VC_ESC: = ;------ = = ;Begin escape sequence. =0274 800E883E01 OR V_FLAGS,VF_ESC =0279 C3 RET = = ;----- = VC_CR: = ;----- = = ;Back to start of line. =027A E87CFE 00F9 CALL V_ROW =027D 8BC2 MOV AX,DX =027F E900FF 0182 JMP V_SETCUR = = ;----- = VC_LF: = ;----- = = ;Next line. Scroll sometimes. =0282 0306843E ADD AX,V_ROWSIZE =0286 E8F9FE 0182 CALL V_SETCUR =0289 7303 028E JNC VL_00 =028B E89BFE 0129 CALL V_LFSCROLL =028E C3 VL_00: RET = = = ;------ = VC_BEL: =   ;------ = = ;Not currently implemented =028F C3 RET = = = ;-------- = VID_PUTC: = ;-------- =0290 8AC1 MOV AL,CL = ;------- = VID_PUT: = ;------- = = ;Put character at cursor position. Update cursor = ;position. = ;in al ( or cl ) = character =0292 06 PUSH ES =0293 8B3E863E MOV DI,V_CURSOR ;Put character =0297 8E06803E MOV ES,V_BUFFER =029B 8A26893E MOV AH,V_ATTRIBUTES CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 16 =029F F6068B3E01 TEST V_GRAPHIC,1 =02A4 7405  02AB JZ VP_02 =02A6 E8FF02 05A8 CALL GR_PUT =02A9 EB03 02AE JMPS VP_03 =02AB 268905 VP_02: MOV ES:[DI],AX =02AE 8BC7 VP_03: MOV AX,DI ;New cursor position =02B0 40 INC AX =02B1 40 INC AX =02B2 E8CDFE 0182 CALL V_SETCUR =02B5 730A 02C1 JNC VP_01 =02B7 2B06843E SUB AX,V_ROWSIZE ;Off screen =02BB E8C4FE 0182 CALL V_SETCUR ;Need scroll =02BE E868FE 0129 CALL V_LFSCROLL =02C1 07 VP_01: POP ES =02C2 C3 RET = = = ;------- = V_INESC: = ;------- = = ;Escape sequence handler. Character output is sent = ;here if in escape sequnce. = ;in  al = next character in escape sequence =02C3 F606883E02 TEST V_FLAGS,VF_ROW ;Getting row position? =02C8 7411 02DB JZ VI_00 =02CA 2C20 SUB AL,' ' ;Offset =02CC 2AE4 SUB AH,AH =02CE F726843E MUL V_ROWSIZE =02D2 E8ADFE 0182 CALL V_SETCUR ;Set row, then look =02D5 8036883E06 XOR V_FLAGS,VF_ROW+VF_COL ;for column =02DA C3 RET =02DB F606883E04 VI_00: TEST V_FLAGS,VF_COL ;Looking for column? =02E0 7412 02F4 JZ VI_01 =02E2 2C20 SUB AL,' ' ;Offset =02E4 2AE4 SUB AH,AH =02E6 D1E0 SHL AX,1 =02E8 0306863E ADD AX,V_CURSOR ;New position =02EC 8036883E05 XOR V_FLAGS,VF_ESC+VF_COL ;Exit esc mode =02F1 E98EFE 0182 JMP  V_SETCUR =02F4 F606883E08 VI_01: TEST V_FLAGS,VF_EXT =02F9 7405 0300 JZ VI_02 =02FB E858FF 0256 CALL ESC_EXT =02FE EB10 0310 JMPS VI_03 =0300 8036883E01 VI_02: XOR V_FLAGS,VF_ESC ;Other escape char =0305 BE4403 R MOV SI,OFFSET ESC_TABLE ;Search table =0308 8AC8 MOV CL,AL =030A A1863E MOV AX,V_CURSOR =030D E8CEFD 00DE CALL CASE =0310 C3 VI_03: RET = = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 17 = ;--------- = VIDEO_OUT: = ;--------- = = ;Entry point for character output = ;in al = char =0311 F606883E01 TEST V_FLAGS,VF_ESC ;In escape sequence? =0316 7405 031D JZ VID_01 =0318 E8A8FF 02C3 CALL V_INESC =031B EB14 0331 JMPS VID_00 =031D 3C20 VID_01: CMP AL,' ' ;Control character? =031F 7205 0326 JC VID_02 =0321 E86EFF 0292 CALL VID_PUT ;In not put charater =0324 EB0B 0331 JMPS VID_00 =0326 BE3203 R VID_02: MOV SI,OFFSET CNTL_TABLE ;Else search =0329 8AC8 MOV CL,AL ;control table codes =032B A1863E MOV AX,V_CURSOR =032E E8ADFD 00DE CALL CASE =0331 C3 VID_00: RET = = = ;--------- =0332 CNTL_TABLE RB 0 = ;--------- = = ;Case table for special handling of control character = ;inputs. =0332 0D7A02 R DB CR ! DW VC_CR =0335 0 A8202 R DB LF ! DW VC_LF =0338 08B601 R DB BS ! DW VC_BS =033B 1B7402 R DB ESC ! DW VC_ESC =033E 078F02 R DB BEL ! DW VC_BEL =0341 009002 R DB 0 ! DW VID_PUTC = = = ;-------- =0344 ESC_TABLE RB 0 = ;-------- = = ;Case table for escape sequences =0344 59A201 R DB 'Y' ! DW ESC_CURPOS =0347 41A801 R DB 'A' ! DW ESC_UP =034A 42AF01 R DB 'B' ! DW ESC_DOWN =034D 43BB01 R DB 'C' ! DW ESC_RIGHT =0350 44B601 R DB 'D' ! DW ESC_LEFT =0353 45C001 R DB 'E' ! DW ESC_ERASE =0356 48C901 R DB 'H' ! DW ESC_HOME =0359 49CE01 R DB 'I' ! DW ESC_REVLF =035C 4A0502 R DB 'J' ! DW ESC_EOS =035F 4B0C02 R DB 'K' ! DW ESC_EOL =0362 641602  R DB 'd' ! DW ESC_BOS =0365 6C2402 R DB 'l' ! DW ESC_EL CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 18 =0368 6F1D02 R DB 'o' ! DW ESC_BOL =036B 4CDB01 R DB 'L' ! DW ESC_INSLINE =036E 4DF101 R DB 'M' ! DW ESC_DELLINE =0371 623002 R DB 'b' ! DW ESC_FG_ATT =0374 633002 R DB 'c' ! DW ESC_BG_ATT =0377 6D3A02 R DB 'm' ! DW ESC_CURSOR_ON =037A 6E4302 R DB 'n' ! DW ESC_CURSOR_OFF =037D 6A4C02 R DB 'j' ! DW ESC_CURSOR_SAVE =0380 6B5002 R DB 'k' ! DW ESC_CURSOR_RESTORE =0383 003103 R DB 0 ! DW VID_00 = = = ;****** IBM ROM EMULATION ******************** = = CSEG = ;Perhaps some other day = READ_LPEN: =  ACT_DISP_PAGE: = WRITE_DOT: = READ_DOT: = V_NULL: =0386 C3 RET = = = ;-------- = SET_MODE: = ;-------- = = ;Set up video for selected mode. = ; 6845 is intialized = ; screen is cleared = ; cursor set to upper left corner = ;in al = desired mode =0387 A28D3E MOV CRT_MODE,AL ;Save mode =038A B20E MOV DL,MD_LEN ;Find mode data =038C F6E2 MUL DL =038E 052B0B R ADD AX,OFFSET MODE_DATA =0391 A38E3E MOV MD_PTR,AX =0394 8BF0 MOV SI,AX =0396 BAB403 MOV DX,03B4H ;Find 6845 =0399 2EF60401  TEST MODE_FLAGS[SI],MF_EXPANSION =039D 7403 03A2 JZ SM_00 =039F BAD403 MOV DX,03D4H =03A2 8916903E SM_00: MOV ADR_6845,DX =03A6 06 PUSH ES ;Initialize 6845 =03A7 2BC0 SUB AX,AX ;for selected mode =03A9 8EC0 MOV ES,AX =03AB 26C41E7400 LES BX,ES:dword ptr vp6845 =03B0 2E035C01 ADD BX,P6845_OFFSET[SI] =03B4 268A27 SM_01: MOV AH,ES:[BX] =03B7 EF OUT DX,AX =03B8 43 INC BX CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 19 =03B9 FEC0 INC AL =03BB 3C10 CMP AL,P6845_LEN =03BD 75F5 03B4 JNZ SM_01 =03BF 83C204 ADD DX,4 =03C2 2E8B4403 MOV AX,CONTROL_REG[SI] =03C6 EF OUT DX,AX =03C7 88268C3E MOV V_COLOR,AH =03CB 83C202 ADD DX,2 =03CE EC IN AL,DX =03CF 2AC0 SUB AL,AL =03D1 2EF60402 TEST MODE_FLAGS[SI],MF_GRAPHIC =03D5 7402 03D9 JZ SM_02 =03D7 FEC0 INC AL =03D9 A28B3E SM_02: MOV V_GRAPHIC,AL ;Graphics flag =03DC 2E8B440C MOV AX,RAM_BASE[SI] =03E0 A3803E MOV V_BUFFER,AX ;Screen buffer segment =03E3 2E8B4407 MOV AX,SCREEN_SIZE[SI] =03E7 A3823E MOV V_SCRNSIZE,AX ;Screen size =03EA 2E8B4405 MOV AX,ROW_SIZE[SI] =03EE A3843E MOV V_ROWSIZE,AX ;Row size =03F1 C706863E0000 MOV V_CURSOR,0 ;Cursor position =03F7 C606883E00 MOV V_FLAGS,0 ;Flags =03FC 2E8B440A MOV AX,INIT_CHAR[SI] ;Clear character =0400 8826893E MOV V_ATTRIBUTES,AH =0404 8E06803E MOV ES,V_BUFFER =0408 2BFF SUB DI,DI =040A B9401F MOV CX,8000 ;Clear screen =040D F3AB REP STOSW =040F 07 POP ES =0410 C3 RET = = = ;--------- = SET_CTYPE: = ;--------- = = ;Set cursor type = ;in cx = cursor type =0411 890E923E MOV CURSOR_MODE,CX =0415 8B16903E MOV DX,ADR_6845 =0419 B00A MOV AL,10 =041B 8AE5 MOV AH,CH =041D EF OUT DX,AX =041E FEC0 INC AL  =0420 8AE1 MOV AH,CL =0422 EF OUT DX,AX =0423 C3 RET = = = ;-------- = SET_CPOS: = ;-------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 20 = = ;Set cursor position = ;in dx = cursor position (row/column) =0424 8BCA MOV CX,DX ;Convert to byte offset =0426 8AC6 MOV AL,DH =0428 2AE4 SUB AH,AH =042A F726843E MUL V_ROWSIZE =042E 2AED SUB CH,CH =0430 03C1 ADD AX,CX =0432 03C1 ADD AX,CX =0434 E84BFD 0182 CALL V_SETCUR ;Then set =0437 C3 RET = = =  ;----------- = READ_CURSOR: = ;----------- = = ;Return cursor type and position = ;out cx = type = ; dx = position =0438 A1863E MOV AX,V_CURSOR ;Convert positon to =043B 2BD2 SUB DX,DX ;row/column =043D F736843E DIV V_ROWSIZE =0441 D1EA SHR DX,1 =0443 8AF0 MOV DH,AL =0445 895608 MOV RDX[BP],DX ;Sneak return values =0448 A1923E MOV AX,CURSOR_MODE ;into stack for later =044B 894606 MOV RCX[BP],AX ;pop. =044E C3 RET = = = ;--------------- = READ_AC_CURRENT: = ;--------------- = = ;Return character at cursor position = ;(text modes only) = ;out ax = character =044F 06 PUSH ES =0450 A1803E MOV AX,V_BUFFER =0453 8EC0 MOV ES,AX =0455 8B36863E MOV SI,V_CURSOR =0459 268B04 MOV AX,ES:[SI] =045C 07 POP ES =045D C3 RET = = = ;---------------- = WRITE_AC_CURRENT: = ;---------------- = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 21 = ;Write character / attribute at current cursor = ;position. = ;in al = character = ; bl = attribute = ; cx = number of copies = ;WARNING: cx not checked. Large cx causes write to = ; non-screen area. =045E 06 PUSH ES =045F 8B3E803E MOV DI,V_BUFFER =0463 8EC7 MOV ES,DI =0465 8B3E863E MOV DI,V_CURSOR =0469 8AE3 MOV AH,BL =046B F6068B3E01 TEST V_GRAPHIC,1 =0470 7405 0477 JZ WC_00 =0472 E87B01 05F0 CALL GR_REP_STOSW =0475 EB02 0479 JMPS WC_01 =0477 F3AB WC_00: REP STOSW =0479 07 WC_01: POP ES =047A C3 RET = = = ;--------------- = WRITE_C_CURRENT: = ;--------------- = = ;Write character at current cursor position = ;position. = ;in al = character = ; cx = number of copies = ;WARNING: cx not checked. Large cx causes write to = ; non-screen area. =047B 06 PUSH ES =047C 8B3E803E MOV DI,V_BUFFER =0480 8EC7 MOV ES,DI =0482 8B3E863E MOV DI,V_CURSOR =0486 F6068B3E01 WR_00: TEST V_GRAPHIC,1 =048B 7406 0493 JZ WR_01 =048D E81801 05A8 CALL GR_PUT =0490 47 INC DI =0491 EB01 0494 JMPS WR_02 =0493 AA WR_01: STOSB =0494 47 WR_02: INC DI =0495 E2EF 0486 LOOP WR_00 =0497 07 POP ES =0498 C3 RET = = = ;--------- = SET_COLOR: = ;--------- = = ;Set color pallette CP/M RASM-86 1.2 SOURCE: VID.A86  PAGE 22 =0499 50 PUSH AX =049A A08C3E MOV AL,V_COLOR =049D 0AFF OR BH,BH =049F 7409 04AA JZ SC_20 =04A1 24DF AND AL,NOT 20H =04A3 C0E305 SLL BL,5 =04A6 0AC3 OR AL,BL =04A8 EB04 04AE JMPS SC_21 =04AA 24E0 SC_20: AND AL,NOT 1FH =04AC 0AC3 OR AL,BL =04AE 8B16903E SC_21: MOV DX,ADR_6845 =04B2 83C205 ADD DX,5 =04B5 EE OUT DX,AL =04B6 58 POP AX =04B7 C3 RET = = = ;-------- = POSITION: = ;-------- = = ;Convert row/column location to byte offset. =  ;in ax = row / column = ;out ax = byte offset =04B8 52 PUSH DX =04B9 50 PUSH AX =04BA 8AC4 MOV AL,AH =04BC 2AE4 SUB AH,AH =04BE F726843E MUL V_ROWSIZE =04C2 5A POP DX =04C3 2AF6 SUB DH,DH =04C5 D1E2 SHL DX,1 =04C7 03C2 ADD AX,DX =04C9 5A POP DX =04CA C3 RET = = = ;--------- = SCROLL_UP: = ;--------- = = ;Scroll up entry. = ;in al = number of lines (0=all) = ; bh = fill attribute = ; cx = upper left corner = ; dx = lower right corner =04CB 50  PUSH AX =04CC 8AE0 MOV AH,AL =04CE 2AC0 SUB AL,AL =04D0 03C1 ADD AX,CX =04D2 E8E3FF 04B8 CALL POSITION =04D5 8BF0 MOV SI,AX CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 23 =04D7 8BC1 MOV AX,CX =04D9 E8DCFF 04B8 CALL POSITION =04DC 8BF8 MOV DI,AX =04DE 58 POP AX =04DF 9C PUSHF =04E0 FC CLD =04E1 53 PUSH BX =04E2 E86600 054B CALL SCROLL_1 =04E5 E91E00 0506 JMP SCROLL_0 = = = ;----------- = SCROLL_DOWN: = ;----------- = = ;Scroll down entry. =  ;in al = number of lines (0=all) = ; bh = fill attribute = ; cx = upper left corner = ; dx = lower right corner = =04E8 50 PUSH AX =04E9 8AE0 MOV AH,AL =04EB F6DC NEG AH =04ED 2AC0 SUB AL,AL =04EF 03C2 ADD AX,DX =04F1 E8C4FF 04B8 CALL POSITION =04F4 8BF0 MOV SI,AX =04F6 8BC2 MOV AX,DX =04F8 E8BDFF 04B8 CALL POSITION =04FB 8BF8 MOV DI,AX =04FD 58 POP AX =04FE 9C PUSHF =04FF FD STD =0500 53 PUSH BX =0501 E84700 054B CALL SCROLL_1 =0504 F7DB NEG BX = =  ;Up and down meet here = ; ax = rows to blank = ; bx = bytes to skip per row = ; cx = rows to copy = ; dx = bytes to copy per row = ; es:si = source = ; ds:di = destination = ; stack = fill attribute = ; = flags = ; = return = SCROLL_0: =0506 50 PUSH AX =0507 8E06803E MOV ES,V_BUFFER =050B D1FA SAR DX,1 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 24 =050D E31E 052D JCXZ SC_01 =050F 51 SC_00: PUSH CX =0510 8BCA MOV CX,DX =0512 F6068B3E01  TEST V_GRAPHIC,1 =0517 7405 051E JZ SC_03 =0519 E81701 0633 CALL GR_REP_MOVSW =051C EB08 0526 JMPS SC_04 =051E 1E SC_03: PUSH DS =051F 8E1E803E MOV DS,V_BUFFER =0523 F3A5 REP MOVSW =0525 1F POP DS =0526 03F3 SC_04: ADD SI,BX =0528 03FB ADD DI,BX =052A 59 POP CX =052B E2E2 050F LOOP SC_00 =052D 59 SC_01: POP CX =052E 58 POP AX =052F B020 MOV AL,' ' =0531 51 SC_02: PUSH CX =0532 8BCA MOV CX,DX =0534 F6068B3E01 TEST V_GRAPHIC,1 =0539 7405 0540 JZ SC_05 =053B E8B200 05F0 CALL GR_REP_STOSW =053E EB02 0542 JMPS SC_06 =0540 F3AB SC_05: REP STOSW =0542 03F3 SC_06: ADD SI,BX =0544 03FB ADD DI,BX =0546 59 POP CX =0547 E2E8 0531 LOOP SC_02 =0549 9D POPF =054A C3 RET = = ;Handy subroutine for scrolling = ;in: al = number of rows to scroll = ; cx = upper left corner = ; dx = lower right corner = ;out: ax = number of rows to blank = ; bx = bytes to skip per row = ; cx = number of rows to copy = ; dx = bytes to copy per row = SCROLL_1: =054B 2BD1 SUB DX,CX =054D 81C20101 ADD DX,101H =0551 2AE4 SUB AH,AH =0553 0AC0  OR AL,AL =0555 7502 0559 JNZ SC_10 =0557 8AC6 MOV AL,DH =0559 2BC9 SC_10: SUB CX,CX =055B 86CE XCHG CL,DH =055D 2BC8 SUB CX,AX =055F D1E2 SHL DX,1 =0561 8B1E843E MOV BX,V_ROWSIZE CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 25 =0565 2BDA SUB BX,DX =0567 C3 RET = = ;--------- = WRITE_TTY: = ;--------- = = ;Make display look like serial terminal = ;in al = char =0568 BE7405 R MOV SI,OFFSET TTY_TABLE =056B 8AC8 MOV CL,AL =056D A1863E MOV AX,V_CURSOR =0570 E86BFB 00DE CALL CASE =0573 C3 RET = = =0574 TTY_TABLE RB 0 =0574 0D7A02 R DB CR ! DW VC_CR =0577 0A8202 R DB LF ! DW VC_LF =057A 08B601 R DB BS ! DW VC_BS =057D 078603 R DB BEL ! DW V_NULL =0580 009002 R DB 0 ! DW VID_PUTC = = = ;----------- = VIDEO_STATE: = ;----------- = = ;Return current video mode = ;out al = mode = ; ah = rowsize =0583 A1843E MOV AX,V_ROWSIZE =0586 D0E8 SHR AL,1 =0588 8AE0 MOV AH,AL =058A A08D3E MOV AL,CRT_MODE =058D C746040000 MOV RBX[BP],0 =0592 C3 RET = = = ;************************************************** = =  ; GRAPHICS SUBROUTINES = = ;************************************************** = = = ;------- = GR_POSN: = ;------- = = ;Convert DI from a character position = ;to a graphic position CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 26 = ;in di = character position (byte offset) = ;out di = graphic position = ;WARNING: Presently 640x200 expansion slot mode only. =0593 50 PUSH AX =0594 52 PUSH DX =0595 8BC7 MOV AX,DI =0597 2BD2 SUB DX,DX =0599 F736843E DIV V_ROWSIZE =059D 2BFA SUB DI,DX =059F D1E7  SHL DI,1 =05A1 D1EA SHR DX,1 =05A3 03FA ADD DI,DX =05A5 5A POP DX =05A6 58 POP AX =05A7 C3 RET = = = ;------ = GR_PUT: = ;------ = = ;Put a character on the graphic screen = ;Replaces MOV ES:[DI],AL charater instruction = ;in al = character = ; es:di = character position = ;WARNING: Presently 640x200 expansion slot mode only. =05A8 56 PUSH SI ;Don't change any =05A9 57 PUSH DI ;registers =05AA 50 PUSH AX =05AB 53 PUSH BX =05AC 51 PUSH CX =05AD 1E PUSH DS =05AE E8E2FF 0593 CALL GR_POSN ;Get graphic byte =05B1 8B1E843E MOV BX,V_ROWSIZE ;offset and offset =05B5 D1EB shr bx,1 ;between graphic rows = ;NOTE: offset between graphic rows depends on mode =05B7 8CC9 MOV CX,CS ;Get character =05B9 8ED9 MOV DS,CX =05BB BE110C R MOV SI,OFFSET GCHAR_SET =05BE A880 TEST AL,80H ;Extended character =05C0 7408 05CA JZ GP_00 ;Set? =05C2 2BC9 SUB CX,CX =05C4 8ED9 MOV DS,CX =05C6 C5367C00 LDS SI,DS:DWORD PTR VCHAR_SET =05CA 8BC8 GP_00: MOV CX,AX ;Here ds:si = char =05CC 81E17F00 AND CX,7FH ;set base. =05D0 C1E103 SLL CX,3 =05D3 03F1 ADD SI,CX ;index to char =05D5 B90400 MOV CX,4 = ;NOTE screen locations depend on mode. =05D8 8B04 GP_01: MOV AX,DS:[SI] ;move to screen =05DA 268805 MOV ES:[DI],AL CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 27 =05DD 2688A50020 MOV ES:2000H[DI],AH =05E2 83C602 ADD SI,2 =05E5 03FB ADD DI,BX =05E7 E2EF 05D8 LOOP GP_01 =05E9 1F POP DS =05EA 59 POP CX =05EB 5B POP BX =05EC 58 POP AX =05ED 5F POP DI =05EE 5E POP SI =05EF C3 RET = = = ;------------ =  GR_REP_STOSW: = ;------------ = = ;Replaces REP STOSW character instruction = ;in ax = character = ; cx = number to draw = ; di = character position =05F0 1E PUSH DS =05F1 2E8E1EE90A R MOV DS,DATASEG =05F6 E8AFFF 05A8 GS_01: CALL GR_PUT =05F9 AF SCASW =05FA E2FA 05F6 LOOP GS_01 =05FC 1F POP DS =05FD C3 RET = = = ;-------- = GR_MOVSW: = ;-------- = = ;Replaces MOVSW character instruction = ;in si = source character position = ; di = destination character position = ;WARNING: Presently 640x200 expansion slot mode only. =05FE 1E PUSH DS =05FF 57 PUSH DI =0600 56 PUSH SI =0601 51 PUSH CX =0602 53 PUSH BX =0603 87FE XCHG DI,SI =0605 E88BFF 0593 CALL GR_POSN =0608 87FE XCHG DI,SI =060A E886FF 0593 CALL GR_POSN = ;NOTE offset between rows depends on mode =060D 8B1E843E MOV BX,V_ROWSIZE =0611 D1EB SHR BX,1 =0613 B90400 MOV CX,4 =0616 8CC0 MOV AX,ES CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 28 =0618 8ED8 MOV DS,AX = ;NOTE offset between even and odd rows depend on mode =061A 8A04 GM_00: MOV AL,[SI] =061C 8805  MOV [DI],AL =061E 8A840020 MOV AL,2000H[SI] =0622 88850020 MOV 2000H[DI],AL =0626 03FB ADD DI,BX =0628 03F3 ADD SI,BX =062A E2EE 061A LOOP GM_00 =062C 5B POP BX =062D 59 POP CX =062E 5E POP SI =062F 5F POP DI =0630 A7 CMPSW =0631 1F POP DS =0632 C3 RET = = = ;------------ = GR_REP_MOVSW: = ;------------ = = = ;Replaces REP MOVSW character instruction = ;in cx = number of characters to move = ; si = source character position = ; di = destination character position =  ;WARNING: Presently 640x200 expansion slot mode only. =0633 1E PUSH DS =0634 50 PUSH AX =0635 2E8E1EE90A R MOV DS,DATASEG =063A E8C1FF 05FE GM_10: CALL GR_MOVSW =063D E2FB 063A LOOP GM_10 =063F 58 POP AX =0640 1F POP DS =0641 C3 RET = INCLUDE VKEYS.A86 = = ;************************************************ = ;* 03/28/85 * VKEYS .A86 * VERSION 1.1 * = ;************************************************ = ;* * = ;* Slicer Video Expansion Board * = ;* Keyboard * = ;*  * = ;************************************************ = = CSEG = = = ;------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 29 =0642 KEYTABLE RB 0 = ;------- = = ;Scan code translation table. = ;Four entries for each character = ; normal, shift, control, alternate = ;Key decoding routine interpets this table as follows: = ; 0 Normal extended code, or ASCII null. = ; Return ah=scan code, al=0. = ; 1-127 ASCII key code. = ; Return ah=scan code, al=table value. = ; 128-199 Modified extended code. = ; Return ah=table value - 44, al=0. = ; This is for things like shift-function = ; key. Offset of 44 keeps these table = ; values distinct from the ASCII codes. = ; 200-255 Special handling. = ; Table value is negative of index into = ; special handling routines. =0642 1B1B1BFF3121 DB 27,27,27,-1,'1!',-1,164 ;Keys 1,2 FFA4 =064A 324000A53323 DB '2@',0,165,'3#',-1,166 ;3,4 FFA6 =0652 3424FFA73525 DB '4$',-1,167,'5%',-1,168 ;5,6 FFA8 =065A 365E1EA93726 DB '6^',30,169,'7&',-1,170 ;7,8 FFAA =0662 382AFFAB3928 DB '8*',-1,171,'9(',-1,172 ;9,10 FFAC =066A 3029FFAD2D5F DB '0)',-1,173,'-_',31,174 ;11,12 1FAE =0672 3D2BFFAF0808 DB '=+',-1,175,8,8,127,-1 ;13,14 7FFF =067A 0900FFFF7151 DB 9,0,-1,-1,'qQ',17,0 ;15,16 1100 =0682 775717006545 DB 'wW',23,0,'eE',5,0,'rR',18,0 ;17,18,19 050072521200 =068E 745414007959 DB 'tT',20,0,'yY',25,0,'uU',21,0 ;20,21,22 190075551500 =069A 694909006F4F DB 'iI',9,0,'oO',15,0,'pP',16,0 ;23,24,25 0F0070501000 =06A6 5B7B1BFF5D7D DB '[{',27,-1,']}',29,-1 ;26,27 1DFF =06AE 0D0D0AFFFCFC DB 13,13,10,-1,-4,-4,-4,-4 ;28,29 FCFC =06B6 614101007353 DB 'aA',1,0,'sS',19,0,'dD',4,0 ;30,31,32 130064440400 =06C2 664606006747 DB 'fF',6,0,'gG',7,0,'hH',8,0 ;33,34,35 070068480800 =06CE 6A4A0A006B4B DB 'jJ',10,0,'kK',11,0,'lL',12,0 ;36,37,38 0B006C4C0C00 =06DA 3B3AFFFF2722 DB ';:',-1,-1,39,'"',-1,-1 ;39,40 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 30 FFFF =06E2 607EFFFFFDFD DB '`~',-1,-1,-3,-3,-3,-3 ;41,42 FDFD =06EA 5C7C1CFF7A5A DB '\|',28,-1,'zZ',26,0,'xX',24,0 ;43,44,45 1A0078581800 =06F6 634303007656 DB 'cC',3,0,'vV',22,0,'bB',2,0 ;46,47,48 160062420200 =0702 6E4E0E006D4D DB 'nN',14,0,'mM',13,0,',<',-1,-1 ;49,50,51 0D002C3CFFFF =070E 2E3EFFFF2F3F DB '.>',-1,-1,'/?',-1,-1 ;52,53 FFFF =0716 FEFEFEFE2AF6 DB -2,-2,-2,-2,'*',-10,158,-1 ;54,55 9EFF =071E FBFBFBFB2020 DB -5,-5,-5,-5,' ',-8,-8,-8,-8 ;56,57,58 2020F8F8F8F8 =072A 00808A940081 DB 0,128,138,148,0,129,139,149 ;59,60 8B95 =0732 00828C960083 DB 0,130,140,150,0,131,141,151 ;61,62 8D97 =073A 00848E980085 DB 0,132,142,152,0,133,143,153 ;63,64 8F99 =0742 0086909A0087 DB 0,134,144,154,0,135,145,155 ;65,66 919B =074A 0088929C0089 DB 0,136,146,156,0,137,147,157 ;67,68 939D =0752 F9F9F5F9FAFA DB -7,-7,-11,-7,-6,-6,-12,-6 ;69,70 F4FA =075A 0037A3FF0038 DB 0,'7',163,-1,0,'8',-1,-1 ;71,72 FFFF =0762 0039B0FF2D2D DB 0,'9',176,-1,'--',-1,-1 ;73,74 FFFF =076A 00349FFFFF35 DB 0,'4',159,-1,-1,'5',-1,-1 ;75,76 FFFF =0772 0036A0FF2B2B DB 0,'6',160,-1,'++',-1,-1 ;77,78 FFFF =077A 0031A1FF0032 DB 0,'1',161,-1,0,'2',-1,-1 ;79,80 FFFF =0782 0033A2FFF730 DB 0,'3',162,-1,-9,'0',-1,-1 ;81,82 FFFF =078A 002EF3F3 DB 0,'.',-13,-13 ;83 = = = ;------- = LOOK_UP: = ;------- = = ;Scan code look up. = ;in al = scan code = ;out al = table look up value. = ; cl = shift state =078E 2BDB SUB BX,BX ;bx = al * 4 = index =0790 D0E0 SHL AL,1 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 31 =0792 8AD8 MOV BL,AL =0794 D1E3 SHL BX,1 =0796 8A0E963E MOV CL,SHIFTS ;Get shift states =079A F6C108 TEST CL,ALTERNATE ;Alt key pressed? =079D 7405 07A4 JZ LU_01 =079F 80C303 ADD BL,3 =07A2 EB1E 07C2 JMPS LU_00 =07A4 F6C104 LU_01: TEST CL,CNTLSTATE ;Control key pressed? =07A7 7405 07AE JZ LU_02 =07A9 80C302 ADD BL,2 =07AC EB14 07C2 JMPS LU_00 =07AE F6C103  LU_02: TEST CL,LEFTSHIFT+RIGHTSHIFT ;Shift? =07B1 7403 07B6 JZ LU_03 =07B3 80C301 ADD BL,1 =07B6 F6C120 LU_03: TEST CL,NUMLOCK ;Num lock? =07B9 7407 07C2 JZ LU_00 =07BB 3C8E CMP AL,142 ;and keypad key? =07BD 7203 07C2 JC LU_00 =07BF 80F301 XOR BL,1 ;toggle shift =07C2 2E8A873E06 R LU_00: MOV AL,KEYTABLE-4[BX] =07C7 C3 RET = = = ;-------- = SPECIALS: = ;-------- = = ;Table of subroutines for keys which require special = ;handling. =07C8 2A08 R DW IGNORE =07CA 2D08 R DW RIGHTSIDE =07CC 3108 R DW LEFTSIDE =07CE 3508 R DW CONTROLKEY =07D0 3908 R DW ALTKEY =07D2 3D08 R DW SCROLLKEY =07D4 4108 R DW NUMKEY =07D6 4508 R DW CAPSKEY =07D8 4908 R DW INSKEY =07DA 2A08 R DW PRTSCRN =07DC 2A08 R DW PAUSE =07DE 2A08 R DW BREAK =07E0 2A08 R DW RESET = = = ;--------- = KEY_XLATE: = ;--------- = = ;Translate scan code in al to action or return code. = ;in al = scan code = ;out ax = return code = ; or if no return code ax = -1 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 32 =07E2 8AE0 MOV AH,AL ;Store scan code =07E4 E8A7FF 078E CALL LOOK_UP ;Table look up =07E7 3C85 CMP AL,133 ;Ascii code or normal =07E9 720D 07F8 JC KX_00 ;scan code? =07EB 3CC8 CMP AL,200 ;Special handling? =07ED 732E 081D JNC SPECIAL =07EF 2C2C SUB AL,44 ;or modified scan code =07F1 80E480 AND AH,80H ;table offset = 44 =07F4 0AE0 OR AH,AL ;save open/close bit =07F6 2AC0 SUB AL,AL ;AH=code, AL=0 =07F8 F6C480 KX_00: TEST AH,80H ;Release? =07FB 7519 0816 JNZ KX_01 ;if so ignore =07FD F6C140 TEST CL,CAPSLOCK ;Check for case toggle =0800 7417 0819 JZ KX_02 =0802 3C41 CMP AL,'A' ;check for letter =0804 7213 0819 JC KX_02 =0806 3C5B CMP AL,'Z'+1 =0808 7208 0812 JC KX_03 =080A 3C61 CMP AL,'a' =080C 720B 0819 JC KX_02 =080E 3C7B CMP AL,'z'+1 =0810 7307 0819 JNC KX_02 =0812 3420 KX_03: XOR AL,20H ;Flip case =0814 EB03 0819 JMPS KX_02 =0816 B8FFFF KX_01: MOV AX,-1 ;-1 = no key =0819 3DFFFF KX_02: CMP AX,-1 ;z = no key =081C C3 RET = = = ;------- = SPECIAL: = ;------- = = ;Key just pressed requires special handling. = ;(This is not really a subroutine, but an extension = ;of key_xlate. Entry is only from a jump from = ;key_xlate. All special handlers exit by jumping = ;back into key_xlate.) = ;in al = negative of special function number. = ; cl = shift state =081D F6D8 NEG AL =081F D0E0 SHL AL,1 =0821 8AD8 MOV BL,AL =0823 2AFF SUB BH,BH =0825 2EFFA7C607 R JMP SPECIALS-2[BX] = = ;------------------------- = ;special function handlers = ;------------------------- = = ;Some are not yet implemented. (Some never will be.) = RESET: CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 33 = BREAK: = PAUSE: = PRTSCRN: = IGNORE: =082A E9E9FF  0816 JMP KX_01 ;ignore = ;Most of these just keep track of shift state = RIGHTSIDE: =082D B501 MOV CH,RIGHTSHIFT =082F EB1C 084D JMPS SETSHIFT = LEFTSIDE: =0831 B502 MOV CH,LEFTSHIFT =0833 EB18 084D JMPS SETSHIFT = CONTROLKEY: =0835 B504 MOV CH,CNTLSTATE =0837 EB14 084D JMPS SETSHIFT = ALTKEY: =0839 B508 MOV CH,ALTERNATE =083B EB10 084D JMPS SETSHIFT = SCROLLKEY: =083D B510 MOV CH,SCROLLLOCK =083F EB15 0856 JMPS TOGSHIFT = NUMKEY: =0841 B520 MOV CH,NUMLOCK =0843 EB11 0856 JMPS TOGSHIFT = CAPSKEY: =0845 B540 MOV CH,CAPSLOCK =0847 EB0D 0856 JMPS TOGSHIFT = INSKEY: =0849 B580 MOV CH,INSSTATE =084B EB09 0856 JMPS TOGSHIFT = ;Set shift bit by open/release of key. (For keys such = ;as shift, which must be held down.) = SETSHIFT: =084D 0ACD OR CL,CH =084F F6C480 TEST AH,80H =0852 7409 085D JZ SS_00 =0854 7505 085B JNZ SS_01 = ;Toggle shift bit. (For lock type keys) = TOGSHIFT: =0856 F6C480 TEST AH,80H =0859 7502 085D JNZ SS_00 ;Ignore release =085B 32CD SS_01: XOR CL,CH =085D 880E963E SS_00: MOV SHIFTS,CL =0861 80FC52 CMP AH,INSCODE  ;Ins also returns a =0864 75B0 0816 JNZ KX_01 ;code, others do not =0866 2AC0 SUB AL,AL =0868 E9AEFF 0819 JMP KX_02 = = = ;-------- = KEY_SCAN: = ;-------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 34 = = ;Check keyboard buffer. = ;Out: nz, ah=-1, al=keycode (if key is ready ) = ; z, ah=0 ( if no key is ready) = ;note: may be called with interrupts on or off. If = ; interrupts are on, 'no key ready' means 'no = ; key was ready when this routine was called'. = ; If interrupts are off 'no key ready' means 'no = ; key will be ready until interrupts are turned = ; on'. =086B 9C PUSHF =086C FA CLI =086D 2BC0 SUB AX,AX ;prepare, no key =086F 833E993E00 CMP K_INDEX,0 ;Check for empty buf =0874 741E 0894 JZ KS_00 =0876 FECC DEC AH =0878 A09B3E MOV AL,K_BUFFER ;Grab character =087B FF0E993E DEC K_INDEX =087F 7413 0894 JZ KS_00 ;Any other left =0881 06 PUSH ES ;in buffer. =0882 8CD9 MOV CX,DS ;If so move them =0884 8EC1 MOV ES,CX ;up. =0886 BF9B3E MOV DI,OFFSET K_BUFFER =0889 8BF7 MOV SI,DI =088B 46 INC SI =088C 8B0E993E MOV CX,K_INDEX =0890 FC  CLD =0891 F3A4 REP MOVSB =0893 07 POP ES =0894 9D KS_00: POPF =0895 0AE4 OR AH,AH =0897 C3 RET = = = ;--------- = KEY_CHECK: = ;--------- = = ;Check if key is ready. = ;This gobbles up non-return key codes ( key releases, = ;shifts ). This routine does not enable interrupts, = ;see comment with key_scan. = ;out ax = return code = ; or if there is no return code ax = -1 =0898 E8D0FF 086B KC_01: CALL KEY_SCAN ;Check buffer =089B 7408 08A5 JZ KC_00 =089D E842FF 07E2 CALL KEY_XLATE ;Translate =08A0 3DFFFF CMP AX,-1 ;If no return code =08A3 74F3 0898 JZ KC_01 ;try again. =08A5 C3 KC_00: RET = = CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 35 = ;-------- = KEY_STAT: = ;-------- = = ;PC like status call. Character codes are returned, = ;but character is not used up. = ;out ax = return code = ; or if there is no return code ax = -1 =08A6 A1CD3E MOV AX,LASTKEY =08A9 3DFFFF CMP AX,-1 =08AC 7508 08B6 JNZ KS_10 =08AE E8E7FF 0898 CALL KEY_CHECK =08B1 7403 08B6 JZ KS_10 =08B3 A3CD3E MOV LASTKEY,AX =08B6 C3 KS_10: RET = = = ;------ =  KEY_IN: = ;------ = = ;Yet another way to read keys. This one will not = ;return until a valid return code is found. Waiting = ;is done by flagwait interrupt. So interrupt may be = ;intercepted to avoid a hard wait loop. =08B7 E8ECFF 08A6 KI_02: CALL KEY_STAT ;Key ready? =08BA 7514 08D0 JNZ KI_00 =08BC FA CLI ;Try again with =08BD E8E6FF 08A6 CALL KEY_STAT ;interrupts off. =08C0 750D 08CF JNZ KI_01 ;Still not ready? =08C2 8A16983E MOV DL,K_FLAG ;If not do flagwait =08C6 B184 MOV CL,DEV_WAITFLAG =08C8 2AF6 SUB DH,DH =08CA CDFF INT XINT =08CC FB STI =08CD EBE8 08B7 JMPS KI_02 =08CF FB KI_01: STI ;Have key. =08D0 C706CD3EFFFF KI_00: MOV LASTKEY,-1 ;Mark as used =08D6 C3 RET = = = ;---------- = KEY_SHIFTS: = ;---------- = = ;PC like call to check shift status. =08D7 A0963E MOV AL,SHIFTS =08DA C3 RET = = ;----- = KEY_8: = ;----- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 36 = = ;Split up function keys for programs that can only = ;handle 8 bit codes. =08DB E8D9FF 08B7 CALL KEY_IN =08DE 0AC0 OR AL,AL ;Function key? =08E0 7504 08E6 JNZ K8_00 ;If so save key code =08E2 8826CD3E MOV BYTE PTR LASTKEY,AH ;for next time =08E6 C3 K8_00: RET = = = ;------- = RAW_KEY: = ;------- = = ;Read raw keyboard character = ;out al = key code =08E7 BA0003 MOV DX,300H =08EA EC IN AL,DX =08EB 50 PUSH AX =08EC B080 MOV AL,KBENABLE ;Keyboard strobe =08EE E84700 0938 CALL VPORTOFF =08F1 B080 MOV AL,KBENABLE =08F3 E84A00 0940 CALL VPORTON =08F6 B80E00 MOV AX,14 ;Tell int. controller =08F9 BA22FF MOV DX,IPC+EOI ;I'm done =08FC EF OUT DX,AX =08FD 58 POP AX =08FE C3 RET = = = = ;---------- = I_KEYBOARD: = ;---------- = = ;Interrupt driven keyboard input service routine. = ;Key is read from keyboard and put into buffer. If = ;buffer is full, key is discarded. No decoding is = ;done, raw scan code is buffered. If someone is = ;waiting for this interrupt then the setflag interrupt = ;is called. =08FF 50 PUSH AX ;Save registers =0900 53 PUSH BX =0901 51 PUSH CX =0902 52 PUSH DX =0903 55 PUSH BP =0904 56 PUSH SI =0905 57 PUSH DI =0906 1E PUSH DS =0907 2E8E1EE90A R MOV DS,DATASEG ;Get scan code =090C BA0003 MOV DX,300H =090F EC IN AL,DX CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 37 =0910 8B3E993E MOV DI,K_INDEX ;Get buffer index =0914 83FF50 CMP DI,K_BUFSIZE ;full? =0917 7309 0922 JNC IK_00 =0919 88859B3E MOV K_BUFFER[DI],AL ;Stuff into buffer =091D 47 INC DI =091E 893E993E MOV K_INDEX,DI ;New index =0922 8A16983E IK_00: MOV DL,K_FLAG ;Some one waiting? =0926 B185 MOV CL,DEV_SETFLAG =0928 2AF6 SUB DH,DH =092A CDFF INT XINT =092C E8B8FF 08E7 IK_01: CALL RAW_KEY =092F 1F POP DS =0930 5F POP DI =0931 5E POP SI =0932 5D POP BP =0933 5A POP DX =0934 59 POP CX =0935 5B POP BX =0936 58 POP AX =0937 CF IRET = = = = ;Video port control. = ;Vport has bits for both video and keyboard control. = ;These routines can turn on/off selected bits on = ;this port without disturbing the others. = = ;-------- = VPORTOFF: = ;-------- = = ;Turn off bits on vport. = ;in al = bit mask =0938 F6D0 NOT AL =093A 2006973E AND VPORTSTATE,AL =093E EB04 0944 JMPS VP_00 = = ;------- = VPORTON: =  ;------- = = ;Turn no bits of vport. = ;in al = bit mask =0940 0806973E OR VPORTSTATE,AL =0944 BA0003 VP_00: MOV DX,VPORT =0947 A0973E MOV AL,VPORTSTATE =094A EE OUT DX,AL =094B C3 RET = = = ;--------- CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 38 = XINT_SERV: = ;--------- = = ;Interrupt waiting bookkeeping = ;Waiting for interrupts is done as follows: = ; Interrupt service routine generates INT 255 with = ; cx = 133 and dl = interrupt wait number. = ; Routine waiting for an interrupt does an INT 255 = ; cx = 132 and dl = interrupt wait number. INT 255 = ; returns when interrupt occurs. = ;This method helps separate the waiting and service = ;routines. All communication between these routines = ;are via INT 255. = ;Also wait loops are not fixed in ROM. Someone could = ;trap interrupt 255 and make better use of the cpu = ;while waiting for an interrupt to occur. = ;Presently only keyboard input uses this interrupt. = ;Keyboard input uses wait flag #18. There is room = ;for 30 flags. =094C 80F985 CMP CL,DEV_SETFLAG ;Setting flag? =094F 7505 0956 JNZ XI_01 =0951 E80B00 095F CALL SET_FLAG =0954 EB08 095E JMPS XI_00 =0956 80F984 XI_01: CMP CL,DEV_WAITFLAG ;Waiting for flag? =0959 7503 095E JNZ XI_02 =095B E81700 0975 CALL WAIT_FLAG = XI_02: =095E CF XI_00: IRET = = = ;-------- = SET_FLAG: = ;-------- = = ;Set interrupt flag to show interrupt has occured. =095F 2BC0 SUB AX,AX =0961 8AF0 MOV DH,AL =0963 8BDA MOV BX,DX =0965 F687CF3E01 TEST I_FLAGS[BX],WAITING =096A 7501 096D JNZ SF_00 =096C 48 DEC AX =096D 80A7CF3EFE SF_00: AND I_FLAGS[BX],NOT WAITING =0972 2BDB SUB BX,BX =0974 C3 RET = = = ;--------- = WAIT_FLAG: = ;--------- = = ;Wait for interrupt to happen =0975 2BC0 SUB AX,AX CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 39 =0977 8AF0 MOV DH,AL =0979 8BDA MOV BX,DX =097B F687CF3E01 TEST I_FLAGS[BX],WAITING =0980 750E 0990 JNZ WF_01 =0982 808FCF3E01 OR I_FLAGS[BX],WAITING =0987 FB STI =0988 F687CF3E01 WF_00: TEST I_FLAGS[BX],WAITING =098D 75F9 0988 JNZ WF_00 =098F 40 INC AX =0990 FB WF_01: STI =0991 48 DEC AX =0992 2BDB SUB BX,BX =0994 C3 RET = INCLUDE VDISK.A86 = = = = = ;************************************************ = ;*  * = ;* Slicer Video Expansion Board * = ;* Disk ROM Calls * = ;* * = ;************************************************ = = = ;IBM rom disk calls emulation = = = ;Slicer monitor definitions = DUMMY DSEG COMMON 'EMPTY' = ORG 84F3H =84F3 DSKSEG RW 1 ;Tranfer Segment =84F5 DSKMEM RW 1 ;Transfer Offset =84F7 DSKNUM RB 1 ;Disk number =84F8 DSKTRACK RW 1 ;Track number =84FA DSKSECTOR RB 1 ;Sector num. (bit 7 = side 2) = = 00FB MONITOR EQU 251 ;Monitor entry interrupt = 0008 READ  EQU 8 ;Read sector function number = 0009 WRITE EQU 9 ;Write sector function number = = = = CSEG = ;Null operation. = ;out ax = 0; = ; nc = DISK_RESET: = DISK_STATUS: = DISK_NULL: CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 40 =0995 2BC0 SUB AX,AX =0997 C3 RET = = ;----------- = DISK_FORMAT: = ;----------- = = ;Format track. = ;Not implemented. Does verify so error is returned = ;unless track is already formatted. = =0998 B101 MOV CL,1 =099A B009 MOV AL,9 = = = ;----------- = DISK_VERIFY: = ;----------- = = ;Verify sector. = ;Sectors are read into ROM area. =099C BF00F8 MOV DI,0F800H =099F 8EC7 MOV ES,DI =09A1 BB0000 MOV BX,0 = = = ;--------- = DISK_READ: = ;--------- = = ;Read sector(s) =09A4 BE0800 MOV SI,READ =09A7 E90300 09AD JMP DISK_OP = = = ;---------- = DISK_WRITE: = ;---------- = = ;Write sector(s) =09AA BE0900 MOV SI,WRITE = = = ;------- = DISK_OP: = ;------- = = ;Common code for reads and writes. =09AD BF00F8 MOV DI,0F800H ;Monitor variables =09B0 8EDF MOV DS,DI =09B2 891EF584 MOV DSKMEM,BX ;Set disk parameters =09B6 8C06F384 MOV DSKSEG,ES CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 41 =09BA 8816F784 MOV DSKNUM,DL =09BE D0E2 SHL DL,1 ;Side is hidden in =09C0 D0EE SHR DH,1 ;Sector number =09C2 D0D9 RCR CL,1 =09C4 880EFA84 MOV DSKSECTOR,CL =09C8 8ACD MOV CL,CH =09CA 2AED SUB CH,CH =09CC 890EF884 MOV DSKTRACK,CX =09D0 8AC8 MOV CL,AL =09D2 8BDE D_LP: MOV BX,SI ;Call monitor =09D4 CDFB INT MONITOR =09D6 750C 09E4 JNZ D_ERR =09D8 8106F5840002 ADD DSKMEM,512 ;Next sector =09DE FE06FA84 INC DSKSECTOR =09E2 E2EE 09D2 LOOP D_LP =09E4 8AE0 D_ERR: MOV AH,AL =09E6 80FC01 CMP AH,1 ;Set carry by error =09E9 F5 CMC ;code. =09EA C3 RET = = ;Notes = ; Reads / Writes assume IBM type floppies = ; 5-1/4", 512 byte sectors. = ; These routines should not be used with other formats = ; Also it is assumed that the monitor has been set = ; up for this disk format. = = ; Error codes returned are 1797 codes, not nec. = include Vinit.a86 = = =  ;************************************************ = ;* 07/18/85 * VINIT .A86 * VERSION 1.2 * = ;************************************************ = ;* * = ;* Slicer Video Expansion Board * = ;* Initialization * = ;* * = ;************************************************ = = ;1.1 original version - 3/28/85 = ;1.2 additional retries added to successfully initialize keyboard - 7/18/85 = = DSEG = =0002 0100 TRIES DW 1 ;NUMBER OF RESET TRIES = = ; = CSEG = INIT: =09EB 06 PUSH ES CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 42 =09EC 1E PUSH DS =09ED 8CC8 MOV AX,CS =09EF 8ED8 MOV DS,AX =09F1 2E8E06E90A R MOV ES,DATASEG =09F6 BA0003 MOV DX,300H =09F9 B0F7 MOV AL,0F7H ;Initialize VPORT =09FB EE OUT DX,AL ;(shared by video and =09FC 26A2973E MOV ES:VPORTSTATE,AL ;keyboard). =0A00 BAD803 MOV DX,3D8H =0A03 B02D MOV AL,2DH =0A05 EE OUT DX,AL =0A06 42 INC DX =0A07 2AC0 SUB AL,AL =0A09 EE OUT DX,AL =0A0A BAB403 MOV DX,3B4H =0A0D 268916903E MOV ES:ADR_6845,DX ;Set 6845 location =0A12 26C706923E0C MOV ES:CURSOR_MODE,0B0CH ;And cursor 0B =0A19 BFCF3E MOV DI,OFFSET I_FLAGS ;Clear int. flags =0A1C B91E00 MOV CX,30 =0A1F 2BC0 SUB AX,AX =0A21 F3AA REP STOSB =0A23 2E8E1EE90A R MOV DS,DATASEG =0A28 C706ED3E0000 MOV T_SECS,0 ;Time = 0 =0A2E C706EF3E0000 MOV T_HIGH,0 =0A34 C706F13E0000 MOV T_LOW,0 =0A3A C606963E00 MOV SHIFTS,0 ;No shift keys active =0A3F C706943EFFFF MOV CONKEY,-1 ;No key waiting =0A45 C706993E0000 MOV K_INDEX,0 ;Empty input buffer =0A4B C606983E12 MOV K_FLAG,0DH+5 ;Keyboard interrupt flag =0A50 C706CD3EFFFF MOV LASTKEY,-1 =0A56 E84201 0B9B CALL KBD_INIT ;Look for keyboard =0A59 0C02  OR AL,VID_ACTIVE ;Return value =0A5B 8A26973E MOV AH,VPORTSTATE =0A5F 50 PUSH AX =0A60 2BC0 SUB AX,AX =0A62 8EC0 MOV ES,AX ;Setup IBM like =0A64 26C706FC034C R MOV VXINT,OFFSET XINT_SERV ;int. vectors 09 R =0A6B 268C0EFE03 MOV VXINT+2,CS =0A70 26C70640004A R MOV VINT10,OFFSET ENTER10 00 R =0A77 268C0E4200 MOV VINT10+2,CS =0A7C 26C706580080 R MOV VINT16,OFFSET ENTER16 00 R =0A83 268C0E5A00 MOV VINT16+2,CS =0A88 26C706F00367 R MOV VDSKINT,OFFSET ENTER13 00 R =0A8F 268C0EF203 MOV VDSKINT+2,CS =0A94 26C7067400EB R MOV VP6845,OFFSET P6845 0A R =0A9B 268C0E7600 MOV VP6845+2,CS CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 43 =0AA0 26C7065C0099 R MOV VINT17,OFFSET ENTER17 00 R =0AA7 268C0E5E00 MOV VINT17+2,CS =0AAC 26C706480019 R MOV VINT12,OFFSET MEM 10 R =0AB3 268C0E4A00 MOV VINT12+2,CS =0AB8 26C706440024 R MOV VINT11,OFFSET EQUIPMENT 10 R =0ABF 268C0E4600 MOV VINT11+2,CS =0AC4 26C70668002E R MOV VTIME,OFFSET TIME_OF_DAY 10 R =0ACB 268C0E6A00 MOV VTIME+2,CS =0AD0 26C7061004FE MOV ES:EQUIP,40FEH 40 =0AD7 2EA1E90A R MOV AX,DATASEG =0ADB 8EC0 MOV ES,AX =0ADD 8ED8 MOV DS,AX =0ADF B80700 MOV AX,7 ;Set screen mode 7 =0AE2 E8A2F8 0387 CALL SET_MODE =0AE5 58 POP AX =0AE6 1F POP DS =0AE7 07 POP ES =0AE8 C3 RET = =0AE9 00B0 DATASEG DW 0B000H = = ;Tables for prgramming the 6845. =0AEB 38282D0A1F06 p6845 db 038h,028h,02dh,00ah,01fh,006h,019h 19 =0AF2 1C02070607 db 01ch,002h,007h,006h,007h =0AF7 00000000 db 0,0,0,0 = 0010 p6845_len equ OFFSET $ - p6845 = =0AFB 71505A0A1F06 db 071h,050h,05ah,00ah,01fh,006h,019h 19 =0B02 1C02070607 db 01ch,002h,007h,006h,007h =0B07 00000000 db 0,0,0,0 = =0B0B 38282D0A7F06 db 038h,028h,02dh,00ah,07fh,006h,064h 64 =0B12 7002010607 db 070h,002h,001h,006h,007h =0B17 00000000 db 0,0,0,0 = =0B1B 6150520F1906 db  061h,050h,052h,00fh,019h,006h,019h 19 =0B22 19020D0B0C db 019h,002h,00dh,00bh,00ch =0B27 FFFF0000 db 0ffh,0ffh,0,0 = = ;Mode parameters = CDUMMY CSEG COMMON 'empty' ! ORG 0 =0000 MODE_FLAGS RB 1 ;Flags = 0001 MF_EXPANSION EQU 1 ; On expansion slot CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 44 = 0002 MF_GRAPHIC EQU 2 ; In graphics mode =0001 P6845_OFFSET RW 1 ;Select one of the = ; above tables =0003 CONTROL_REG RW 1 ;Initial 6845 control/ = ; color register value =0005 ROW_SIZE RW 1 ;Row size =0007  SCREEN_SIZE RW 1 ;Screen size = ;NOTE row_size, screen_size are in bytes for character = ; modes and 'bytes if this were a character mode' for = ; graphic modes. =0009 NUM_PAGES RB 1 =000A INIT_CHAR RW 1 ;Clear screen character =000C RAM_BASE RW 1 ;Screen segment = 000E MD_LEN EQU OFFSET $ = = CSEG = =0B2B MODE_DATA RW 0 = ;Mode 0 =0B2B 01 DB 01H ;Flags =0B2C 0000 DW 0*P6845_LEN =0B2E 2C DB 02CH ;Control register =0B2F 00 DB 0 ;Color register =0B30 5000 DW 80 ;Row size =0B32 D007 DW 2000 ;Screen size =0B34 08 DB 8 ;Number of pages =0B35 2007 DW 0720H ;Initial character =0B37 00B8 DW 0B800H ;RAM base segment = ;Mode 1 =0B39 01 DB 01H ;Flags =0B3A 0000 DW 0*P6845_LEN =0B3C 28 DB 028H ;Control register =0B3D 00 DB 0 ;Color register =0B3E 5000 DW 80 ;Row size =0B40 D007 DW 2000 ;Screen size =0B42 08 DB 8 ;Number of pages =0B43 2007 DW 0720H ;Initial character =0B45 00B8 DW 0B800H ;RAM base segment = ;Mode 2 =0B47 01 DB 01H ;Flags =0B48 1000 DW 1*P6845_LEN =0B4A 2D DB 02DH ;Control register =0B4B 00 DB 0 ;Color register =0B4C A000 DW 160 ;Row size =0B4E A00F DW 4000 ;Screen size =0B50 04 DB 4 ;Number of pages =0B51 2007 DW 0720H ;Initial character =0B53 00B8 DW 0B800H ;RAM base segment = ;Mode 3 =0B55 01 DB 01H ;Flags =0B56 1000 DW 1*P6845_LEN =0B58 29 DB 029H ;Control register CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 45 =0B59 00 DB 0 ;Color register =0B5A A000 DW 160 ;Row size =0B5C A00F DW 4000 ;Screen size =0B5E 04 DB 4 ;Number of pages =0B5F 2007 DW 0720H ;Initial character =0B61 00B8 DW 0B800H ;RAM base segment = ;Mode 4 =0B63 03 DB 03H ;Flags =0B64 2000 DW 2*P6845_LEN =0B66 2A DB 02AH ;Control register =0B67 00 DB 0 ;Color register =0B68 5000 DW 80 ;Row size =0B6A D007 DW 2000 ;Screen size =0B6C 01 DB 1 ;Number of pages =0B6D 0000 DW 0000H ;Initial character =0B6F 00B8 DW 0B800H ;RAM base segment = ;Mode 5 =0B71 03 DB 03H ;Flags =0B72 2000 DW 2*P6845_LEN =0B74 2E DB 02EH ;Control register =0B75 00 DB 0 ;Color register =0B76 5000 DW 80 ;Row size =0B78 D007 DW 2000 ;Screen size =0B7A 01 DB 1 ;Number of pages =0B7B 0000 DW 0000H ;Initial character =0B7D 00B8 DW 0B800H ;RAM base segment = ;Mode 6 =0B7F 03 DB 03H ;Flags =0B80 2000 DW 2*P6845_LEN =0B82 1E DB 01EH ;Control register =0B83 07 DB 7 ;Color register =0B84 A000 DW 160 ;Row size =0B86 A00F DW 4000 ;Screen size =0B88 01 DB 1 ;Number of pages =0B89 0000 DW 0000H ;Initial character =0B8B 00B8 DW 0B800H ;RAM base segment = ;Mode 7 =0B8D 00  DB 00H ;Flags =0B8E 3000 DW 3*P6845_LEN =0B90 2C DB 02CH ;Control register =0B91 07 DB 7 ;Color register =0B92 A000 DW 160 ;Row size =0B94 A00F DW 4000 ;Screen size =0B96 04 DB 4 ;Number of pages =0B97 2007 DW 0720H ;Initial character =0B99 00B0 DW 0B000H ;RAM base segment = = = = = 0002 VID_ACTIVE EQU 2 = 0001 KBD_ACTIVE EQU 1 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 46 = = = = ;-------- = KBD_INIT: = ;-------- = = ;Keyboard interrupt set up. =0B9B C70602000200 R MOV TRIES,2 ;NUMBER OF KBD RESET TRIES =0BA1 BA3CFF INIT1: MOV DX,IPC+INT2 ;Level trig. interrupt =0BA4 B81F00 MOV AX,1FH =0BA7 EF OUT DX,AX =0BA8 B0C0 MOV AL,KBCLOCK+KBENABLE =0BAA E88BFD 0938 CALL VPORTOFF =0BAD B080 MOV AL,KBENABLE =0BAF E88EFD 0940 CALL VPORTON =0BB2 B550 MOV CH,80 =0BB4 E2FE 0BB4 KLP0: LOOP KLP0 =0BB6 B0C0 MOV AL,KBCLOCK+KBENABLE =0BB8 E885FD 0940 CALL VPORTON =0BBB BA2EFF MOV DX,IPC+INTREQ =0BBE ED KLP1: IN AX,DX ;Wait for int attempt =0BBF A840 TEST AL,40H =0BC1 E1FB 0BBE LOOPZ KLP1 =0BC3 750A 0BCF JNZ KLP2 ;interrupt received, continue =0BC5 832E020001 R SUB TRIES,1 ;try again if no interrupt =0BCA 7442 0C0E JZ NOKEY =0BCC E9D2FF 0BA1 JMP INIT1 =0BCF C70602000500 R KLP2: MOV TRIES,5 ;reset number of tries =0BD5 BA0003 KLP8: MOV DX,KBD =0BD8 EC IN AL,DX =0BD9 3CAA CMP AL,0AAH ;look for keyboard response =0BDB 740A 0BE7 JZ TRYOK ;received =0BDD 832E020001 R SUB TRIES,1 ;no - try again =0BE2 742A 0C0E JZ NOKEY ;reset keyboard =0BE4 E9EEFF 0BD5 JMP KLP8 =0BE7 B080 TRYOK: MOV AL,KBENABLE =0BE9 E84CFD 0938 CALL VPORTOFF =0BEC B080 MOV AL,KBENABLE =0BEE E84FFD 0940 CALL VPORTON =0BF1 06 PUSH ES ;Set interrupt vector =0BF2 2BC0 SUB AX,AX =0BF4 8EC0  MOV ES,AX =0BF6 26C7063800FF R MOV VINT2,OFFSET I_KEYBOARD 08 R =0BFD 268C0E3A00 MOV VINT2+2,CS =0C02 07 POP ES =0C03 BA3CFF MOV DX,IPC+INT2 ;And int. controller =0C06 B81700 MOV AX,17H =0C09 EF OUT DX,AX =0C0A B80100 MOV AX,KBD_ACTIVE =0C0D C3 RET CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 47 = NOKEY: =0C0E 2BC0 SUB AX,AX =0C10 C3 RET = = 0300 VPORT EQU 300H = 0300 KBD EQU 300H = 0080 KBENABLE EQU 80H = 0040 KBCLOCK EQU 40H = = = ;80186 internal addresses = FF00 IPC EQU -100H ;Integrated peripherials cntl base = 003C INT2 EQU 3CH = 002E INTREQ EQU 2EH = 0022 EOI EQU 22H = = 00FF XINT EQU 255 = 00FC DSKINT EQU 252 = = ;********************* = ; INTERRUPT VECTORS = ;********************* = = edummy eseg common 'empty' = ORG 14*4 =0038 VINT2 RW 2 =003C RW 2 =0040 VINT10 RW 2 =0044 VINT11 RW 2 =0048 VINT12 RW 2 =004C RW 2 =0050 RW 2 =0054 RW 2 =0058 VINT16 RW 2 =005C VINT17 RW 2 =0060  RW 2 =0064 RW 2 =0068 VTIME RW 2 = org (01dh*4) =0074 vp6845 rw 2 =0078 rw 2 =007C vchar_set rw 2 = ORG XINT*4 =03FC VXINT RW 2 = ORG DSKINT*4 =03F0 VDSKINT RW 2 = include Vtable.a86 = = = cseg = GCHAR_SET: CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 48 =0C11 000000000000 db 000H,000H,000H,000H,000H,000H,000H,000H 0000 =0C19 7E81A581BD99 db 07EH,081H,0A5H,081H,0BDH,099H,081H,07EH 817E =0C21 7EFFDBFFC3E7 db 07EH,0FFH,0DBH,0FFH,0C3H,0E7H,0FFH,07EH FF7E =0C29 6CFEFEFE7C38 db 06CH,0FEH,0FEH,0FEH,07CH,038H,010H,000H 1000 =0C31 10387CFE7C38 db 010H,038H,07CH,0FEH,07CH,038H,010H,000H 1000 =0C39 387C38FEFE7C db 038H,07CH,038H,0FEH,0FEH,07CH,038H,07CH 387C =0C41 1010387CFE7C db 010H,010H,038H,07CH,0FEH,07CH,038H,07CH 387C =0C49 0000183C3C18 db 000H,000H,018H,03CH,03CH,018H,000H,000H 0000 =0C51 FFFFE7C3C3E7 db 0FFH,0FFH,0E7H,0C3H,0C3H,0E7H,0FFH,0FFH FFFF =0C59 003C66424266 db 000H,03CH,066H,042H,042H,066H,03CH,000H 3C00 =0C61 FFC399BDBD99 db 0FFH,0C3H,099H,0BDH,0BDH,099H,0C3H,0FFH C3FF =0C69 0F070F7DCCCC db 00FH,007H,00FH,07DH,0CCH,0CCH,0CCH,078H CC78 =0C71 3C6666663C18 db 03CH,066H,066H,066H,03CH,018H,07EH,018H 7E18 =0C79 3F333F303070 db 03FH,033H,03FH,030H,030H,070H,0F0H,0E0H F0E0 =0C81 7F637F636367 db 07FH,063H,07FH,063H,063H,067H,0E6H,0C0H E6C0 =0C89 995A3CE7E73C db 099H,05AH,03CH,0E7H,0E7H,03CH,05AH,099H 5A99 = =0C91 80E0F8FEF8E0 db 080H,0E0H,0F8H,0FEH,0F8H,0E0H,080H,000H 8000 =0C99 020E3EFE3E0E db 002H,00EH,03EH,0FEH,03EH,00EH,002H,000H 0200 =0CA1 183C7E18187E db 018H,03CH,07EH,018H,018H,07EH,03CH,018H 3C18 =0CA9 666666666600 db 066H,066H,066H,066H,066H,000H,066H,000H 6600 =0CB1 7FDBDB7B1B1B db 07FH,0DBH,0DBH,07BH,01BH,01BH,01BH,000H 1B00 =0CB9 3E63386C6C3C db 03EH,063H,038H,06CH,06CH,03CH,0CCH,078H CC78 =0CC1 000000007E7E db 000H,000H,000H,000H,07EH,07EH,07EH,000H 7E00 =0CC9 183C7E187E3C db 018H,03CH,07EH,018H,07EH,03CH,018H,0FFH 18FF =0CD1 183C7E181818 db 018H,03CH,07EH,018H,018H,018H,018H,000H 1800 =0CD9 181818187E3C db 018H,018H,018H,018H,07EH,03CH,018H,000H CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 49 1800 =0CE1 00180CFE0C18 db 000H,018H,00CH,0FEH,00CH,018H,000H,000H 0000 =0CE9 003060FE6030 db 000H,030H,060H,0FEH,060H,030H,000H,000H 0000 =0CF1 0000C0C0C0FE db 000H,000H,0C0H,0C0H,0C0H,0FEH,000H,000H 0000 =0CF9 002466FF6624 db 000H,024H,066H,0FFH,066H,024H,000H,000H 0000 =0D01 00183C7EFFFF db 000H,018H,03CH,07EH,0FFH,0FFH,000H,000H 0000 =0D09 00FFFF7E3C18 db 000H,0FFH,0FFH,07EH,03CH,018H,000H,000H 0000 = =0D11 000000000000 db 000H,000H,000H,000H,000H,000H,000H,000H 0000 =0D19 307878303000 db 030H,078H,078H,030H,030H,000H,030H,000H 3000 =0D21 6C6C6C000000 db 06CH,06CH,06CH,000H,000H,000H,000H,000H 0000 =0D29 6C6CFE6CFE6C db 06CH,06CH,0FEH,06CH,0FEH,06CH,06CH,000H 6C00 =0D31 307CC0780CF8 db 030H,07CH,0C0H,078H,00CH,0F8H,030H,000H 3000 =0D39 00C6CC183066 db 000H,0C6H,0CCH,018H,030H,066H,0C6H,000H C600 =0D41 386C3876DCCC db 038H,06CH,038H,076H,0DCH,0CCH,076H,000H  7600 =0D49 6060C0000000 db 060H,060H,0C0H,000H,000H,000H,000H,000H 0000 =0D51 183060606030 db 018H,030H,060H,060H,060H,030H,018H,000H 1800 =0D59 603018181830 db 060H,030H,018H,018H,018H,030H,060H,000H 6000 =0D61 00663CFF3C66 db 000H,066H,03CH,0FFH,03CH,066H,000H,000H 0000 =0D69 003030FC3030 db 000H,030H,030H,0FCH,030H,030H,000H,000H 0000 =0D71 000000000030 db 000H,000H,000H,000H,000H,030H,030H,060H 3060 =0D79 000000FC0000 db 000H,000H,000H,0FCH,000H,000H,000H,000H 0000 =0D81 000000000030 db 000H,000H,000H,000H,000H,030H,030H,000H 3000 =0D89 060C183060C0 db 006H,00CH,018H,030H,060H,0C0H,080H,000H 8000 = =0D91 7CC6CEDEF6E6 db 07CH,0C6H,0CEH,0DEH,0F6H,0E6H,07CH,000H 7C00 =0D99 307030303030 db 030H,070H,030H,030H,030H,030H,0FCH,000H FC00 =0DA1 78CC0C3860CC db 078H,0CCH,00CH,038H,060H,0CCH,0FCH,000H CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 50 FC00 =0DA9 78CC0C380CCC db 078H,0CCH,00CH,038H,00CH,0CCH,078H,000H 7800 =0DB1 1C3C6CCCFE0C db 01CH,03CH,06CH,0CCH,0FEH,00CH,01EH,000H 1E00 =0DB9 FCC0F80C0CCC db 0FCH,0C0H,0F8H,00CH,00CH,0CCH,078H,000H 7800 =0DC1 3860C0F8CCCC db 038H,060H,0C0H,0F8H,0CCH,0CCH,078H,000H 7800 =0DC9 FCCC0C183030 db 0FCH,0CCH,00CH,018H,030H,030H,030H,000H 3000 =0DD1 78CCCC78CCCC db 078H,0CCH,0CCH,078H,0CCH,0CCH,078H,000H 7800 =0DD9 78CCCC7C0C18 db 078H,0CCH,0CCH,07CH,00CH,018H,070H,000H 7000 =0DE1 003030000030 db 000H,030H,030H,000H,000H,030H,030H,000H 3000 =0DE9 003030000030 db 000H,030H,030H,000H,000H,030H,030H,060H 3060 =0DF1 183060C06030 db 018H,030H,060H,0C0H,060H,030H,018H,000H 1800 =0DF9 0000FC0000FC db 000H,000H,0FCH,000H,000H,0FCH,000H,000H 0000 =0E01 6030180C1830 db 060H,030H,018H,00CH,018H,030H,060H,000H 6000 =0E09 78CC0C183000 db 078H,0CCH,00CH,018H,030H,000H,030H,000H 3000 = =0E11 7CC6DEDEDEC0 db 07CH,0C6H,0DEH,0DEH,0DEH,0C0H,078H,000H 7800 =0E19 3078CCCCFCCC db 030H,078H,0CCH,0CCH,0FCH,0CCH,0CCH,000H CC00 =0E21 FC66667C6666 db 0FCH,066H,066H,07CH,066H,066H,0FCH,000H FC00 =0E29 3C66C0C0C066 db 03CH,066H,0C0H,0C0H,0C0H,066H,03CH,000H 3C00 =0E31 F86C6666666C db 0F8H,06CH,066H,066H,066H,06CH,0F8H,000H F800 =0E39 FE6268786862 db 0FEH,062H,068H,078H,068H,062H,0FEH,000H FE00 =0E41 FE6268786860 db 0FEH,062H,068H,078H,068H,060H,0F0H,000H F000 =0E49 3C66C0C0CE66 db 03CH,066H,0C0H,0C0H,0CEH,066H,03EH,000H 3E00 =0E51 CCCCCCFCCCCC db 0CCH,0CCH,0CCH,0FCH,0CCH,0CCH,0CCH,000H CC00 =0E59 783030303030 db 078H,030H,030H,030H,030H,030H,078H,000H 7800 =0E61 1E0C0C0CCCCC db 01EH,00CH,00CH,00CH,0CCH,0CCH,078H,000H 7800 =0E69 E6666C786C66 db 0E6H,066H,06CH,078H,06CH,066H,0E6H,000H E600 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 51 =0E71 F06060606266 db 0F0H,060H,060H,060H,062H,066H,0FEH,000H FE00 =0E79 C6EEFEFED6C6 db 0C6H,0EEH,0FEH,0FEH,0D6H,0C6H,0C6H,000H C600 =0E81 C6E6F6DECEC6 db 0C6H,0E6H,0F6H,0DEH,0CEH,0C6H,0C6H,000H C600 =0E89 386CC6C6C66C db 038H,06CH,0C6H,0C6H,0C6H,06CH,038H,000H 3800 = =0E91 FC66667C6060 db 0FCH,066H,066H,07CH,060H,060H,0F0H,000H F000 =0E99 78CCCCCCDC78 db 078H,0CCH,0CCH,0CCH,0DCH,078H,01CH,000H 1C00 =0EA1 FC66667C6C66 db 0FCH,066H,066H,07CH,06CH,066H,0E6H,000H E600 =0EA9 78CCE0701CCC db 078H,0CCH,0E0H,070H,01CH,0CCH,078H,000H 7800 =0EB1 FCB430303030 db 0FCH,0B4H,030H,030H,030H,030H,078H,000H 7800 =0EB9 CCCCCCCCCCCC db 0CCH,0CCH,0CCH,0CCH,0CCH,0CCH,0FCH,000H FC00 =0EC1 CCCCCCCCCC78 db 0CCH,0CCH,0CCH,0CCH,0CCH,078H,030H,000H 3000 =0EC9 C6C6C6D6FEEE db 0C6H,0C6H,0C6H,0D6H,0FEH,0EEH,0C6H,000H C600 =0ED1 C6C66C38386C db 0C6H,0C6H,06CH,038H,038H,06CH,0C6H,000H C600 =0ED9 CCCCCC783030 db 0CCH,0CCH,0CCH,078H,030H,030H,078H,000H 7800 =0EE1 FEC68C183266 db 0FEH,0C6H,08CH,018H,032H,066H,0FEH,000H FE00 =0EE9 786060606060 db 078H,060H,060H,060H,060H,060H,078H,000H 7800 =0EF1 C06030180C06 db 0C0H,060H,030H,018H,00CH,006H,002H,000H 0200 =0EF9 781818181818 db 078H,018H,018H,018H,018H,018H,078H,000H 7800 =0F01 10386CC60000 db 010H,038H,06CH,0C6H,000H,000H,000H,000H 0000 =0F09 000000000000 db 000H,000H,000H,000H,000H,000H,000H,0FFH 00FF = =0F11 303018000000 db 030H,030H,018H,000H,000H,000H,000H,000H 0000 =0F19 0000780C7CCC db 000H,000H,078H,00CH,07CH,0CCH,076H,000H 7600 =0F21 E060607C6666 db 0E0H,060H,060H,07CH,066H,066H,0DCH,000H DC00 =0F29 000078CCC0CC db 000H,000H,078H,0CCH,0C0H,0CCH,078H,000H 7800 =0F31 1C0C0C7CCCCC db 01CH,00CH,00CH,07CH,0CCH,0CCH,076H,000H 7600 CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 52 =0F39 000078CCFCC0 db 000H,000H,078H,0CCH,0FCH,0C0H,078H,000H 7800 =0F41 386C60F06060 db 038H,06CH,060H,0F0H,060H,060H,0F0H,000H F000 =0F49 000076CCCC7C db 000H,000H,076H,0CCH,0CCH,07CH,00CH,0F8H 0CF8 =0F51 E0606C766666 db 0E0H,060H,06CH,076H,066H,066H,0E6H,000H E600 =0F59 300070303030 db 030H,000H,070H,030H,030H,030H,078H,000H 7800 =0F61 0C000C0C0CCC db 00CH,000H,00CH,00CH,00CH,0CCH,0CCH,078H CC78 =0F69 E060666C786C db 0E0H,060H,066H,06CH,078H,06CH,0E6H,000H E600 =0F71 703030303030  db 070H,030H,030H,030H,030H,030H,078H,000H 7800 =0F79 0000CCFEFED6 db 000H,000H,0CCH,0FEH,0FEH,0D6H,0C6H,000H C600 =0F81 0000F8CCCCCC db 000H,000H,0F8H,0CCH,0CCH,0CCH,0CCH,000H CC00 =0F89 000078CCCCCC db 000H,000H,078H,0CCH,0CCH,0CCH,078H,000H 7800 = =0F91 0000DC66667C db 000H,000H,0DCH,066H,066H,07CH,060H,0F0H 60F0 =0F99 000076CCCC7C db 000H,000H,076H,0CCH,0CCH,07CH,00CH,01EH 0C1E =0FA1 0000DC766660 db 000H,000H,0DCH,076H,066H,060H,0F0H,000H F000 =0FA9 00007CC0780C db 000H,000H,07CH,0C0H,078H,00CH,0F8H,000H F800 =0FB1 10307C303034 db 010H,030H,07CH,030H,030H,034H,018H,000H 1800 =0FB9 0000CCCCCCCC db 000H,000H,0CCH,0CCH,0CCH,0CCH,076H,000H 7600 =0FC1 0000CCCCCC78 db 000H,000H,0CCH,0CCH,0CCH,078H,030H,000H 3000 =0FC9 0000C6D6FEFE db 000H,000H,0C6H,0D6H,0FEH,0FEH,06CH,000H 6C00 =0FD1 0000C66C386C db 000H,000H,0C6H,06CH,038H,06CH,0C6H,000H C600 =0FD9 0000CCCCCC7C db 000H,000H,0CCH,0CCH,0CCH,07CH,00CH,0F8H 0CF8 =0FE1 0000FC983064 db 000H,000H,0FCH,098H,030H,064H,0FCH,000H FC00 =0FE9 1C3030E03030 db 01CH,030H,030H,0E0H,030H,030H,01CH,000H 1C00 =0FF1 181818001818 db 018H,018H,018H,000H,018H,018H,018H,000H 1800 =0FF9 E030301C3030 db 0E0H,030H,030H,01CH,030H,030H,0E3H,000H E300 =1001 76DC00000000 db 076H,0DCH,000H,000H,000H,000H,000H,000H CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 53 0000 =1009 0010386CC6C6 db 000H,010H,038H,06CH,0C6H,0C6H,0FEH,000H FE00 ;---------------- 000E LSTOUT EQU 14 CSEG PRINTER_OUT: 1011 B30E MOV BL,LSTOUT 1013 CDFB INT MONITOR 1015 C3  RET PRINTER_INIT: PRINTER_STAT: 1016 B4E0 MOV AH,0E0H 1018 C3 RET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EEH 84EE MEMSIZE RW 1 CSEG MEM: 1019 1E PUSH DS 101A B800F8 MOV AX,0F800H 101D 8ED8 MOV DS,AX 101F A1EE84 MOV AX,MEMSIZE 1022 1F POP DS 1023 CF IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 410H 0410 EQUIP RW 1 CSEG EQUIPMENT: 1024 1E PUSH DS 1025 2BC0 SUB AX,AX 1027 8ED8  MOV DS,AX 1029 A11004 MOV AX,EQUIP 102C 1F POP DS 102D CF IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EAH 84EA SECONDS RW 1 CSEG TIME_OF_DAY: 102E 1E PUSH DS 102F 80FC01 CMP AH,1 1032 B800F8 MOV AX,0F800H 1035 8ED8 MOV DS,AX CP/M RASM-86 1.2 SOURCE: VID.A86 PAGE 54 1037 A1EA84 MOV AX,SECONDS 103A 2E8E1EE90A R MOV DS,DATASEG 103F 7418 1059 JZ SET_TIME 1041 2B06ED3E SUB AX,T_SECS 1045 BA1200 MOV DX,18 1048 F7E2 MUL DX 104A 0306F13E ADD AX,T_LOW 104E 92 XCHG AX,DX 104F 1306EF3E ADC AX,T_HIGH 1053 8BC8 MOV CX,AX 1055 2BC0 SUB AX,AX 1057 1F POP DS 1058 CF IRET SET_TIME: 1059 A3ED3E MOV T_SECS,AX 105C 8916F13E MOV T_LOW,DX 1060 890EEF3E MOV T_HIGH,CX 1064 1F POP DS 1065 CF IRET END OF ASSEMBLY. NUMBER OF ERRORS: 0. USE FACTOR: 20%  MOV CX,AX 1055 2BC0 SUB AX,AX 1057 1F POP DS 105;1/24/85 ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* version 1.4 * ;* July 18, 1985 * ;************************************************ ; To assemble: ; RASM86 VID ; LINK86 VID ;------------------- ; include files LIST include sxcodes.mac include sxascii.equ INCLUDE SXBDOS.EQU LIST INCLUDE VVARS.A86 ;------------------- ;---- notes -------- ;1/24/85 elh added raw_key keyboard interrupt ;------------------- cseg org 0 ;Video Board ID. Software can read this location to ;determine if video board can be used. First two bytes ;identify video board. Next two bytes are the version ;number. At offset 4 is an initialization entry point. DB 'VD' DW 1 WAKE_UP: CALL INIT RETF cseg ;Entry points to video routines. ;Entry is via a software interrupt. At boot a callf to ;wake_up setup interrupt vectors. Each entry is called ;with a function number in ah. Positive ah emulate ;ibm rom calls. Negative ah for Slicer additions ;Branch tables. ;Video (Int 10H ) VID_LOW: DW SET_MODE DW SET_CTYPE DW SET_CPOS DW READ_CURSOR DW READ_LPEN DW ACT_DISP_PAGE DW SCROLL_UP DW SCROLL_DOWN DW READ_AC_CURRENT DW WRITE_AC_CURRENT DW WRITE_C_CURRENT DW SET_COLOR DW WRITE_DOT DW READ_DOT DW WRITE_TTY DW VIDEO_STATE ; DW NO_OP ; DW FILL_WINDOW VID_LLIMIT EQU (OFFSET $ - OFFSET VID_LOW) / 2 VID_HIGH: DW VIDEO_OUT VID_HLIMIT EQU (OFFSET $ - OFFSET VID_HIGH) / 2 ;Disk ( Int 252 ) ;On the IBM PC this interrupt is at 13H. On the 80186 ;13H is reserved for hardware timer interrupt. So the ;Slicer re-routes disk interrupts to 252. DSK_LOW: DW DISK_RESET DW DISK_STATUS DW DISK_READ DW DISK_WRITE DW DISK_VERIFY DW DISK_FORMAT DSK_LLIMIT EQU (OFFSET $ - OFFSET DSK_LOW) / 2 DSK_HIGH: DSK_HLIMIT EQU (OFFSET $ - OFFSET DSK_HIGH) / 2 ;Keyboard ( int 16H ) KBD_LOW: DW KEY_IN DW KEY_STAT DW KEY_SHIFTS KBD_LLIMIT EQU (OFFSET $ - OFFSET KBD_LOW) / 2 KBD_HIGH:  DW KEY_8 DW VPORTON DW VPORTOFF DW RAW_KEY KBD_HLIMIT EQU (OFFSET $ - OFFSET KBD_HIGH) / 2 ;Printer ( int 17H ) PRN_LOW: DW PRINTER_OUT DW PRINTER_INIT DW PRINTER_STAT PRN_LLIMIT EQU (OFFSET $ - OFFSET PRN_LOW) / 2 PRN_HIGH: PRN_HLIMIT EQU (OFFSET $ - OFFSET PRN_HIGH) / 2 ;Range checks are made for each interrupt. If ah ;holds a legal value then a jump to the common code ;at enter is made. This save registers, calls ;subroutine, restores registers then returns. ;Video ENTER10: PUSH SI CMP AH,VID_LLIMIT JNC ENTER10A MOV SI,OFFSET VID_LOW JMP ENTER ENTER10A: NOT AH CMP AH,VID_HLIMIT JNC NO_ENTRY MOV SI,OFFSET VID_HIGH JMP ENTER NO_ENTRY: POP SI NOT AH IRET ;Disk (looks like int. 13H but really int. 252 ) ENTER13: PUSH SI CMP AH,DSK_LLIMIT JNC ENTER13A MOV SI,OFFSET DSK_LOW JMP ENTER ENTER13A: NOT AH CMP AH,DSK_HLIMIT JNC NO_ENTRY MOV SI,OFFSET DSK_HIGH JMP ENTER ;Keyboard ENTER16: PUSH SI CMP AH,KBD_LLIMIT JNC ENTER16A MOV SI,OFFSET KBD_LOW JMP ENTER ENTER16A: NOT AH CMP AH,KBD_HLIMIT JNC NO_ENTRY MOV SI,OFFSET KBD_HIGH JMP ENTER ;Printer ENTER17: PUSH SI CMP AH,PRN_LLIMIT JNC ENTER17A MOV SI,OFFSET PRN_LOW JMP ENTER ENTER17A: NOT AH CMP AH,PRN_HLIMIT JNC NO_ENTRY MOV SI,OFFSET PRN_HIGH JMP ENTER ;----- ENTER: ;----- ;Common code for interrupt entry. ;in: ah = routine number (range already checked ) ; si = branch table ;For each subroutines ;in: ah, si = unknown( altered by enter) ; al, bx, cx, dx, di, es, ss = set by caller ; ( unaltered by enter ) ; bp = pointer to register save area (on stack) ; ds = Video board data segment ;out: ax, flags = returned to caller ; other registers = restored from stack. ;If it is necessary to return a value in a register ;other than ax and flags then the saved copy of that ;register on the stack should be altered. ;Flags are not saved so caution should be used when ;altering flags such as I and D. PUSH BP MOV BP,SP PUSH WORD PTR 8[BP] POPF PUSH DI PUSH DX PUSH CX PUSH BX MOV BL,AH SUB BH,BH SHL BX,1 ADD SI,BX POP BX PUSH BX PUSH DS PUSH ES MOV DS,DATASEG MOV BP,SP CALL CS:WORD PTR[SI] POP ES POP DS POP BX POP CX POP DX POP DI POP BP POP SI RETF 2 ;Offsets into stack (relative to bp) for orignal/ ;return register values. SDUMMY SSEG COMMON 'EMPTY' ! ORG 0 RES RW 1 RDS RW 1 RBX RW 1 RCX RW 1 RDX RW 1 RDI RW 1 RBP RW 1 RSI RW 1 CSEG WAIT EQU 1 ;---------------- ;Include files INCLUDE VIDEO.A86 INCLUDE VKEYS.A86 INCLUDE VDISK.A86 include Vinit.a86 include Vtable.a86 ;---------------- LSTOUT EQU 14 CSEG PRINTER_OUT: MOV BL,LSTOUT INT MONITOR RET PRINTER_INIT: PRINTER_STAT: MOV AH,0E0H RET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EEH MEMSIZE RW 1 CSEG MEM: PUSH DS MOV AX,0F800H MOV DS,AX MOV AX,MEMSIZE POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 410H EQUIP RW 1 CSEG EQUIPMENT: PUSH DS SUB AX,AX MOV DS,AX MOV AX,EQUIP POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EAH SECONDS RW 1 CSEG TIME_OF_DAY: PUSH DS CMP AH,1 MOV AX,0F800H MOV DS,AX MOV AX,SECONDS MOV DS,DATASEG JZ SET_TIME SUB AX,T_SECS MOV DX,18 MUL DX ADD AX,T_LOW XCHG AX,DX ADC AX,T_HIGH MOV CX,AX SUB AX,AX POP DS IRET SET_TIME: MOV T_SECS,AX MOV T_LOW,DX MOV T_HIGH,CX POP DS IRET V&RASM-86 1.2 10/31/83_EXTRACODESTACKDATAvsegEMPTYemptyEMPTYemptyDUMMYCDUMMYEDUMMYDATACODESDUMMYVSEGX u8 X H(fXX> VD @$8O^{h @ 8 ͜yTTTTT T TTTTTTTTTT T"T$T&T(T*T,T.T0T2T4T6T8T:TDVs\Ԁs(O^Vs*?Ԁs62Vs6&Ԁsо<VsD ԀsJUvWRQSĜ-TTT TT*T7TCTPT\TiT#*[S. .[YZ_]^5 T5.: t .<u.dGP+6>XÜ+> &>>t+6>>+Μ+tCsON>>t>&> k>t{>;>s>RPP>XXZÀ>+>>HH@@+>8++>r>>+6>Th+OND6>>+0>>+>> >ø >ø+ >éLá,$>>at .>>&>À>|>sÊ>>>&>>t&@@s +>h> TTnt, *&>6>>t, *>6>>tX6>Dȡ>>t< rn 2ȡ>` >T_T2 z tTTT T TTjFDYABCDEHIJK dl$oLMb0c0m:nCjLkP1YTTT T TTTTTTT"T%T(T+T.T1T4T7T:T=T@T ~â>+ >.t>+&t.\&'C<u.D&>*.t>.D >.D>.D>>>.D  T9~&>>+@É>> Ëʊ*&>*Ká>+6>V>F>6>&>>Nj>>>t{=~z>>Nj>>>tGGP> t $ $ Ë>XRP*&>Z*ZP*XSfP*JXSGP>Q>t>YYX Q>tY+с* u+Ɇ+>+þtȡ>(uT͠pk͠~t z >ࠍ>FPR+6>+ZXVWPSQ>Ɏپ t+Ɏ6|ȁ&& Y[X_TTT T THT2X^. WVQS>؊ [Y^_P. X TJTѠ~B1!2@3#4$5%6^7&8*9(0)-_=+ qQwWeErRtTyYuUiI oOpP[{]} aAsS ~dDfFgGhHjJ kK lL ;:'"`~\|zZxXcCvVbBnNmM ,<.>/?* Š6789--456++1230.+>ttt t*-159=AEI****Ru*+>>t̠>>tَ>F> tB=tá>F=ut>uu >*>à> u&>úPGJ"XPSQRUVW. >>Ps >G>>>aTs& *_^]ZY[X >>>Àu u+>uH>++>u>>u@H+0Z +ñ ǻ ߉و*ȋu S Ȏ. &>-B*&>&> >+. >>>>>>>>B &>P+&L * T;T~T>~k &&@J&B&X&Z&g&&t &v&\&^&H&J&D$&F&h.&j&@. ظ % TT"T.T:TFTRT^TnT,J X8(- qPZ 8(- dpaPR + ,P (P - )  *P .P 0, <rTѠn P.@u .tB><~~<ffffff{>c8llx00000x xflxlf`~s``bf8ll8ff|``xxff|lfxpx0000xx0l88lx00xƌ2fx```~``x`0 xx8l00x |v``|ffxx |vxx8l```v| `lvff0p000x ̧~gx`flxlp00000xxxff|`v| vf`|x 0|004vx0ll8l| 40d00000000v8l| ôËء$+ء<.ء. t+>>>+ϣ>>>=T3tfxpx0000xx0l88lx00xƌ2fx```~``x`0 x 0000 VARIABLES 3E90 ADR_6845 0000 CASE_CODE 0001 CASE_ROUTINE 0332 CNTL_TABLE 3E94 CONKEY 0003 CONTROL_REG 3E8D CRT_MODE 3E92 CURSOR_MODE 0000 CUR_SAVE 0AE9 DATASEG 84F5 DSKMEM 84F7 DSKNUM 84FA DSKSECTOR 84F3 DSKSEG 84F8 DSKTRACK 0410 EQUIP 0344 ESC_TABLE 000A INIT_CHAR 3ECF I_FLAGS 3E98 KBD_DATA 0642 KEYTABLE 3E9B K_BUFFER 3E98 K_FLAG 3E99 K_INDEX 3ECD LASTKEY 3E8E MD_PTR 84EE MEMSIZE 0B2B MODE_DATA 0000 MODE_FLAGS 0009 NUM_PAGES 0AEB P6845 0001 P6845_OFFSET 000C RAM_BASE 000C RBP 0004 RBX 0006 RCX 000A RDI 0002 RDS 0008 RDX 0000 RES 0005 ROW_SIZE 000E RSI 0007 SCREEN_SIZE 84EA SECONDS 3E96 SHIFTS 0002 TRIES 0574 TTY_TABLE 3EEF T_HIGH 3EF1 T_LOW 3EED T_SECS 007C VCHAR_SET 03F0 VDSKINT 0040 VINT10 0044 VINT11 0048 VINT12 0058 VINT16 005C VINT17 0038 VINT2 0074 VP6845 3E97 VPORTSTATE 0068 VTIME 03FC VXINT 3E89 V_ATTRIBUTES 3E80 V_BUFFER 3E8C V_COLOR 3E86 V_CURSOR 3E8A V_ESC_EXT 3E88 V_FLAGS 3E8B V_GRAPHIC 3E84 V_ROWSIZE 3E82 V_SCRNSIZE 0000 NUMBERS 0006 ACK 0008 ALTERNATE 0007 BEL 0008 BS 0018 CAN 0040 CAPSLOCK 0003 CASE_LEN FFC0 CNTL 0004 CNTLSTATE 000D CR 0095 C_ASSIGN 0092 C_ATTACH 00A2 C_CATTACH 006E C_DELIMIT 0093 C_DETACH 0099 C_GET 006D C_MODE 0006 C_RAWIO 0001 C_READ 000A C_READSTR 0094 C_SET 000B C_STAT 0002 C_WRITE 006F C_WRITEBLK 0009 C_WRITESTR 0011 DC1 0012 DC2 0013 DC3 0014 DC4 007F DEL 0083 DEV_POLL 0085 DEV_SETFLAG 0084 DEV_WAITFLAG 0010 DLE 0026 DRV_ACCESS 001B DRV_ALLOCVEC 000D DRV_ALLRESET 001F DRV_DPB 0030 DRV_FLUSH 0027 DRV_FREE 0019 DRV_GET 0065 DRV_GETLABEL 0018 DRV_LOGINVEC 0025 DRV_RESET 001D DRV_ROVEC 000E DRV_SET 0064 DRV_SETLABEL 001C DRV_SETRO 002E DRV_SPACE 00FC DSKINT 0000 DSK_HLIMIT 0006 DSK_LLIMIT 0019 EM 0005 ENQ 0022 EOI 0004 EOT 001B ESC 0017 ETB 0003 ETX 000C FF 001C FS 001E F_ATTACH 0010 F_CLOSE 0013 F_DELETE 0034 F_DMAGET 001A F_DMAOFF 0033 F_DMASEG 002D F_ERRMODE 002A F_LOCK 0016 F_MAKE 002C F_MULTISEC 000F F_OPEN 0098 F_PARSE 006A F_PASSWD 0024 F_RANDREC 0014 F_READ 0021 F_READRAND 0017 F_RENAME 0011 F_SFIRST 0023 F_SIZE 0012 F_SNEXT 0066 F_TIMEDATE 0063 F_TRUNCATE 002B F_UNLOCK 0020 F_USERNUM 0015 F_WRITE 0022 F_WRITERAND 0067 F_WRITEXFCB 0028 F_WRITEZF 001D GS 0009 HT 0052 INSCODE 0080 INSSTATE 003C INT2 002E INTREQ FF00 IPC 0040 KBCLOCK 0300 KBD 0001 KBD_ACTIVE 0004 KBD_HLIMIT 0003 KBD_LLIMIT 0080 KBENABLE 0050 K_BUFSIZE 0002 LEFTSHIFT 000A LF 000E LSTOUT 009E L_ATTACH 00A1 L_CATTACH 009F L_DETACH 00A4 L_GET 00A0 L_SET 0005 L_WRITE 0070 L_WRITEBLK 0036 MC_ABS 003A MC_ALLFREE 0037 MC_ALLOC 0038 MC_ALLOCABS 0039 MC_FREE 000E MD_LEN 0001 MF_EXPANSION 0002 MF_GRAPHIC 00FB MONITOR 0080 M_ALLOC 0082 M_FREE 0015 NAK 0000 NUL 0020 NUMLOCK 0010 P6845_LEN 0000 PRN_HLIMIT 0003 PRN_LLIMIT 009D P_ABORT 002F P_CHAIN 0096 P_CLI 0090 P_CREATE 008D P_DELAY 008E P_DISPATCH 003B P_LOAD 009C P_PDADR 0091 P_PRIORITY 0097 P_RPL 008F P_TERM 0000 P_TERMCPM 008A Q_CREAD 008C Q_CWRITE 0088 Q_DELETE 0086 Q_MAKE 0087 Q_OPEN 0089 Q_READ 008B Q_WRITE 0008 READ 0001 RIGHTSHIFT 0010 SCROLLLOCK 000F SHI 000E SO 0001 SOH 0002 STX 001A SUBB 0016 SYN 000C S_BDOSVER 0032 S_BIOS 00A3 S_OSVER 006B S_SERIAL 009A S_SYSDAT 0069 T_GET 009B T_SECONDS 0068 T_SET 001F US 0004 VF_COL 0001 VF_ESC 0008 VF_EXT 0002 VF_ROW 0002 VID_ACTIVE 0001 VID_HLIMIT 0010 VID_LLIMIT 0300 VPORT 000B VT 0001 WAIT 0001 WAITING 0009 WRITE 00FF XINT 00E0 _BDOS 0000 LABELS 0386 ACT_DISP_PAGE 0839 ALTKEY 082A BREAK 0845 CAPSKEY 00DE CASE 0835 CONTROLKEY 00DE C_00 00EC C_01 0998 DISK_FORMAT 0995 DISK_NULL 09AD DISK_OP 09A4 DISK_READ 0995 DISK_RESET 0995 DISK_STATUS 099C DISK_VERIFY 09AA DISK_WRITE 0036 DSK_HIGH 002A DSK_LOW 09E4 D_ERR 09D2 D_LP 0266 EE_00 00B2 ENTER 004A ENTER10 0056 ENTER10A 0067 ENTER13 0073 ENTER13A 0080 ENTER16 008C ENTER16A 0099 ENTER17 00A5 ENTER17A 1024 EQUIPMENT 0230 ESC_BG_ATT 021D ESC_BOL 0216 ESC_BOS 01A2 ESC_CURPOS 0243 ESC_CURSOR_OFF 023A ESC_CURSOR_ON 0250 ESC_CURSOR_RESTORE 024C ESC_CURSOR_SAVE 01F1 ESC_DELLINE 01AF ESC_DOWN 0224 ESC_EL 020C ESC_EOL 0205 ESC_EOS 01C0 ESC_ERASE 0256 ESC_EXT 0230 ESC_FG_ATT 01C9 ESC_HOME 01DB ESC_INSLINE 01B6 ESC_LEFT 01CE ESC_REVLF 01BB ESC_RIGHT 01A8 ESC_UP 0C11 GCHAR_SET 061A GM_00 063A GM_10 05CA GP_00 05D8 GP_01 05FE GR_MOVSW 0593 GR_POSN 05A8 GR_PUT 0633 GR_REP_MOVSW 05F0 GR_REP_STOSW 05F6 GS_01 082A IGNORE 0922 IK_00 092C IK_01 09EB INIT 0BA1 INIT1 0849 INSKEY 08FF I_KEYBOARD 08E6 K8_00 003C KBD_HIGH 0B9B KBD_INIT 0036 KBD_LOW 08A5 KC_00 0898 KC_01 08DB KEY_8 0898 KEY_CHECK 08B7 KEY_IN 086B KEY_SCAN 08D7 KEY_SHIFTS 08A6 KEY_STAT 07E2 KEY_XLATE 08D0 KI_00 08CF KI_01 08B7 KI_02 0BB4 KLP0 0BBE KLP1 0BCF KLP2 0894 KS_00 08B6 KS_10 07F8 KX_00 0816 KX_01 0819 KX_02 0812 KX_03 0831 LEFTSIDE 078E LOOK_UP 07C2 LU_00 07A4 LU_01 07AE LU_02 07B6 LU_03 1019 MEM 0C0E NOKEY 0063 NO_ENTRY 0841 NUMKEY 082A PAUSE 04B8 POSITION 1016 PRINTER_INIT 1011 PRINTER_OUT 1016 PRINTER_STAT 004A PRN_HIGH 0044 PRN_LOW 082A PRTSCRN 08E7 RAW_KEY 044F READ_AC_CURRENT 0438 READ_CURSOR 0386 READ_DOT 0386 READ_LPEN 082A RESET 082D RIGHTSIDE 083D SCROLLKEY 0506 SCROLL_0 054B SCROLL_1 04E8 SCROLL_DOWN 04CB SCROLL_UP 050F SC_00 052D SC_01 0531 SC_02 051E SC_03 0526 SC_04 0540 SC_05 0542 SC_06 0559 SC_10 04AA SC_20 04AE SC_21 084D SETSHIFT 0499 SET_COLOR 0424 SET_CPOS 0411 SET_CTYPE 095F SET_FLAG 0387 SET_MODE 1059 SET_TIME 096D SF_00 03A2 SM_00 03B4 SM_01 03D9 SM_02 081D SPECIAL 07C8 SPECIALS 085D SS_00 085B SS_01 102E TIME_OF_DAY 0856 TOGSHIFT 0BE7 TRYOK 028F VC_BEL 01B6 VC_BS 027A VC_CR 0274 VC_ESC 0282 VC_LF 0126 VE_00 0124 VE_01 0311 VIDEO_OUT 0583 VIDEO_STATE 0331 VID_00 031D VID_01 0326 VID_02 0028 VID_HIGH 0008 VID_LOW 0292 VID_PUT 0290 VID_PUTC 02DB VI_00 02F4 VI_01 0300 VI_02 0310 VI_03 028E VL_00 0938 VPORTOFF 0940 VPORTON 0944 VP_00 02C1 VP_01 02AB VP_02 02AE VP_03 0180 VS_00 0144 VS_01 0161 VS_02 0159 VS_03 0177 VS_04 017F VS_05 01A0 VS_10 00F0 V_COLUMN 0101 V_ERASE 02C3 V_INESC 0129 V_LFSCROLL 0386 V_NULL 00F9 V_ROW 0135 V_SCROLL 0182 V_SETCUR 0975 WAIT_FLAG 0004 WAKE_UP 0477 WC_00 0479 WC_01 0988 WF_00 0990 WF_01 045E WRITE_AC_CURRENT 047B WRITE_C_CURRENT  0386 WRITE_DOT 0568 WRITE_TTY 0486 WR_00 0493 WR_01 0494 WR_02 094C XINT_SERV 095E XI_00 0956 XI_01 095E XI_02  VI_03 028;VSCREEN.A86 title 'Virtual Screen Handler ' ;*******************************************************; ; ; ; This module contains all code necessary for ; ; full screen buffering on a serial Heath/Zenith ; ; Z29 terminal. ; ; Note: assumes m_alloc in XIOS header has been ; ; initialized to reserve space for screen ; ; images. ; ; Last changed: 2/23/85 JMB ; ; ; ;*******************************************************; include vscreen.equ nolist include system.lib include chrcomm.equ include serdata.equ list ;include system.lib ;include chrcomm.equ ;include serdata.equ dseg extrn mem_alloc:word extrn ocdesctbl:word public screen_image_tbl cseg public vs_init public vs_conout public default_esc public vs_switch public set_up_bx extrn conout1:near extrn serial_out:near eject ;***********************************************; ; VIRTUAL SCREEN INITIALIZATION ; ;***********************************************; ;======; vs_init: ;======; ; mov ax,mem_alloc ; segment address given by GENCCPM mov bx,offset scrn_image0 ; get first screen image table xor ch,ch mov cl,nvcons ; do init for each virtual console init_scrn: ; init each structure with the segment mov vs_screen_seg,ax ; address of its char/attrib buffer add bx,vs_struc_len add ax,((crt_size + 15) shr 4) * 2 loop init_scrn mov ah,vsa_normal ; attribute = normal mov al,blank ; char = blank mov bx,offset scrn_image0 ; with normal attribute byte mov cl,nvcons push es clear_scrn: ; do one clear for each virtual console push cx mov es,vs_screen_seg ; get segment address back sub di,di mov cx,crt_size ; get screen size rep stosw ; paint screen with blanks pop cx add bx,vs_struc_len ; index to next screen structure loop clear_scrn pop es ; we're done ret eject ;*******************************************************; ; ; ; ENTRY POINT FOR VIRTUAL SCREEN UPDATES ; ;  ; ;*******************************************************; ;========; vs_conout: ;========; ; Entry: DL = virtual console # ; CL = character ; Exit: None ; mov bx,dx ; BL = virtual console # shl bx,1 mov bx,screen_image_tbl[bx] ; get virtual screen structure mov al,cl ; Set up AX for subroutines mov ah,dl push ax mov cx,0 ; AH = console #, AL = character call vs_escape_rt ; Points to escape handler if in middle ; of a sequence. Default is CONOUT01. cmp cx,0 ; CX = 0 if in escape sequence jne conout01 ; = ffff if regular char other_char: ; Either we're in the middle of an ; escape sequence or its a special char pop cx ; Fall through to physical output. mov dl,ch xor ch,ch ; Virtual update has been done. jmp conout1 conout01: mov di,offset spec_char_tab ; check if special char (CR,LF,BS,ESC) mov si,offset spec_func_tab ; if so, co_look_up jmps to call co_look_up ; corresponding function jcxz conout02 ; else,update image with simple char jmps other_char conout02: ; simple character handling pop cx ; restore console # and char mov dl,ch xor ch,ch cmp cl,' ' ; don't save ctrl chars in screen image jb conout03 mov di,vs_cursor ; starting point of single char copy push es ; BX = virtual screen structure mov es,vs_screen_seg ; ES = segment of virtual screen mov ah,vs_attrib ; AH = current attribute mov al,cl ; CL,AL = new char stosw pop es ; DI pts to next attribute/char word cmp vs_column,crt_col - 1 ; are we at end of line? jb inc_col ; No: go move cursor one to the right test vs_mode,vsm_no_wrap ; Yes: are we in wrap mode? jnz conout03 ; No: leave cursor alone call carriage_return ; Yes: update virtual cursor call line_feed conout03: jmp conout1 inc_col: call r_right ; updates cursor by one (to the right) jmp conout1 eject ;***********************************************; ; ; ; SPECIAL CHARACTER OUTPUT ROUTINES ; ;  ; ;***********************************************; ;--------------; carriage_return: ;--------------; ; Entry: BX = screen structure ; Exit: BX preserved ; push dx xor dx,dx xchg vs_column,dl ; set column to zero shl dx,1 ; back up cursor sub vs_cursor,dx pop dx ret ;--------; line_feed: ;--------; ; Entry: BX = screen structure ; Exit: BX preserved ; cmp vs_row,crt_row - 1 je lf_scroll ; are we at bottom of screen? jmp d_down ; no, move cursor down a line lf_scroll: push dx xor dl,dl ; yes, adjust top & bottom pointers mov dh,crt_row - 1 call scroll_up pop dx jmp erase_line ;---------; back_space: ;---------; ; Entry: BX = screen structure ; Exit: BX = preserved ; mov di,vs_cursor test di,di ; are we at home position ? jz bs_ret ; yes, ignore backspace cmp vs_column,0 ; are we at the beginning of a line ? je bs_row ; yes, try previous line dec vs_column ; else, simple case: dec # cols jmps bs_set_cursor bs_row: test vs_mode,vsm_no_wrap ; if in nowrap mode, don't back up to jnz bs_ret ; previous line dec vs_row ; else, dec current row and mov al,vs_row mov dl,crt_col - 1 mov vs_column,dl ; show column at end of line push bx push dx mov dh,vs_pcon ; get physical console # call set_up_bx ; get Xmit Q pop dx call ser_position_cursor ; set cursor at end of last line pop bx push bp mov bp,sp ; (Making changes? Be *SURE* this is still correct) and word ptr 6[bp],0FF00h ; change BS to NULL pop bp bs_set_cursor: sub di,2 ; DI = cursor mov vs_cursor,di bs_ret: ret eject ;***************************************; ; ; ; ESCAPE SEQUENCE ROUTINES ; ; ; ;***************************************; ;---------; co_look_up: ;---------; ; Entry: BX = address of screen structure ; AH = device number ; AL = char to scan for ; DI = ptr to lookup table ; SI = function table ; Exit: CX = 0ffffh if special char found ; 0 if no spec char found ; if not spec function, AX & BX preserved ; mov bp,es ! mov dx,ds mov es,dx xor ch,ch ! mov cl,[di] ; first byte of di is length of table mov dx,cx ! inc di repne scasb ; cruise through table for match mov es,bp ; restore ES je lookup_func ; got a match, go get function ret ; else, return with CX = 0 lookup_func: inc cx ; CX = number matched on sub dx,cx ! shl dx,1 ; function number add si,dx call word ptr [si] xor cx,cx ! dec cx ; return with CX = 0ffffh ret ;--------; escape_rt: ;--------; ; Entry: BX = screen structure ; AL = current byte in esc sequence ; Exit: vs_escape_rt = address of next routine to execute ; in this sequence ; mov vs_escape_rt,offset escape1 ret escape1: mov vs_escape_rt,offset default_esc ; assume done with escape mov di,offset esc_tbl ; if more to do, this field mov si,offset esc_func_tbl ; will be set by handler push cx ; save CX to show in esc call co_look_up ; sequence pop cx ret ;-; up: ; ESC A ;-; ; Move up a line ; cmp vs_row,0 ; if at top of screen, ignore it je up_ret sub vs_cursor,crt_col * 2 dec vs_row up_ret: ret ;---; down: ; ESC B ;---; ; Move down a line ; cmp vs_row,crt_row - 1 ; if at bottom of screen, ignore it je down_ret d_down: add vs_cursor,crt_col * 2 inc vs_row down_ret: ret ;----; right: ; ESC C ;----; ; Move right a character ; cmp vs_column,crt_col - 1 ; if at end of screen, ignore it je right_ret r_right: add vs_cursor,2 inc vs_column right_ret: ret ;---; left: ; ESC D ;---; ; Move left a character ; cmp vs_column,0 ; if at beginning of screen, ignore it je left_ret sub vs_cursor,2 dec vs_column left_ret: ret ;-------------; up_with_scroll: ; ESC I ;-------------; ; Move up a line, scrolling down if needed ; cmp vs_row,0 ; if not on the top line ja up ; move the cursor up only push dx xor dl,dl ; else, scroll it down mov dh,crt_row - 1 ; start row = 0, end row = screen bottom call scroll_down ; cursor stays the same pop dx jmp erase_line ;---; save: ; ESC j ;---; ; Save the current cursor position ; mov ah,vs_row ; save row and col in xy mov al,vs_column mov vs_xy,ax mov ax,vs_cursor ; save cursor position mov vs_oldcursor,ax ret ;------; restore: ; ESC k ;------; ; Recall the last saved cursor position ; mov ax,vs_xy mov vs_column,al mov vs_row,ah mov ax,vs_oldcursor mov vs_cursor,ax ret ;------; x_and_y: ; ESC Y ;------; ; Direct cursor addressing (row+32,col+32) ; mov vs_escape_rt,offset xy_row ; wait for row ret xy_row: sub al,32 cmp al,crt_row - 1 ja row_done mov vs_row,al row_done: mov vs_escape_rt,offset xy_col ; wait for column ret xy_col: sub al,32 cmp al,crt_col - 1 jbe xy_set_col mov al,crt_col - 1 xy_set_col: mov vs_column,al ; Set the new column # push cx xor ah,ah mov al,vs_row ; Use new row and column to compute mov cx,crt_col * 2 ; new cursor position. mul cx xor ch,ch mov cl,vs_column shl cx,1 add ax,cx mov vs_cursor,ax pop cx xy_ret: mov vs_escape_rt,offset default_esc ret ;-----------; erase_screen: ; ESC E ;-----------; ; Erase the screen, and home the cursor ; push es ! push cx mov es,vs_screen_seg ; get virtual screen segment mov ax,vsa_normal*256 + ' ' ; put normal attribute with blank mov cx,crt_size ; do entire screen xor di,di ; start at position zero rep stosw pop cx ! pop es ;; jmp home ;---; home: ; ESC H ;---; ; Home the cursor ; xor ax,ax mov vs_cursor,ax mov vs_column,al mov vs_row,al ret ;----------; erase_begin: ; ESC b ;----------; ; Erase to the beginning of the screen from the cursor position ; push es ! push cx mov es,vs_screen_seg ; get virtual screen segment mov ax,vs_cursor ; get number of words to erase from shr ax,1 ; beginning of screen mov cx,ax mov ax,vsa_normal*256 + ' ' ; give them all normal atrributes xor di,di ; start at top of screen rep stosw pop cx ! pop es ret ;--------; erase_end: ; ESC J ;--------; ; Erase to the end of the screen from the cursor position ; push es ! push cx mov es,vs_screen_seg ; get virtual screen segment mov ax,vs_cursor mov di,ax ; erase from cursor to the end shr ax,1 mov cx,crt_size sub cx,ax ; CX = total # words to erase mov ax,vsa_normal*256 + ' ' ; given them all normal attributes rep stosw pop cx ! pop es ret ;---------; erase_line: ; ESC l ;---------; ; Erase the entire line (not delete) ; mov al,vs_row erase_line_al: push es ! push cx ! push dx mov es,vs_screen_seg ; get virtual screen segment xor ah,ah mov cx,crt_col mul cx ; get word offset of current row shl ax,1 ; make it a byte offset mov di,ax ; start erasing here mov ax,vsa_normal*256 + ' ' ; give them all normal attributes rep stosw pop dx ! pop cx ! pop es ret ;--------; erase_bol: ; ESC o ;--------; ; Erase to the beginng of the line ; push es! push cx mov es,vs_screen_seg mov di,vs_cursor ; beginning offset - word xor ch,ch mov cl,vs_column ; number of words to erase on this line inc cx ; including character under cursor mov ax,vsa_normal*256 + ' ' ; give them all normal attributes std rep stosw cld pop cx ! pop es ret ;--------; erase_eol: ; ESC K ;--------; ; Erase to the end of the line ; push es ! push cx ; erase to end of line mov es,vs_screen_seg ; get virtual screen segment mov di,vs_cursor ; start to erase here mov cx,crt_col sub cl,vs_column ; number of words to erase on this line mov ax,vsa_normal*256 + ' ' ; give them all normal attributes rep stosw pop cx ! pop es ret ;----------; insert_line: ; ESC L ;----------; ; Insert a line, pushing the last line off the screen ; push ax ! push dx mov dl,vs_row ; start row mov dh,crt_row - 1 ; ending row call scroll_down ; make room for the new line call erase_line ; erase the old one call carriage_return pop dx ! pop ax ret ;----------; delete_line: ; ESC M ;----------; ; Delete the current line. Bring a blank line in at the bottom ; ; ENTRY: BX = screen structure ; EXIT: BX = same push ax ! push dx mov dl,vs_row ; scroll up first mov dh,crt_row - 1 call scroll_up mov al,crt_row - 1 call erase_line_al ; then erase the line call carriage_return pop dx ! pop ax ret ;----------; delete_char: ; ESC N ;----------; ; Delete the character under the cursor ; push es ! push cx mov es,vs_screen_seg ; get virtual screen segment mov di,vs_cursor mov si,di add si,2 xor ch,ch mov cl,crt_col - 1 sub cl,vs_column push ds ! push es ! pop ds rep movsw mov word ptr 0[di],vsa_normal*256 + ' ' ; put a blank in last column pop ds ! pop cx ! pop es ret ;---------; reverse_on: ; ESC p ;---------; ; Turn the reverse video bit on ; or vs_attrib,vsa_reverse ret ;----------; reverse_off: ; ESC q ;----------; ; Turn the reverse video bit off ; and vs_attrib,not vsa_reverse ret ;----------; graphics_on: ; ESC F ;----------; ; Turn the graphics bit on ; or vs_attrib,vsa_graphics ret ;-----------; graphics_off: ; ESC G ;-----------; ; Turn the graphics bit off ; and vs_attrib,not vsa_graphics ret ;------------; set_attribute: ; ESC s # ('0' <= # <= 'O') ;------------; ; Set the attribute bits to # - '0' ; mov vs_escape_rt,offset set_attrib2 ret set_attrib2: sub al,'0' jb set_not cmp al,31 ja set_not and vs_attrib,vsa_graphics or vs_attrib,al set_not: mov vs_escape_rt,offset default_esc ret ;-----------; keypad_shift: ; ESC t ;-----------; ; Turn the keypad shift bit on ; or vs_mode,vsm_keypadshift ret ;-------------; keypad_unshift: ; ESC u ;-------------; ; Turn the keypad shift bit off ; and vs_mode,not vsm_keypadshift ret ;----------; enable_wrap: ; ESC v ;----------; ; Turn the line-wrap bit on ; and vs_mode,not vsm_no_wrap ret ;-----------; disable_wrap: ; ESC w ;-----------; ; Turn the line-wrap bit off ; or vs_mode,vsm_no_wrap ret ;--------; set_modes: ; ESC x # ('1' <= # <= '9') ;--------; ; Turn mode # on ; mov vs_escape_rt,offset set_mode2 ret set_mode2: mov vs_escape_rt,offset default_esc cmp al,'5' je hide_cursor cmp al,'6' je keypad_shift cmp al,'7' je keypad_alt hide_cursor: ; ESC x 5 or vs_mode,vsm_nocursor ret ;----------; reset_modes: ; ESC y # ('1' <= # <= '9') ;----------; ; Turn mode # off ; mov vs_escape_rt,offset reset_mode2 ret reset_mode2: mov vs_escape_rt,offset default_esc cmp al,'5' je show_cursor cmp al,'6' je keypad_unshift cmp al,'7' je keypad_unalt ret show_cursor: ; ESC y 5 and vs_mode,not vsm_nocursor ret ;---------; keypad_alt: ; ESC = ;---------; ; Turn the alt keypad bit on ; or vs_mode,vsm_keypadalt ret ;-----------; keypad_unalt: ; ESC > ;-----------;  ; Turn the alt keypad bit off ; and vs_mode,not vsm_keypadalt ret eject ;*******************************************************; ; ; ; SUBROUTINES FOR VIRTUAL SCREEN UPDATES ; ; ; ;*******************************************************; ;--------; scroll_up: ; scroll up in the range given in AX ;--------; ; Entry: AH = virtual screen # ; BX = screen structure ; DL = starting row - 0 relative ; DH = ending row - 0 relative ; Exit: AX,BX,ES preserved ; push es ! push cx ! push dx mov es,vs_screen_seg ; DX=start,end rows; AH=virt. console # mov cx,dx ; save copy of start,end rows xor ah,ah ! mov al,dl ; set up SI,DI mov dx,crt_col * 2 mul dx ! mov di,ax ; DX,AX = byte offset starting row add ax,crt_col * 2 mov si,ax ! mov ax,cx ; SI = first word to copy from sub ah,al ! xor al,al xchg al,ah ; set up CX for # words to copy mov dx,crt_col mul dx ! mov cx,ax push ds ! push es! pop ds rep movsw pop ds ! pop dx ! pop cx ! pop es ret  ;----------; scroll_down: ;----------; ; Entry: AH = virtual console number ; BX = screen structure ; DL = start row ; DH = end row ; Exit: AX,BX,ES preserved ; push ax ! push cx ! push es mov es,vs_screen_seg mov cx,dx xor ah,ah mov al,dh inc al push dx mov dx,crt_col * 2 mul dx sub ax,2 mov di,ax sub ax,crt_col * 2 mov si,ax std mov ax,cx sub ah,al xor al,al xchg al,ah mov dx,crt_col mul dx mov cx,ax pop dx push ds ! push es ! pop ds rep movsw pop ds ! pop es ! pop cx ! pop ax cld ret ;----------; default_esc: ;----------; ; Entry: CX = 0 ; Exit: CX = ffffh - flag for simple char ; CX = 0 for escape or backspace dec cx ret eject ;***********************************************; ; ; ; SCREEN SWITCH ROUTINES ; ; ; ;***********************************************; ;========; vs_switch: ; Switch screen with full screen buffering ;========; ; ; Entry: DL = Vcon to switch to ; DH = Pcon to do the switch on ; ;Comments: A "normal" screen-switch algorithm for a serial console ; would use the following basic algorithm: ; * Loop through the character/attribute buffer comparing each ; attribute to the previous. ; * If different, send the physical codes to the console to change ; to the proper attribute. ; * Send the character, and repeat until buffer has been dumped. ; ; This XIOS improves its screen-switch performance by counting, but not ; sending, consecutive occurances of the most common character/attribute ; (char=space(20h), attrib=normal), and using direct cursor addressing ; to position the cursor to the next different char./attr. If less than ; 5 spaces were counted, they are sent directly to the UART, and direct ; cursor addressing is not performed. ; ; Because a typical console contains so much "white space" at any given ; moment, his method greatly improves screen switch performance. switch_init: ;; These values should be mov term_attrib,vsa_graphics or vsa_reverse ;; changed to attrib & mode mov term_mode,0 ;; of last vcon mov bx,dx xor bh,bh shl bx,1 mov bx,screen_image_tbl[bx] ;; BX = screen structure mov es,vs_screen_seg ;; ES = screen image buffer mov al,vs_mode push ax push word ptr vs_column ;; save row for cursor restore. push word ptr vs_row ;; save col for cursor restore. push word ptr vs_attrib ;; save attributes for restore. push ax set_up: call set_up_bx ;; BX = output Q ctl structure call ser_home ;; home physical cursor call ser_clear ;; clear physical screen chk_keypad_shift: pop ax ! push ax test al,vsm_keypadshift ;; check keypad shift mode jz no_keyshift call ser_keypad_shift jmps chk_keypad_alt no_keyshift: call ser_keypad_unshift chk_keypad_alt: pop ax test al,vsm_keypadalt ;; check keypad alt mode jz no_keyalt call ser_keypad_alt jmps fill_screen no_keyalt: call ser_keypad_unalt fill_screen: call ser_dis_wrap mov ah,vsa_normal call ser_set_attribute ;; set normal attribute mov dl,ah ;; DL = attribute vsa_normal xor di,di ;; DI = our cursor line_loop: mov cx,crt_col ;; number of chars left on line char_loop: mov ax,es:[di] ;; CX = new atrribute, char cmp ax,vsa_normal*256 + ' ' ;; Is is a normal space? jne compare_attrib cmp cx,1 ;; Is it the last character? je compare_attrib dec cx push di space_count_loop: ;; See if there are > 4 spaces inc di ! inc di cmp es:[di],ax jne found_nonspace loop space_count_loop pop si ;; (Formerly di) inc di ! inc di jmps next_line found_nonspace: mov si,di pop ax ;; (Formerly di) sub si,ax shr si,1 cmp si,5 jb not_enough push dx ! push cx mov al,0FFh ;; keeps Z29 on current line mov dl,crt_col sub dl,cl call ser_position_cursor pop cx ! pop dx jmps char_loop not_enough: mov ah,vsa_normal ;; there were < 5 spaces cmp dl,ah ;; is the attribute different? mov dl,ah ;; set last attribute push dx ! push cx je send_spaces push si call ser_set_attribute pop si send_spaces: mov cl,' ' push si call serial_out pop si dec si jnz send_spaces pop cx ! pop dx jmps char_loop compare_attrib: cmp dl,ah ;; is the attribute different? mov dl,ah push dx ! push cx je send_char call ser_set_attribute send_char: mov cl,al call serial_out ;; send the char pop cx ! pop dx inc di ! inc di ;; DI = curr char count loop char_loop ;; decrements line's char count next_line: cmp di,crt_size * 2 ;; DI = total chars sent so far je restore_attribute push dx call ser_cr_lf ;; send a CR/LF pop dx jmp line_loop restore_attribute: pop cx ;; cl <-- current attribute cmp dl,cl je restore_cursor mov ah,cl call ser_set_attribute restore_cursor: pop ax ! pop dx ;; AL = row, DL = col call ser_position_cursor chk_wrap: pop dx ;; get mode back test dl,vsm_no_wrap ;; check for wrap-around mode jnz chk_cursor push dx call ser_en_wrap pop dx chk_cursor: test dl,vsm_nocursor ;; check cursor mode jz show_cur call ser_hide_cursor jmps curr_vc show_cur: call ser_show_cursor curr_vc: ret ;; back to switch module eject ;--------; set_up_bx: ;--------; ; Put the Trasmit Queue control structure into BX ; ; Entry: DH = Pcon ; Exit: BX = Xmit Q control structure ; xor bh,bh mov bl,dh ;; use Pcon to index into the Xmit Q's shl bx,1 mov bx,ocdesctbl[bx] ;; bx = Xmit Q control ret ;----------------; ser_set_attribute: ;----------------; ; Sends Z-29/19 escape sequence to change characters attribute ; ; Entry: BX = Xmit Q control structure ; AL = attribute byte ; Exit: AX preserved ; mov cl,term_attrib ; Check current graphics mode xor cl,ah ; are the attributes different? and cl,vsa_graphics jz ser_chk_attrib xor term_attrib,vsa_graphics ; Yes, so toggle attribute push ax mov oesc_cnt[bx],2  mov cl,esc test ah,vsa_graphics jz ser_graphics_off call serial_out ; Send graphics_on esc sequence mov cl,'F' call serial_out jmps ser_graphics_pop ser_graphics_off: call serial_out ; Send graphics_off esc sequence mov cl,'G' call serial_out ser_graphics_pop: pop ax ser_chk_attrib: cmp ah,term_attrib ; Are we the same now? je s_s_a_exit mov term_attrib,ah ; No, so change char attributes push ax mov oesc_cnt[bx],3 mov cl,esc call serial_out mov cl,'s' call serial_out mov cl,term_attrib and cl,not vsa_graphics ; leave out the graphics bit add cl,'0' call serial_out pop ax s_s_a_exit: ret ;----------; ser_en_wrap: ;----------; ; Sends Z-29/19 escape sequence for Enable Wrap Mode ; ; Entry: BX = Xmit Q control structure ; mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'v' call serial_out ret ;-----------; ser_dis_wrap: ;-----------; ; Sends Z-29/19 escape sequence for Disable Wrap Mode ; ; Entry: BX = Xmit Q control structure ; mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'w' call serial_out ret ;--------------; ser_hide_cursor: ;--------------; ; Sends Z-29/19 escape sequence to hide cursor ; ; Entry: BX = Xmit Q control structure ; ;; test term_mode,vsm_nocursor ;; jnz s_s_c_exit or term_mode,vsm_nocursor mov oesc_cnt[bx],3 mov cl,esc call serial_out mov cl,'x' call serial_out mov cl,'5' call serial_out s_h_c_exit: ret ;--------------; ser_show_cursor: ;--------------; ; Sends Z-29/19 escape sequence to show cursor ; ; Entry: BX = Xmit Q control structure ; ;; test term_mode,vsm_nocursor ;; jz s_s_c_exit and term_mode,not vsm_nocursor mov oesc_cnt[bx],3 mov cl,esc call serial_out mov cl,'y' call serial_out mov cl,'5' call serial_out s_s_c_exit: ret ;---------------; ser_keypad_shift: ;---------------; ; Sends Z-29/19 escape sequence to shift keypad ; ; Entry: BX = Xmit Q control structure ; ;; test term_mode,vsm_keypadshift ;; jnz s_k_s_exit or term_mode,vsm_keypadshift mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'t' call serial_out s_k_s_exit: ret ;-----------------; ser_keypad_unshift: ;-----------------; ; Sends Z-29/19 escape sequence to unshift keypad ; ; Entry: BX = Xmit Q control structure ; ;; test term_mode,vsm_keypadshift ;; jz s_k_us_exit and term_mode,not vsm_keypadshift mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'u' call serial_out s_k_us_exit: ret ;-------------; ser_keypad_alt: ;-------------; ; Sends Z-29/19 escape sequence to alternate keypad ; ; Entry: BX = Xmit Q control structure ; ;; test term_mode,vsm_keypadalt ;; jnz s_k_a_exit or term_mode,vsm_keypadalt mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'=' call serial_out s_k_a_exit: ret ;---------------; ser_keypad_unalt: ;---------------; ; Sends Z-29/19 escape sequence to unalternate keypad ; ; Entry: BX = Xmit Q control structure ;  ;; test term_mode,vsm_keypadalt ;; jz s_k_ua_exit and term_mode,not vsm_keypadalt mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'>' call serial_out s_k_ua_exit: ret ;--------; ser_clear: ;--------; ; Sends Z-29/19 escape sequence for Clear Screen ; ; Entry: BX = Xmit Q control structure ; mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'E' call serial_out ret ;-------; ser_home: ;-------; ; Send Z29/19 escape sequence for Home-Cursor ; ; Entry: BX = XMIT Q control structure ; mov oesc_cnt[bx],2 mov cl,esc call serial_out mov cl,'H' call serial_out ret ;--------; ser_cr_lf: ;--------; ; Sends a carriage return/linefeed to the Z19/29. ; ; Entry: BX = Xmit Q control structure ; push ax ! push si mov cl,0Ah call serial_out mov cl,0Dh call serial_out pop si ! pop ax ret ;------------------; ser_position_cursor: ;------------------; ; Sends Z-29/19 escape sequence to position the cursor ; ; Entry: BX = Xmit Q control structure ; push dx ! push ax mov oesc_cnt[bx],4 mov cl,esc call serial_out mov cl,'Y' call serial_out pop ax ;; row # add al,32 ;; normalize for terminal mov cl,al call serial_out pop dx ;; col # add dl,32 ;; move cursor 1 char past last char mov cl,dl call serial_out ret eject dseg ;***************************************************************; ; ; ; SPECIAL OUTPUT CHARACTER TABLES ; ; ; ;***************************************************************; spec_char_tab db 4 db cr,lf,backsp,escape spec_func_tab dw carriage_return,line_feed,back_space,escape_rt ;***************************************************************; ; ; ; ESCAPE SEQUENCE TABLES ; ; ; ;***************************************************************; esc_tbl db 31 db 'A','B','C','D' db 'E','H','I','Y' db 'b','J','M','j' db 'o','K','L','k' db 'N','p','q' db 's','l','t','u' db 'v','w','x','y'  db 'F','G','=','>' esc_func_tbl rw 0 dw up, down, right, left dw erase_screen, home, up_with_scroll, x_and_y dw erase_begin, erase_end, delete_line, save dw erase_bol, erase_eol, insert_line, restore dw delete_char, reverse_on, reverse_off dw set_attribute, erase_line, keypad_shift, keypad_unshift dw enable_wrap, disable_wrap, set_modes, reset_modes dw graphics_on, graphics_off, keypad_alt, keypad_unalt eject ;***************************************************************; ; ; ; VIRTUAL SCREEN IMAGE TABLE ; ; ; ;***************************************************************; screen_image_tbl dw scrn_image0, scrn_image1, scrn_image2, scrn_image3 dw scrn_image4, scrn_image5, scrn_image6, scrn_image7 scrn_image0 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 0 ;pcon scrn_image1 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 0 ;pcon scrn_image2 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 0 ;pcon scrn_image3 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 0 ;pcon scrn_image4 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 1 ;pcon scrn_image5 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 1  ;pcon scrn_image6 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 1 ;pcon scrn_image7 dw 0,0 ;cursor, oldcursor db 0,0,0 ;col, row, mode db vsa_normal ;attribute dw 0,0,0 ;xy, oldxy, screen segment dw offset default_esc ;default: first char = reg char db 1 ;pcon ;*************************************; ; Current terminal Mode & attribute ; ;*************************************; term_mode db 0 term_attrib db 0 end  CALL PAUSE SUB SI,SI LOOP: MOV AH,-1 MOV AL,STRING[SI] INC SI CMP AL,AH JZ DONE INT 10H JMPS LOOP DONE: CALL PAUSE RETF STRING DB 1BH,'b',7,1BH,'c',0,1BH,'E',1BH,'H',-1 PAUSE: MOV CX,1 SUB AX,AX P_00: DEC AX JNZ P_00 LOOP P_00 RET  CALL PAUSE SUB SI,SI LOOP: MOV AH,-1 MOV AL,STRING[SI] INC SI CMP AL,AH JZ DONE INT 10H JMPS LOOP DONE: CALL PAUSE RETF STRING DB 1BH,'b',0FH,1BH,'c',0,1BH,'E',1BH,'H',-1 PAUSE: MOV CX,1 SUB AX,AX P_00: DEC AX JNZ P_00 LOOP P_00 RET  CALL PAUSE SUB SI,SI LOOP: MOV AH,-1 MOV AL,STRING[SI] INC SI CMP AL,AH JZ DONE INT 10H JMPS LOOP DONE: CALL PAUSE RETF STRING DB 1BH,'b',0,1BH,'c',7,1BH,'E',1BH,'H',-1 PAUSE: MOV CX,1 SUB AX,AX P_00: DEC AX JNZ P_00 LOOP P_00 RET  CALL PAUSE SUB SI,SI LOOP: MOV AH,-1 MOV AL,STRING[SI] INC SI CMP AL,AH JZ DONE INT 10H JMPS LOOP DONE: CALL PAUSE RETF STRING DB 1BH,'b',01H,1BH,'c',0,1BH,'E',1BH,'H',-1 PAUSE: MOV CX,1 SUB AX,AX P_00: DEC AX JNZ P_00 LOOP P_00 RET 0/U@]UFFF~ |FFF F FF~}ZFFF$FFF;F }.FF;F}vFFPFFP<FFʋFFF렋F FFq]UF~ }!v F-FPvvv Fً]UF~} v vFFPvFڋ]UPP PPPPPPPPPKPPPPPKPPPPPKP Px!PPPKP@P_*PPPKPuPF3PPPKPP-]UvvF=uv@PLP-F]USPNPFF~>}v^&Fv;]UZPUPoFF~>}!^&FvvFv]UFF]UNFӺظ~tr&1 &!& ]U;<| +<]U+<;~ <]U;<| +<]UW+<;~ <V]UFn~]UF+FFF +FF~~FF؋~~FF;u~~7FF;F(v vvvFPFFPF5FF;F|(v vvvXFPFFPN~~7FF;F(v FFPvvvFPGFL~}7FF;F|(v FFPvvvFP Nv vv]UFF]UFPP+F=t-F t@FP6666` 뺃~tP6666> ~Lu~Su~Gu~Tu~8uv~2u~4uz~6un~5u66 X~ u6>6666 6~9u>(~3u>~7u< ~1u<F]U-^CC]UfF]U PP\P]U PP|P]UL=t]Uva}w~a.K -PvF=uF]v F=uF]øPvZF=tPRPv~F]vq F=uF]ø]Ë]Uv]UFfPvv F~t~uF3v]UFfPvv {=uF]Uv vvv]UPRPv]Uv]UvFPe]UFPyP#yP']UFPv]UFF4vFhFFF<u~%tsqdžjƆnƆpƆov<-uFov<0unvP<t FPulFFF<.uFPPjpFFF~lt~LuFFPF^C}x~C. j m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m ? m m m m 3 m m 9 h<}qq-h4ދh5lF FFFPhh4qP})lhT}*qq-hT؃hTlF FFFPht4qPx)lhhD$<tqq-hdlFPF~Eujhqf4~Fujhqlfjhqff)lqfhthhqq4ƈlLpudžjhh4vv<t'jt FFqqjlыqsqou*ll=~nt0 NF֋qq~<tF怾otll=~ FF FFF FFF'v]UFv4P<tF v  -0F͋F]UF;Fs'~ sF0F7v ]vF3vPvFvF3vRvF]UVF|YF ڋȋVF}FVF }VF03VF73Ӌv ]Ã~ u9v VFRPvtFv VF%RPvW~ u9v VFpRPv5Fv VF%RPvVF}]F0VF|VF;~nʁ^;FϋvFv vvv]v F ڋȋVF RPvFv F ڋȋVFRPvfF]U f~~ ~ ~ v ]ËFƱF-Ɗ466F~u ]Ë6DFv6D~u6>tY~u~ u6>t+u)v^06D6DF PvvF- ]À~ uG63ұFV60t+v~tFFVn^~ tVFB6L 3}6|tw6 t u!E#0PP3  P!P" =t ]F~tN0F<uF6D~ u-6 >3ұڋȊD3FV~v FF6 >3ұ\ڋȊD3ӉFVVF^NPvvvu ]ËVF^N+ӉF~u9~vFFvPv =u ]ËF)F뾋VF]ñVF D!6D D#0PP P!P06D6DVFFf~t(0P6~F6FD6FDVF]X= r@Kt 0u;rF#N |y^3 u >}0CM>}0C>}.C0C;t,H;096vF>u.CC9}ۋ+F]NCZ^C t.C0;6sFC;vEC y-C+F]= r 3ҹ RX0CÍG;s.5r't9vƇ0Ky1ZURv|u|u *u0'irq{Yrae>t5qfw.iV<QKsY<"0QQ.rQ#YYt>tY€>u XUPvF~F- F-NJ56 PPk PPZF~uF=66D6D06D6D6D 6DF ]UFF~vn~v]ÊFPvF~F- F-NJ56 PPF~uF3~r@v P#P^6D >t!u 6|u6| t6D6L 6D06D6D6DF6F ]UJFFvt+uv~t^6|t6>t;u v]ËF;FvFF~t)v6tv 6FDFFF)F~r(v6FF)F~tzFFу~tl06DP0P6F0F6DF;FvFF~t#v6tv 6FDF)FF+FFFvtFF;Fsvv<tFF]Uv|tvv:=}]ËvDvPF PPF~t]Fv~t ;uu$F~tNv<uNvFDvDF]Uf~|~ ~]ËFF~*FN=tvFFP݋F]Ã~u+FN=tFFPP܋F]ËF-Ɗ466F~s]Ë609Dt0>u6>t+uv~u6|uT6L6 tu!E#0PP P!P=t]Ë6DF;FvFF~uj6tvv6FDFFF)F6>t;uu10P6 =u]á06D6D~r+v6FF)F~s]ÁF΃~u~uo6>t;u r6>t;u uO6|tE0PP6 tu!E# P!P=t]Ë6D6tvvi6FD6DF]UvPsF PPbFvDvD~t]Uf~]ËF-Ɗ46~  6<u]v4=u]Ë6 PP=u]UF-Ɗ466|u60t+ƈF6>t ;uuD6|u$6L0D=u6D6D:Fv 6DF6>t;u r66>tu 6FD~sFF00P6`C6>t;u v36|t6t >;us6>tu 6D]UFfFƱt;uv6|u6DDFPFPv=t]Ëvt ~uFF]Uf~FNȋ]ËF-Ɗ466t>;us%6|u6t4v6DF]øPFPv:=t]ËF]UfFƱ;us 6|t6DDF]øPFPv+]UPFPv]Uf~v]VFFN~t4v~F=|#~t~ t FFF~ uËvF;FuFF]Uf~}v: ]ËFFF<t<~ uv P=u]vFP=u]본]UPFP]UFF;F| F^####$ $ $&$Pw  ~t!NP  P P T~t#NP  P P )FFP FFvF8vv P F];uy ;tr <;tr<õõZXPu%ZыR>si2sa;r]؎> %uF<t-t(7AF<tu؀< t< øP PQֺZZ/>t <t7<tøt t<t!<uXZRP u  P 9X[SP t SP[CÀ>t ñ tñXZRPáZZ[;uSÌUNV]Z[R3Ҏ&/0>A@@>A>p !>A@@@@@A> 8 !~!!!>($"sCan't open %spictrpictw}Pcd  aPR CON:PRN:LST:*Control C*?$@?.Aư>errno= *Error in Floating Point* *Overflow* *Divide by Zero* *Domain Error* *Out of Range*not enough memory *Control C*#define debug 0 #define ON 1 #define OFF 0 #define FLIP 2 #define SCRNSIZE 16000 #define XMAX 599 #define YMAX 199 #include int xpos, ypos; int xset, yset; int cspd = 1; int state = ON; FILE *eopen( name, mode ) char *name, *mode; { FILE *f; if( ( f = fopen( name, mode ) ) == 0 ) exit( printf( "Can't open %s", name ) ); return( f ); } load( ) { int i; /* must be first var */ FILE *f; f = eopen( "pict", "r" ); for( i=0; i= cspd ) ypos -= cspd; } down( ) { if( ypos < YMAX - cspd ) ypos += cspd; } left( ) { if( xpos >= cspd ) xpos -= cspd; } right( ) { if( xpos < XMAX - cspd ) xpos += cspd; } ldiv( a, b, c ) int a, b, c; { #asm mov ax,word[bp+param1] imul word[bp+param2] idiv word[bp+param3] #endasm } line( x0, y0, x1, y1, state ) int x0, y0, x1, y1, state; { int x, y, dx, dy; dx = x1 - x0; dy = y1 - y0; if( ( dx > 0 ? dx : -dx ) > ( dy > 0 ? dy : -dy ) ) if( dx > 0 ) for( x = 0; x <= dx; x++ ) dot( x0 + x, y0 + ldiv( dy, x, dx), state ); else for( x = 0; x >= dx; x-- ) dot( x0 + x, y0 + ldiv( dy, x, dx), state ); else if( dy > 0 ) for( y = 0; y <= dy; y++ ) dot( x0 + ldiv( dx, y, dy), y0 + y, state ); else if( dy < 0 ) for( y = 0; y >= dy; y-- ) dot( x0 + ldiv( dx, y, dy) / dy, y0 + y, state ); else dot( x0, y0, state ); } set( x, y ) int x, y; { xset = x; yset = y; } inbranch( ) { int c, s; s = 0; while( !( c = _os( 6, -1 ) ) ) { s = !s; line( xset, yset, xpos, ypos, FLIP ); } if( s ) line( xset, yset, xpos, ypos, FLIP ); if( c == 'L' ) load( ); else if( c == 'S' ) save( ); else if( c == 'G' ) init_gr( ); else if( c == 'T' ) uninit_gr( ); else if( c == '8' ) up( ); else if( c == '2' ) down( ); else if( c == '4' ) left( ); else if( c == '6' ) right( ); else if( c == '5' ) set( xpos, ypos ); else if( c == ' ' ) line( xset, yset, xpos, ypos, state ); else if( c == '9' ) state = 1; else if( c == '3' ) state = 0; else if( c == '7' ) cspd = 10; else if( c == '1' ) cspd = 1; return( c ); } vid_init( list ) int list; { #asm REGADDR EQU 3B4H DATADDR EQU 3B5H CRTADDR EQU 3D8H COLADDR EQU 3D9H STADDR EQU 3BAH CONTL EQU 0B7H ;CONTROL DATA CPORT EQU 300H ;PORT ADDRESS MOV DX,CRTADDR MOV AL,2dh OUT DX,AL MOV DX,REGADDR MOV BX,word[bp+param1] MOV CX,16 INIT2: MOV AX,[BX] OUT DX,AX ;OUTPUT ADDRESS AND DATA IN ONE OP INC BX INC BX LOOP INIT2 ;LOOP UNTIL ALL DATA OUTPUT(CX=0) MOV DX,03DAH IN AL,DX #endasm } static char grlist[ ] = { 0, 0x7D, 1, 0x50, 2, 0x63, 3, 0x0F, 4, 0x07F, 5, 0x08, 6, 0x64, 7, 0x7F, 8, 0x02, 9, 0x01, 10, 0x20, 11, 0x00, 12, 0xFF, 13, 0xFF, 14, 0x00, 15, 0 }; static char chrlist[ ] = { 0, 0x61, 1, 0x50, 2, 0x52, 3, 0x0F, 4, 0x19, 5, 6, 6, 0x19, 7, 0x19, 8, 0x02, 9, 0x0D, 10, 0x0B, 11, 0x0C, 12, 0xFF, 13, 0xFF, 14, 0, 15, 0 }; int16( ah, al ) char ah, al; { #if debug #else #asm mov ah, byte[bp+param1] mov al, byte[bp+param2] int 16h #endasm #endif } init_gr( ) { int16( -2, 0x20 ); vid_init( &grlist ); } uninit_gr( ) { int16( -1, 0x20 ); vid_init( &chrlist ); } main( ) { init_gr( ); while( inbranch( ) != 3 ); uninit_gr( ); } #define debug 0 #define ON 1 #define OFF 0 #define FLIP 2 #define SCRNSIZE 16000 #define XMAX 599 #define YMAX 199 #include int xpos, ypos; int xset, yset; int cspd = 1; int state = ON; FILE *eopen( name, mode ) char *name, *mode; { FILE *f; if( ( f = fopen( name, mode ) ) == 0 ) exit( printf( "Can't open %s", name ) ); return( f ); } load( ) { int i; /* must be first var */ FILE *f; f = eopen( "pict", "r" ); for( i=0; i= cspd ) ypos -= cspd; } down( ) { if( ypos < YMAX - cspd ) ypos += cspd; } left( ) { if( xpos >= cspd ) xpos -= cspd; } right( ) { if( xpos < XMAX - cspd ) xpos += cspd; } ldiv( a, b, c ) int a, b, c; { #asm mov ax,word[bp+param1] imul word[bp+param2] idiv word[bp+param3] #endasm } line( x0, y0, x1, y1, state ) int x0, y0, x1, y1, state; { int x, y, dx, dy; dx = x1 - x0; dy = y1 - y0; if( ( dx > 0 ? dx : -dx ) > ( dy > 0 ? dy : -dy ) ) if( dx > 0 ) for( x = 0; x <= dx; x++ ) dot( x0 + x, y0 + ldiv( dy, x, dx), state ); else for( x = 0; x >= dx; x-- ) dot( x0 + x, y0 + ldiv( dy, x, dx), state ); else if( dy > 0 ) for( y = 0; y <= dy; y++ ) dot( x0 + ldiv( dx, y, dy), y0 + y, state ); else if( dy < 0 ) for( y = 0; y >= dy; y-- ) dot( x0 + ldiv( dx, y, dy) / dy, y0 + y, state ); else dot( x0, y0, state ); } set( x, y ) int x, y; { xset = x; yset = y; } inbranch( ) { int c, s; s = 0; while( !( c = _os( 6, -1 ) ) ) { s = !s; line( xset, yset, xpos, ypos, FLIP ); } if( s ) line( xset, yset, xpos, ypos, FLIP ); if( c == 'L' ) load( ); else if( c == 'S' ) save( ); else if( c == 'G' ) init_gr( ); else if( c == 'T' ) uninit_gr( ); else if( c == '8' ) up( ); else if( c == '2' ) down( ); else if( c == '4' ) left( ); else if( c == '6' ) right( ); else if( c == '5' ) set( xpos, ypos ); else if( c == ' ' ) line( xset, yset, xpos, ypos, state ); else if( c == '9' ) state = 1; else if( c == '3' ) state = 0; else if( c == '7' ) cspd = 10; else if( c == '1' ) cspd = 1; return( c ); } vid_init( list ) int list; { #asm REGADDR EQU 3B4H DATADDR EQU 3B5H CRTADDR EQU 3D8H COLADDR EQU 3D9H STADDR EQU 3BAH CONTL EQU 0B7H ;CONTROL DATA CPORT EQU 300H ;PORT ADDRESS MOV DX,CRTADDR MOV AL,2dh OUT DX,AL MOV DX,REGADDR MOV BX,word[bp+param1] MOV CX,16 INIT2: MOV AX,[BX] OUT DX,AX ;OUTPUT ADDRESS AND DATA IN ONE OP INC BX INC BX LOOP INIT2 ;LOOP UNTIL ALL DATA OUTPUT(CX=0) MOV DX,03DAH IN AL,DX #endasm } static char grlist[ ] = { 0, 0x7D, 1, 0x50, 2, 0x63, 3, 0x0F, 4, 0x07F, 5, 0x08, 6, 0x64, 7, 0x7F, 8, 0x02, 9, 0x01, 10, 0x20, 11, 0x00, 12, 0xFF, 13, 0xFF, 14, 0x00, 15, 0 }; static char chrlist[ ] = { 0, 0x61, 1, 0x50, 2, 0x52, 3, 0x0F, 4, 0x19, 5, 6, 6, 0x19, 7, 0x19, 8, 0x02, 9, 0x0D, 10, 0x0B, 11, 0x0C, 12, 0xFF, 13, 0xFF, 14, 0, 15, 0 }; int16( ah, al ) char ah, al; { #if debug #else #asm mov ah, byte[bp+param1] mov al, byte[bp+param2] int 16h #endasm #endif } init_gr( ) { int16( -3, 0x20 ); vid_init( &grlist ); } uninit_gr( ) { int16( -2, 0x20 ); vid_init( &chrlist ); } main( ) { init_gr( ); while( inbranch( ) != 3 ); uninit_gr( ); } ;1/24/85 ;************************************************ ;* * ;* Slicer Video Expansion Board * ;* * ;************************************************ ;------------------- ; include files NOLIST include sxcodes.mac include sxascii.equ INCLUDE SXBDOS.EQU LIST INCLUDE VVARS.A86 ;------------------- ;---- notes -------- ;1/24/85 elh added raw_key keyboard interrupt ;------------------- cseg org 0 ;Video Board ID. Software can read this location to ;determine if video board can be used. First two bytes ;identify video board. Next two bytes are the version ;number. At offset 4 is an initialization entry point. DB 'VD' DW 1 WAKE_UP: CALL INIT RETF cseg ;Entry points to video routines. ;Entry is via a software interrupt. At boot a callf to ;wake_up setup interrupt vectors. Each entry is called ;with a function number in ah. Positive ah emulate ;ibm rom calls. Negative ah for Slicer additions ;Branch tables. ;Video (Int 10H ) VID_LOW: DW SET_MODE DW SET_CTYPE DW SET_CPOS DW READ_CURSOR DW READ_LPEN DW ACT_DISP_PAGE DW SCROLL_UP DW SCROLL_DOWN DW READ_AC_CURRENT DW WRITE_AC_CURRENT DW WRITE_C_CURRENT DW SET_COLOR DW WRITE_DOT DW READ_DOT DW WRITE_TTY DW VIDEO_STATE ; DW NO_OP ; DW FILL_WINDOW VID_LLIMIT EQU (OFFSET $ - OFFSET VID_LOW) / 2 VID_HIGH: DW VIDEO_OUT VID_HLIMIT EQU (OFFSET $ - OFFSET VID_HIGH) / 2 ;Disk ( Int 252 ) ;On the IBM PC this interrupt is at 13H. On the 80186 ;13H is reserved for hardware timer interrupt. So the ;Slicer re-routes disk interrupts to 252. DSK_LOW: DW DISK_RESET DW DISK_STATUS DW DISK_READ DW DISK_WRITE DW DISK_VERIFY DW DISK_FORMAT DSK_LLIMIT EQU (OFFSET $ - OFFSET DSK_LOW) / 2 DSK_HIGH: DSK_HLIMIT EQU (OFFSET $ - OFFSET DSK_HIGH) / 2 ;Keyboard ( int 16H ) KBD_LOW: DW KEY_IN DW KEY_STAT DW KEY_SHIFTS KBD_LLIMIT EQU (OFFSET $ - OFFSET KBD_LOW) / 2 KBD_HIGH: DW KEY_8 DW VPORTON DW VPORTOFF DW RAW_KEY KBD_HLIMIT EQU (OFFSET $ - OFFSET KBD_HIGH) / 2 ;Printer ( int 17H ) PRN_LOW: DW PRINTER_OUT DW PRINTER_INIT DW PRINTER_STAT PRN_LLIMIT EQU (OFFSET $ - OFFSET PRN_LOW) / 2 PRN_HIGH: PRN_HLIMIT EQU (OFFSET $ - OFFSET PRN_HIGH) / 2 ;Range checks are made for each interrupt. If ah ;holds a legal value then a jump to the common code ;at enter is made. This save registers, calls ;subroutine, restores registers then returns. ;Video ENTER10: PUSH SI CMP AH,VID_LLIMIT JNC ENTER10A MOV SI,OFFSET VID_LOW JMP ENTER ENTER10A: NOT AH CMP AH,VID_HLIMIT JNC NO_ENTRY MOV SI,OFFSET VID_HIGH JMP ENTER NO_ENTRY: POP SI NOT AH IRET ;Disk (looks like int. 13H but really int. 252 ) ENTER13: PUSH SI CMP AH,DSK_LLIMIT JNC ENTER13A MOV SI,OFFSET DSK_LOW JMP ENTER ENTER13A: NOT AH CMP AH,DSK_HLIMIT JNC NO_ENTRY MOV SI,OFFSET DSK_HIGH JMP ENTER ;Keyboard ENTER16: PUSH SI CMP AH,KBD_LLIMIT JNC ENTER16A MOV SI,OFFSET KBD_LOW JMP ENTER ENTER16A: NOT AH CMP AH,KBD_HLIMIT  JNC NO_ENTRY MOV SI,OFFSET KBD_HIGH JMP ENTER ;Printer ENTER17: PUSH SI CMP AH,PRN_LLIMIT JNC ENTER17A MOV SI,OFFSET PRN_LOW JMP ENTER ENTER17A: NOT AH CMP AH,PRN_HLIMIT JNC NO_ENTRY MOV SI,OFFSET PRN_HIGH JMP ENTER ;----- ENTER: ;----- ;Common code for interrupt entry. ;in: ah = routine number (range already checked ) ; si = branch table ;For each subroutines ;in: ah, si = unknown( altered by enter) ; al, bx, cx, dx, di, es, ss = set by caller ; ( unaltered by enter ) ; bp = pointer to register save area (on stack) ; ds = Video board data segment ;out: ax, flags = returned to caller ; other registers = restored from stack. ;If it is necessary to return a value in a register ;other than ax and flags then the saved copy of that ;register on the stack should be altered. ;Flags are not saved so caution should be used when ;altering flags such as I and D. PUSH BP MOV BP,SP PUSH WORD PTR 8[BP] POPF PUSH DI PUSH DX PUSH CX PUSH BX MOV BL,AH SUB BH,BH SHL BX,1 ADD SI,BX POP BX PUSH BX PUSH DS PUSH ES MOV DS,DATASEG MOV BP,SP CALL CS:WORD PTR[SI] POP ES POP DS POP BX POP CX POP DX POP DI POP BP POP SI RETF 2 ;Offsets into stack (relative to bp) for orignal/ ;return register values. SDUMMY SSEG COMMON 'EMPTY' ! ORG 0 RES RW 1 RDS RW 1 RBX RW 1 RCX RW 1 RDX RW 1 RDI RW 1 RBP RW 1 RSI RW 1 CSEG WAIT EQU 1 ;---------------- ;Include files INCLUDE VIDEO.A86 INCLUDE VKEYS.A86 INCLUDE VDISK.A86 include Vinita.a86 include Vtable.a86 ;---------------- LSTOUT EQU 14 CSEG PRINTER_OUT: MOV BL,LSTOUT INT MONITOR RET PRINTER_INIT: PRINTER_STAT: MOV AH,0E0H RET DUMMY DSEG COMMON 'EMPTY' ! ORG 84EEH MEMSIZE RW 1 CSEG MEM: PUSH DS MOV AX,0F800H MOV DS,AX MOV AX,MEMSIZE POP DS IRET DUMMY DSEG COMMON 'EMPTY' ! ORG 410H EQUIP RW 1 CSEG EQUIPMENT: PUSH DS SUB AX,AX MOV DS,AX MOV AX,EQUIP POP DS IRET  DUMMY DSEG COMMON 'EMPTY' ! ORG 84EAH SECONDS RW 1 CSEG TIME_OF_DAY: PUSH DS CMP AH,1 MOV AX,0F800H MOV DS,AX MOV AX,SECONDS MOV DS,DATASEG JZ SET_TIME SUB AX,T_SECS MOV DX,18 MUL DX ADD AX,T_LOW XCHG AX,DX ADC AX,T_HIGH MOV CX,AX SUB AX,AX POP DS IRET SET_TIME: MOV T_SECS,AX MOV T_LOW,DX MOV T_HIGH,CX POP DS IRET VIDRASM-86 1.2 10/31/83_EXTRACODESTACKDATAvsegEMPTYemptyEMPTYemptyDUMMYCDUMMYEDUMMYDATACODESDUMMYVSEGX u8 X H(fXX> VD @$8O^{h @ 8 ͜yTTTTT T TTTTTTTTTT T"T$T&T(T*T,T.T0T2T4T6T8T:TDVs\Ԁs(O^Vs*?Ԁs62Vs6&Ԁsо<VsD ԀsJUvWRQSĜ-TTT TT*T7TCTPT\TiT#*[S. .[YZ_]^5 T5.: t .<u.dGP+6>XÜ+> &>>t+6>>+Μ+tCsON>>t>&> k>t{>;>s>RPP>XXZÀ>+>>HH@@+>8++>r>>+6>Th+OND6>>+0>>+>> >ø >+ >éLá,$>>at .>>&>À>|>sÊ>>>&>>t&@@s +>h> TTnt, *&>6>>t, *>6>>tX6>Dȡ>>t< rn 2ȡ>` >T_T2 z tTTT T TTjFDYABCDEHIJK dl$oLMb0c0m:nCjLkP1YTTT T TTTTTTT"T%T(T+T.T1T4T7T:T=T@T ~â>+ >.t>+&t.\&'C<u.D&>*.t>.D >.D>.D>>>.D  T9~&>>+@É>> Ëʊ*&>*Ká>+6>V>F>6>&>>Nj>>>t{=~z>>Nj>>>tGGP> t $ $ Ë>XRP*&>Z*ZP*XSfP*JXSGP>Q>t>YYX Q>tY+с* u+Ɇ+>+þtȡ>(uT͠pk͠~t z >ࠍ>FPR+6>+ZXVWPSQ>Ɏپ t+Ɏ6|ȁ&& Y[X_TTT T THT2X^. WVQS>؊ [Y^_P. X TJTѠ~B1!2@3#4$5%6^7&8*9(0)-_=+ qQwWeErRtTyYuUiI oOpP[{]} aAsS ~dDfFgGhHjJ kK lL ;:'"`~\|zZxXcCvVbBnNmM ,<.>/?* Š6789--456++1230.+>ttt t*-159=AEI****Ru*+>>t̠>>tَ>F> tB=tá>F=ut>uu  >*>à> u&>úPGJ"XPSQRUVW. >>Ps >G>>>aTs& *_^]ZY[X >>>Àu u+>uH>++>u>>u@H+0Z +ñ ǻ ߉و*ȋu S Ȏ. &>-B*&>&> >+. >>>>>>>>B &>P+&L * T;T~T>~k &&@J&B&X&Z&g&&t &v&\&^&H&J&D$&F&h.&j&@. ظ % TT"T.T:TFTRT^TnT,J X8(- qPZ 8(- dpaPR + ,P (P - )  *P .P 0, <rTѠn P.@u .tB><~~<ffffff{>c8llx00000x xflxlf`~s``bf8ll8ff|``xxff|lfxpx0000xx0l88lx00xƌ2fx```~``x`0 xx8l00x |v``|ffxx |vxx8l```v| `lvff0p000x ̧~gx`flxlp00000xxxff|`v| vf`|x 0|004vx0ll8l| 40d00000000v8l| ôËء$+ء<.ء. t+>>>+ϣ>>>=T3tfxpx0000xx0l88lx00xƌ2fx```~``x`0 x !!""##$$%%&&''(())**++,,--..//00112233445566778899::;;<<==>>??@@AABBCCDDEEFFGGHHIIJJKKLLMMNNOO