wrote vdriver 80x25 8 color, works but problem with cursor
Posted: Sat Jan 23, 2016 9:32 pm
I ported the given simple video driver in order to bypass int21h. Here is the brief summary for this driver:
The driver is written in C but I ported to assembly.
It works and able to process NL, CR (tested) as well as BS (not tested) as well as ordinary chars and maintains offset, col, row and other variables in data segment. So anything I throw out, it prints correctly, but there is one issue: However once everything printed, the cursor always jumps to the beginning of 4rd line of screen no matter how many lines I print: 1 line, 2 line, 3 line or 40 lines. I re-checked everything and after each time the char is printed, it calculates the cursor from offset (offset=row * 80 + col), cursorPos = offset/2 since, offset is buffer offset relative to video buffer address and each char is 2 bytes (1 byte color, 1 byte char value).
When setting cursor it uses Rx = 0E to port 3d4h and sends to cursor value to 3d5h.
I set debugging outputs and can see it is sending right offsets to function.
I am wondering what else I should check? May be there is something I am missing?
Thanks.,
The code is a lot so I took out all of the debug statements as well as special char processing code removed to make it as short as possible:
video.inc:
Here is an debugging output when sending string with NL, CR:
videoModuleTestStr0 db 'Test String1 NL, CR' , 0ah, 0dh, 'Test String2', '$'
The debugg output will print out the value that is being set to videoSetVideoRx function as well as offset, color, org, row, col, pos values after each char print.
The driver is written in C but I ported to assembly.
It works and able to process NL, CR (tested) as well as BS (not tested) as well as ordinary chars and maintains offset, col, row and other variables in data segment. So anything I throw out, it prints correctly, but there is one issue: However once everything printed, the cursor always jumps to the beginning of 4rd line of screen no matter how many lines I print: 1 line, 2 line, 3 line or 40 lines. I re-checked everything and after each time the char is printed, it calculates the cursor from offset (offset=row * 80 + col), cursorPos = offset/2 since, offset is buffer offset relative to video buffer address and each char is 2 bytes (1 byte color, 1 byte char value).
When setting cursor it uses Rx = 0E to port 3d4h and sends to cursor value to 3d5h.
I set debugging outputs and can see it is sending right offsets to function.
I am wondering what else I should check? May be there is something I am missing?
Thanks.,
The code is a lot so I took out all of the debug statements as well as special char processing code removed to make it as short as possible:
Code: Select all
data segment para public 'data'
vidOffset dw 0
vidColor dw VIDEO_H_YELLOW
vidOrg dw 0
vidRow dw 0
vidCol dw 0
vidPos dw 0
data ends
code segment para public use16 'code'
assume cs:code, ds:data, ss:sta
M_EXTERNDEF
; helper function for setting the video register to specified value.
; input EAX[31:16]=video register to set.
; AX = video data value to write.
; output CX=0 if success.
; CX=1 if failure.
; destroys: None
videoSetVideoRx proc far
M_PUSH <dx>
cli
mov dx, VIDEO_CTRL_IDX
ror eax, 16
out dx, ax
mov dx, VIDEO_CTRL_DATA
ror eax, 16
out dx, ax
sti
videoSetVideoRxExit:
M_POP <dx>
ret
videoSetVideoRx endp
; Initialize video buffer along with cursor and position and clears screen.
; input None
; output CX=0 if success.
; CX=1 if failure.
; destroys: None
videoInitCtrl proc far
M_PUSH <eax, cx, ds, si>
; set cursor size to 15.
mov eax, VIDEO_RX_CURSIZE SHL 16
mov ax, 15
call videoSetVideoRx
; set display address to 0.
mov eax, VIDEO_RX_START_ADDR SHL 16
mov ax, 0
call videoSetVideoRx
; set cursor position to 0.
mov eax, (VIDEO_RX_CURSOR_POS SHL 16)
mov ax, 0
call videoSetVideoRx
; clear screen by writing 0700 to every word in video buffer (2000 chars = 25 * 80)
mov ax, VIDEO_BUFFER_BASE
mov ds, ax
sub si, si ; (DS:SI) = video buffer pointer, b800:0000
mov ax, 0700h ; (AX) = char to write.
mov cx, (VIDEO_BUFFER_LINE_WIDTH * VIDEO_BUFFER_LINES_PER_SCREEN) ; (CX) = size of video buffer char.
videoInitCtrlLoop1:
mov ds:[si], ax
add si, 2
loop videoInitCtrlLoop1
M_POP <si, ds, cx, eax>
ret
videoInitCtrl endp
; scrolls screen by one line
; input: None
; output: None
; destroys: None
videoScroll proc far
M_PUSH <ax, cx, ds, si, es, di>
mov ax, DATA
mov ds, ax ; (DS) = data segment.
cmp word ptr vidOffset, VIDEO_MASK ; buffer is full? if so will scroll
ja videoScrollLab1
; less than full buffer (4000h), therefore org += 2 * LINEWIDTH, just increment by one line.
add word ptr vidOrg, (VIDEO_BUFFER_LINE_WIDTH SHL 1) ; org increment by one line worth of bytes.
jmp videoScrollLab2
; full buffer, copy last 24 lines to first 24 line and full last line with
; empty data.
videoScrollLab1:
mov cx, (VIDEO_BUFFER_LINE_WIDTH * (VIDEO_BUFFER_LINES_PER_SCREEN - 1))
mov di, VIDEO_BUFFER_BASE
mov es, di ; (ES) = base - b800h
sub si, si ; (ES:SI) = first line.
sub di, di
add di, vidOrg
add di, 160 ; (ES:SI) = second line + org.
videoScrollLoop1:
mov ax, es:[di] ; (AX) = char from ES:[DI]
mov es:[si], ax ; char from ES:[DI] to ES:[SI]
add si, 2
add di, 2
loop videoScrollLoop1
; update org.
videoScrollLab2:
mov ax, 2 * (VIDEO_BUFFER_LINE_WIDTH * (VIDEO_BUFFER_LINES_PER_SCREEN - 1))
add ax, vidOrg
mov vidOffset, ax
; update last line with blank char-s.
mov di, VIDEO_BUFFER_BASE
mov es, di ; (ES) = b800h, video buffer base.
sub di, di ; (ES:DI) = b800h, video buffer base.
mov ax, 0c00h ; HRGB=1100 highlight RED, null char.
mov cx, 80h ; (CX) = char per line.
videoScrollLoop2:
mov es:[di], ax ; update buffer position with blank char.
add di, 2
loop videoScrollLoop2
M_POP <di, es, si, ds, cx, ax>
ret
videoScroll endp
; put one char (print one char on screen), and takes care of
; details.
; input DL = char to print
; output CX=0 if success.
; CX=1 if failure.
; destroys: None
videoPutChar proc far
M_PUSH <eax, ebx, cx, dx>
; c is an ordinary character.
; pos = 2 * ( row*80 + column )
videoPutCharLab6:
mov ax, vidRow
push dx
push cx
mov cx, VIDEO_BUFFER_LINE_WIDTH
mul cx ; (DX:AX) = product of line width * vidRow
pop cx
pop dx
add ax, vidCol
shl ax, 1 ; (AX) = 2 * (vidRow * lineWidth + vidCol)
mov vidPos, ax
mov ax, vidOrg
add ax, vidPos
and ax, VIDEO_MASK ; (AX) = (vidOrg + vidPos) & VIDEO_MASK
mov vidOffset, ax
; w = color; w = (w << 8 ) + c;
mov ax, vidColor
shl ax, 8
and dx, 0ffh
add ax, dx
; place w (in this case ax) into buffer.
mov di, 0b800h
mov es, di
mov di, vidOffset ; (ES:DI) = b800:offset.
; will update video buffer with char using 0:32 flat offset in EBX.
M_1616_TO_FLAT32 es, di, ebx ; (EBX) = flat address of vidOffset.
call putWordExtMem
inc word ptr vidCol ; increment col.
cmp word ptr vidCol, VIDEO_BUFFER_LINE_WIDTH ; col is past 80?
jb videoPutCharLab3
; column is more than or equal to 80, set column to 0 and increment row by 1.
mov word ptr vidCol, 0h
inc word ptr vidRow
cmp word ptr vidRow, VIDEO_BUFFER_LINES_PER_SCREEN
jb videoPutCharLab4
; row is more than or equal to 25, therefore, set the row at 24 and scroll 1 line.
mov vidRow, 24
call videoScroll
; reached here when ros is less than 25.
videoPutCharLab4:
; reached here when col is less than 80.
videoPutCharLab3:
; calculate new offset.
; vidPos = vidRow * lineWidth + vidCol
mov ax, vidRow
push dx
push cx
mov cx, VIDEO_BUFFER_LINE_WIDTH ;
mul cx
pop cx
pop dx
add ax, vidCol
shl ax, 1 ; (AX) = (vidRow * lineWidth + vidCol) * 2
mov vidPos, ax ; updated the position.
; offset = (org + post) & vid_mask
mov ax, vidOrg
add ax, vidPos
and ax, VIDEO_MASK ; (AX) = (vidOrg + vidPos) & VIDEO_MASK
mov vidOffset, ax ; update offset.
; set_VDC(CURSOR, offset >> 1)
mov eax, (VIDEO_RX_CURSOR_POS SHL 16)
mov ax, vidOffset
shr ax, 1
call videoSetVideoRx
videoPutCharExit:
M_POP <dx, cx, ebx, eax>
ret
videoPutChar endp
videoDbgStatus proc far
M_PRINTF "\noffset, color, org, row, col, pos: "
IRP vidVar, <vidOffset, vidColor, vidOrg, vidRow, vidCol, vidPos>
M_PRINTWORD_SPC &vidVar&
ENDM
ret
videoDbgStatus endp
code ends
end
Code: Select all
VIDEO_CTRL_IDX = 3d4h
VIDEO_CTRL_DATA = 3d5h
VIDEO_BUFFER_BASE = 0b800h
VIDEO_RX_CURSIZE = 0ah
VIDEO_RX_START_ADDR = 0ch
VIDEO_RX_CURSOR_POS = 0eH
VIDEO_BUFFER_LINES_PER_SCREEN = 25
VIDEO_BUFFER_LINE_WIDTH = 80
; VIDEO_BYTES_PER_SCREEN = VIDEO_BUFFER_LINES_PER_SCREEN * VIDEO_BUFFER_LINE_WIDTH * 2
VIDEO_RAM_SIZE_BYTE = 16*1024
VIDEO_CURSOR_SHAPE = 15
VIDEO_H_GREEN = 0ah
VIDEO_H_CYAN = 0bh
VIDEO_H_RED = 0ch
VIDEO_H_PURPLE = 0dh
VIDEO_H_YELLOW = 0eh
VIDEO_MASK = VIDEO_RAM_SIZE_BYTE - 1 ; MASK = VIDEO RAM SIZE - 1
; when enabled, b8000:0000 output is disabled and instead use int21h for debugging output
; if you enable this switch, also enable OPTION_USE_INT21H otherwise
; result is unpredictable.
OPTION_DEBUG_VIDEO = 1
OPTION_DEBUG_VIDEO_L2 = 0
videoModuleTestStr0 db 'Test String1 NL, CR' , 0ah, 0dh, 'Test String2', '$'
The debugg output will print out the value that is being set to videoSetVideoRx function as well as offset, color, org, row, col, pos values after each char print.
Code: Select all
videoPutChar Entered: 54
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0000 000B8000
videoSetVideoRx: rx[31:16], val[0:15] 000E0001
offset, color, org, row, col, pos: 0002 000E 0000 0000 0001 0002
videoPutChar: done.
videoPutChar Entered: 65
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0002 000B8002
videoSetVideoRx: rx[31:16], val[0:15] 000E0002
offset, color, org, row, col, pos: 0004 000E 0000 0000 0002 0004
videoPutChar: done.
videoPutChar Entered: 73
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0004 000B8004
videoSetVideoRx: rx[31:16], val[0:15] 000E0003
offset, color, org, row, col, pos: 0006 000E 0000 0000 0003 0006
videoPutChar: done.
videoPutChar Entered: 74
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0006 000B8006
videoSetVideoRx: rx[31:16], val[0:15] 000E0004
offset, color, org, row, col, pos: 0008 000E 0000 0000 0004 0008
videoPutChar: done.
videoPutChar Entered: 20
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0008 000B8008
videoSetVideoRx: rx[31:16], val[0:15] 000E0005
offset, color, org, row, col, pos: 000A 000E 0000 0000 0005 000A
videoPutChar: done.
videoPutChar Entered: 53
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:000A 000B800A
videoSetVideoRx: rx[31:16], val[0:15] 000E0006
offset, color, org, row, col, pos: 000C 000E 0000 0000 0006 000C
videoPutChar: done.
videoPutChar Entered: 74
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:000C 000B800C
videoSetVideoRx: rx[31:16], val[0:15] 000E0007
offset, color, org, row, col, pos: 000E 000E 0000 0000 0007 000E
videoPutChar: done.
videoPutChar Entered: 72
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:000E 000B800E
videoSetVideoRx: rx[31:16], val[0:15] 000E0008
offset, color, org, row, col, pos: 0010 000E 0000 0000 0008 0010
videoPutChar: done.
videoPutChar Entered: 69
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0010 000B8010
videoSetVideoRx: rx[31:16], val[0:15] 000E0009
offset, color, org, row, col, pos: 0012 000E 0000 0000 0009 0012
videoPutChar: done.
videoPutChar Entered: 6E
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0012 000B8012
videoSetVideoRx: rx[31:16], val[0:15] 000E000A
offset, color, org, row, col, pos: 0014 000E 0000 0000 000A 0014
videoPutChar: done.
videoPutChar Entered: 67
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0014 000B8014
videoSetVideoRx: rx[31:16], val[0:15] 000E000B
offset, color, org, row, col, pos: 0016 000E 0000 0000 000B 0016
videoPutChar: done.
videoPutChar Entered: 31
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0016 000B8016
videoSetVideoRx: rx[31:16], val[0:15] 000E000C
offset, color, org, row, col, pos: 0018 000E 0000 0000 000C 0018
videoPutChar: done.
videoPutChar Entered: 20
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0018 000B8018
videoSetVideoRx: rx[31:16], val[0:15] 000E000D
offset, color, org, row, col, pos: 001A 000E 0000 0000 000D 001A
videoPutChar: done.
videoPutChar Entered: 4E
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:001A 000B801A
videoSetVideoRx: rx[31:16], val[0:15] 000E000E
offset, color, org, row, col, pos: 001C 000E 0000 0000 000E 001C
videoPutChar: done.
videoPutChar Entered: 4C
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:001C 000B801C
videoSetVideoRx: rx[31:16], val[0:15] 000E000F
offset, color, org, row, col, pos: 001E 000E 0000 0000 000F 001E
videoPutChar: done.
videoPutChar Entered: 2C
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:001E 000B801E
videoSetVideoRx: rx[31:16], val[0:15] 000E0010
offset, color, org, row, col, pos: 0020 000E 0000 0000 0010 0020
videoPutChar: done.
videoPutChar Entered: 20
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0020 000B8020
videoSetVideoRx: rx[31:16], val[0:15] 000E0011
offset, color, org, row, col, pos: 0022 000E 0000 0000 0011 0022
videoPutChar: done.
videoPutChar Entered: 43
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0022 000B8022
videoSetVideoRx: rx[31:16], val[0:15] 000E0012
offset, color, org, row, col, pos: 0024 000E 0000 0000 0012 0024
videoPutChar: done.
videoPutChar Entered: 52
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:0024 000B8024
videoSetVideoRx: rx[31:16], val[0:15] 000E0013
offset, color, org, row, col, pos: 0026 000E 0000 0000 0013 0026
videoPutChar: done.
videoPutChar Entered: 0A
videoPutChar: processing new line (0x0a)
offset, color, org, row, col, pos: 00C6 000E 0000 0001 0013 00C6
videoPutChar: done.
videoPutChar Entered: 0D
videoPutChar: processing CR(0x0d)
videoSetVideoRx: rx[31:16], val[0:15] 000E0050
offset, color, org, row, col, pos: 00A0 000E 0000 0001 0000 00A0
videoPutChar: done.
videoPutChar Entered: 54
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00A0 000B80A0
videoSetVideoRx: rx[31:16], val[0:15] 000E0051
offset, color, org, row, col, pos: 00A2 000E 0000 0001 0001 00A2
videoPutChar: done.
videoPutChar Entered: 65
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00A2 000B80A2
videoSetVideoRx: rx[31:16], val[0:15] 000E0052
offset, color, org, row, col, pos: 00A4 000E 0000 0001 0002 00A4
videoPutChar: done.
videoPutChar Entered: 73
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00A4 000B80A4
videoSetVideoRx: rx[31:16], val[0:15] 000E0053
offset, color, org, row, col, pos: 00A6 000E 0000 0001 0003 00A6
videoPutChar: done.
videoPutChar Entered: 74
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00A6 000B80A6
videoSetVideoRx: rx[31:16], val[0:15] 000E0054
offset, color, org, row, col, pos: 00A8 000E 0000 0001 0004 00A8
videoPutChar: done.
videoPutChar Entered: 20
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00A8 000B80A8
videoSetVideoRx: rx[31:16], val[0:15] 000E0055
offset, color, org, row, col, pos: 00AA 000E 0000 0001 0005 00AA
videoPutChar: done.
videoPutChar Entered: 53
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00AA 000B80AA
videoSetVideoRx: rx[31:16], val[0:15] 000E0056
offset, color, org, row, col, pos: 00AC 000E 0000 0001 0006 00AC
videoPutChar: done.
videoPutChar Entered: 74
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00AC 000B80AC
videoSetVideoRx: rx[31:16], val[0:15] 000E0057
offset, color, org, row, col, pos: 00AE 000E 0000 0001 0007 00AE
videoPutChar: done.
videoPutChar Entered: 72
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00AE 000B80AE
videoSetVideoRx: rx[31:16], val[0:15] 000E0058
offset, color, org, row, col, pos: 00B0 000E 0000 0001 0008 00B0
videoPutChar: done.
videoPutChar Entered: 69
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00B0 000B80B0
videoSetVideoRx: rx[31:16], val[0:15] 000E0059
offset, color, org, row, col, pos: 00B2 000E 0000 0001 0009 00B2
videoPutChar: done.
videoPutChar Entered: 6E
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00B2 000B80B2
videoSetVideoRx: rx[31:16], val[0:15] 000E005A
offset, color, org, row, col, pos: 00B4 000E 0000 0001 000A 00B4
videoPutChar: done.
videoPutChar Entered: 67
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00B4 000B80B4
videoSetVideoRx: rx[31:16], val[0:15] 000E005B
offset, color, org, row, col, pos: 00B6 000E 0000 0001 000B 00B6
videoPutChar: done.
videoPutChar Entered: 32
videoPutChar: processing ordinary char.
vidOffset 16:16 0:32: B800:00B6 000B80B6
videoSetVideoRx: rx[31:16], val[0:15] 000E005C
offset, color, org, row, col, pos: 00B8 000E 0000 0001 000C 00B8
videoPutChar: done.