Text Mode Cursor: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(8 intermediate revisions by 8 users not shown)
Line 16:
 
* AH = 0x01
* CH = 0x3F (bits 06-7 unused, bit 5 disables cursor, bits 0-4 control cursor shape)
 
===Moving the Cursor===
Line 47:
'''Source in C'''
 
<sourcesyntaxhighlight lang="c">
void enable_cursor(uint8_t cursor_start, uint8_t cursor_end)
{
Line 56:
outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end);
}
</syntaxhighlight>
</source>
 
===Disabling the Cursor===
Line 62:
'''Source in C'''
 
<sourcesyntaxhighlight lang="c">
void disable_cursor()
{
Line 68:
outb(0x3D5, 0x20);
}
</syntaxhighlight>
</source>
 
'''Source in Assembly'''
 
<sourcesyntaxhighlight lang="asm">
disable_cursor:
pushf
Line 90:
popf
ret
</syntaxhighlight>
</source>
 
===Moving the Cursor===
Line 98:
'''Source in C'''
 
<sourcesyntaxhighlight lang="c">
void update_cursor(int x, int y)
{
Line 108:
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
</syntaxhighlight>
</source>
 
'''Source in Assembly'''
 
<sourcesyntaxhighlight lang="asm">
Cursor:
; BL = x
VGA.Width equ 80
; BH = y
update_cursor:
pushfq
push eax
push ebx
push ecx
push edx
 
.SetCoords:
; position = x * VGA_HEIGHT + y
; input bx = x, ax = y
mov ax, bx
and; modifies ax, 0FFhbx, dx
mov cl, VGA_HEIGHT
mul cl
mov cx, bx
shr cx, 8
add ax, cx
mov cx, ax
; cursor low port to VGA index register
mov al, 0Fh
mov dx, 3D4h
out dx, al
 
mov dl, VGA.Width
; cursor low position to VGA data register
mul dl
mov ax, cx
movadd dxbx, 3D5hax
 
.SetOffset:
; input bx = cursor offset
; modifies al, dx
 
mov dx, 0x03D4
mov al, 0x0F
out dx, al
 
inc dl
; cursor high port to VGA index register
mov al, 0Ehbl
mov dx, 3D4h
out dx, al
 
dec dl
; cursor high position to VGA data register
mov axal, cx0x0E
shr ax, 8
mov dx, 3D5h
out dx, al
 
popinc edxdl
mov al, bh
pop ecx
out dx, al
pop ebx
pop eax
popfq
ret
</syntaxhighlight>
</source>
 
===Get Cursor Position===
Line 167 ⟶ 152:
'''Source in C'''
 
<sourcesyntaxhighlight lang="c">
uint16_t get_cursor_position(void)
{
Line 177 ⟶ 162:
return pos;
}
</syntaxhighlight>
</source>
 
==Font based "graphical" cursor==
 
===Used by===
 
Back in the DOS days it was quite common not to use the hardware VGA cursor at all, instead overriding the VGA fonts to create an arrow pointer just like in graphical modes. This technique was used in [https://en.wikipedia.org/wiki/Norton_Utilities Norton Utilities] or the DOS version of [[Norton Diskedit]] for example.
 
[[Image:Itmouse.png|Arrow cursor in text mode]]
 
You can easily spot this font altering cursor by the cursor color: as only the fonts are altered and the attribute bytes are untouched, the pointer changes color as you move it around.
 
Here's another example from the Screenshots forum [https://forum.osdev.org/download/file.php?id=2264&mode=view TUI with 8x8 characters and pointing finger-shaped cursor]
 
===How to implement===
 
The basic principle is to store 4 bytes (2x2) from the screen, copy their [[VGA Fonts]] to some unused box drawing characters (0xC0 - 0xDF), OR mask the arrow onto then write those 2x2 box drawing characters on screen. Then when the mouse moved, the original 4 bytes are restored on screen, and the whole procedure repeated on the new position.
 
It is important to use box drawing characters, because normally VGA displays fonts as 9x16, adding an empty 9th column, which would cause a "gap" in the pointer. With the box drawing characters that 9th column is a copy of the 8th column, and therefore does not cut the pointer in half. If you use 8x8 characters (like 80x50 or 132x50 modes) then there are no character separator columns, and you are free to use any character you like. On the forum example above you can spot the cursor on the ASCII table at characters 0xF0 - 0xF3.
 
Although the arrow size is the same as one character (typically 8x16 or 8x8), as the pointer can be moved with pixel precision it can overlap with the next character both horizontally and vertically, thus giving the total 4 bytes requirement:
<pre>
char 1 attr 1 char 2 attr 2
........|????????|........|???????? first line
........|????????|........|???????? (note attribute bytes are untouched)
........|????????|........|????????
....x...|????????|........|????????
....xx..|????????|........|????????
....xxx.|????????|........|????????
....xxxx|????????|........|????????
....xxxx|????????|x.......|????????
--------+--------+--------+--------
....xxxx|????????|xx......|???????? second line
....xxxx|????????|xxx.....|????????
....xxxx|????????|xxxx....|????????
.......x|????????|x.......|????????
.......x|????????|x.......|????????
........|????????|xx......|????????
........|????????|........|????????
........|????????|........|????????
char 3 attr 3 char 4 attr 4
</pre>
You can read the VGA Fonts with BIOS, or if you're already in protected mode, with VGA registers. Read [[VGA Fonts]] article for more information.
 
The character positions are calculated by dividing mouse coordinates by font size: cx = mx / 8 and cy = my / 16. Then you calculate my % 16 to get the first byte of the font glyph to be modified, and mx % 8 to get the shift value by which you have to shift the arrow mask.
 
==A Note on GRUB==
Line 184 ⟶ 213:
 
==See Also==
* [http://wiki.osdev.org/VGA_Hardware [VGA Hardware]]
* [http://wiki.osdev.org/Text_UI [Text UI]]
 
===External Links===
Line 191 ⟶ 220:
* https://web.archive.org/web/20080731014051/http://www.bookcase.com:80/library/dos/ints/int10.html
* https://web.archive.org/web/20120324083032/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_13/CH13-2.html
* https://en.wikipedia.org/wiki/VGA-compatible_text_mode
 
[[Category:Video]]