How do i read/get the cursor position?
How do i read/get the cursor position?
For a shell, I need a part of a function get the cursor position.
However, I can't find any documentation or code that shows how i can get the cursor position.
How do I get this?
However, I can't find any documentation or code that shows how i can get the cursor position.
How do I get this?
Re: How do i read/get the cursor position?
I meant get the cursor location/position, not setting it. I already have a function that sets the cursor.iansjack wrote:http://wiki.osdev.org/Text_Mode_Cursor
Re: How do i read/get the cursor position?
Why do you need to get it again? Why not just store the position of the cursor in your code?
com.sun.java.swing.plaf.nimbus.InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState
Compiler Development Forum
Compiler Development Forum
Re: How do i read/get the cursor position?
I've been following your train-wreck on #osdev. You don't listen so there is little point in anyone wasting their time to help you.
One last try. The text cursor is at 0, 0 until you put it somewhere else. And then you know where it is.
One last try. The text cursor is at 0, 0 until you put it somewhere else. And then you know where it is.
Re: How do i read/get the cursor position?
Yep, I should do that.zenzizenzicube wrote:Why do you need to get it again? Why not just store the position of the cursor in your code?
EDIT: Got it, but i get a space character every time i release a key.
Re: How do i read/get the cursor position?
Use INT 10h. Go to Wikipedia. That's a nice reference. Learn Assembly instead! C is useless. Assembly is great. Look how many good projects are written 100% fully in Assembly.
Re: How do i read/get the cursor position?
I'm in Protected Mode (you can't use int 10h) and thanks but I'm not switching to Assembly, i prefer C/C++.TheDev100 wrote:Use INT 10h. Go to Wikipedia. That's a nice reference. Learn Assembly instead! C is useless. Assembly is great. Look how many good projects are written 100% fully in Assembly.
-
- Posts: 1
- Joined: Thu Jan 05, 2017 12:20 pm
- Libera.chat IRC: ThinkingMind
Re: How do i read/get the cursor position?
In case you do not know how to print a character, read the following.
In case you already know how to print a character, still read the following.
0xB8000 | character at (0, 0) |
0xB8001 | color of character at (0, 0) |
0xB8002 | character at (1, 0) |
0xB8003 | color of character at (1, 0) |
0xB8004 | character at (2, 0) |
0xB8005 | color of character at (2, 0) |
0xB8006 | character at (3, 0) |
0xB8007 | color of character at (3, 0) |
.
.
.
To improve performance, you should store the cursor's position in two variables and update the cursor whenever necessary. By doing so, we will avoid reading from the controller. Also when you are OS starts, you would want to start printing text from (0, 0) right?
If you observe the memory layout I posted at the start, you can derive the following formula which tells you the memory location where the character at (x, y) is stored:
location = 0xB8000 + (y*80 + x)*2
Why 80? There are 80 characters per line.
Why 2? The first byte is used to store the character and the next byte is used to store the color/attribute. So each character takes up two bytes.
You would want to have a common color for all characters, so you store the color information it in a variable.
To display a character on the screen, all you have to do is write to the correct memory location. Nothing to do with the hardware.
x, y always has the position of the next character to be printed.
Where should the cursor appear?
"Hiiiiiiiii_"
..........^ the cursor should appear in the location of the next character to be printed
so that means that x, y are essentially storing the cursor's new position.
Unlike displaying characters on screen, the cursor has to be updated by talking to the CRT controller using the in/out instruction.
The controller accepts the position as:
cursor position = y*80 + x
25*80 = 2000, this would mean the cursor position cannot be stored in a byte. You'd need at least two bytes.
Unfortunately, you cannot send two bytes of data in a single out instruction to the CRT controller. You have to split it into two bytes and send separately.
So everytime you print a character, you must update the cursor.
The final code would look something like this:
You'll never need to read the location from the controller because you already have it
You might also want to update the cursor when your OS starts so that it moves to zero (in case it had been moved somewhere else by the bootloader or BIOS or whatever). Might also want to clear the screen? That is for you to write after reading this post (fill the screen with spaces).
The code I gave does not handle null character, carriage return, backspace, etc. Here is a better (more complete) version of the same.
When you are printing strings, you should update the cursor only once. Not every time you print a character. So instead of having update cursor in putc, add it in your puts.
In case you already know how to print a character, still read the following.
0xB8000 | character at (0, 0) |
0xB8001 | color of character at (0, 0) |
0xB8002 | character at (1, 0) |
0xB8003 | color of character at (1, 0) |
0xB8004 | character at (2, 0) |
0xB8005 | color of character at (2, 0) |
0xB8006 | character at (3, 0) |
0xB8007 | color of character at (3, 0) |
.
.
.
To improve performance, you should store the cursor's position in two variables and update the cursor whenever necessary. By doing so, we will avoid reading from the controller. Also when you are OS starts, you would want to start printing text from (0, 0) right?
Code: Select all
int x = 0, y = 0;
location = 0xB8000 + (y*80 + x)*2
Why 80? There are 80 characters per line.
Why 2? The first byte is used to store the character and the next byte is used to store the color/attribute. So each character takes up two bytes.
You would want to have a common color for all characters, so you store the color information it in a variable.
Code: Select all
static uint8_t attribute = 0x0F;
Code: Select all
static void putc(unsigned char c)
{
uint16_t *where = 0xB8000 + (y *80 + x);
*where = c | (attribute << 8);
x++;
if(x == 80)
{
x = 0;
y++;
}
}
Where should the cursor appear?
"Hiiiiiiiii_"
..........^ the cursor should appear in the location of the next character to be printed
so that means that x, y are essentially storing the cursor's new position.
Unlike displaying characters on screen, the cursor has to be updated by talking to the CRT controller using the in/out instruction.
The controller accepts the position as:
cursor position = y*80 + x
25*80 = 2000, this would mean the cursor position cannot be stored in a byte. You'd need at least two bytes.
Unfortunately, you cannot send two bytes of data in a single out instruction to the CRT controller. You have to split it into two bytes and send separately.
Code: Select all
unsigned int temp = y * 80 + x;
outportb(0x3D4, 0xE);
outportb(0x3D5, temp >> 8);
outportb(0x3D4, 0xF);
outportb(0x3D5, temp);
The final code would look something like this:
Code: Select all
static void putc(unsigned char c)
{
uint16_t *where = 0xB8000 + (y *80 + x);
*where = c | (attribute << 8);
x++;
if(x == 80)
{
x = 0;
y++;
}
unsigned int temp = y * 80 + x;
outportb(0x3D4, 0xE);
outportb(0x3D5, temp >> 8);
outportb(0x3D4, 0xF);
outportb(0x3D5, temp);
}
You might also want to update the cursor when your OS starts so that it moves to zero (in case it had been moved somewhere else by the bootloader or BIOS or whatever). Might also want to clear the screen? That is for you to write after reading this post (fill the screen with spaces).
The code I gave does not handle null character, carriage return, backspace, etc. Here is a better (more complete) version of the same.
Code: Select all
static void putc(unsigned char c)
{
switch(c)
{
case '\0': return;
case '\b':
if(curPos_x != 0) curPos_x--;
break;
case ' ':
curPos_x++;
break;
case '\t':
curPos_x = (curPos_x + 8) & ~(8 - 1);
break;
case '\r':
curPos_x = 0;
break;
case '\n':
curPos_x = 0;
curPos_y++;
break;
default:
{
if(isprint(c))
{
uint16_t *where = vmemptr + (curPos_y * TEXTMODE_MAX_X + curPos_x);
*where = c | (attribute << 8);
curPos_x++;
}
break;
}
}
if(curPos_x >= TEXTMODE_MAX_X)
{
curPos_x = 0;
curPos_y++;
}
if(curPos_y >= TEXTMODE_MAX_Y)
{
uint16_t blank = 0x20 | (attribute << 8);
uint16_t temp = curPos_y - TEXTMODE_MAX_Y + 1;
memcpy (vmemptr, vmemptr + temp * TEXTMODE_MAX_X, (TEXTMODE_MAX_Y - temp) * TEXTMODE_MAX_X * 2);
memsetw (vmemptr + (TEXTMODE_MAX_Y - temp) * TEXTMODE_MAX_X, blank, TEXTMODE_MAX_X);
curPos_y = TEXTMODE_MAX_Y - 1;
}
updatecursor();
}
Last edited by ThinkingMind on Sun Jan 15, 2017 7:14 am, edited 1 time in total.
Re: How do i read/get the cursor position?
I already created my own functions, i only need that character to not appear.ThinkingMind wrote:In case you do not know how to print a character, read the following.
In case you already know how to print a character, still read the following.
0xB8000 | character at (0, 0) |
0xB8001 | color of character at (0, 0) |
0xB8002 | character at (1, 0) |
0xB8003 | color of character at (1, 0) |
0xB8004 | character at (2, 0) |
0xB8005 | color of character at (2, 0) |
0xB8006 | character at (3, 0) |
0xB8007 | color of character at (3, 0) |
.
.
.
To improve performance, you should store the cursor's position in two variables and update the cursor whenever necessary. By doing so, we will avoid reading from the controller. Also when you are OS starts, you would want to start printing text from (0, 0) right?
If you observe the memory layout I posted at the start, you can derive the following formula which tells you the memory location where the character at (x, y) is stored:Code: Select all
int x = 0, y = 0;
location = 0xB8000 + (y*80 + x)*2
Why 80? There are 80 characters per line.
Why 2? The first byte is used to store the character and the next byte is used to store the color/attribute. So each character takes up two bytes.
You would want to have a common color for all characters, so you store the color information it in a variable.To display a character on the screen, all you have to do is write to the correct memory location. Nothing to do with the hardware.Code: Select all
static uint8_t attribute = 0x0F;
x, y always has the position of the next character to be printed.Code: Select all
static void putc(unsigned char c) { uint16_t *where = 0xB8000 + (y *80 + x); *where = c | (attribute << 8); x++; if(x == 80) { x = 0; y++; } }
How should the cursor appear?
"Hiiiiiiiii_"
...........^ the cursor should appear in the location of the next character to be printed
so that means that x, y are essentially storing the cursor's new position.
Unlike displaying characters on screen, the cursor has to be updated by talking to the CRT controller using the in/out instruction.
The controller accepts the position as:
cursor position = y*80 + x
25*80 = 2000, this would mean the cursor position cannot be stored in a byte. You'd need at least two bytes.
Unfortunately, you cannot send two bytes of data in a single out instruction to the CRT controller. You have to split it into two bytes and send separately.
So everytime you print a character, you must update the cursor.Code: Select all
unsigned int temp = y * 80 + x; outportb(0x3D4, 0xE); outportb(0x3D5, temp >> 8); outportb(0x3D4, 0xF); outportb(0x3D5, temp);
The final code would look something like this:
You'll never need to read the location from the controller because you already have itCode: Select all
static void putc(unsigned char c) { uint16_t *where = 0xB8000 + (y *80 + x); *where = c | (attribute << 8); x++; if(x == 80) { x = 0; y++; } unsigned int temp = y * 80 + x; outportb(0x3D4, 0xE); outportb(0x3D5, temp >> 8); outportb(0x3D4, 0xF); outportb(0x3D5, temp); }
The code I gave does not handle null character, carriage return, backspace, etc. Here is a better (more complete) version of the same.When you are printing strings, you should update the cursor only once. Not every time you print a character. So instead of having update cursor in putc, add it in your puts.Code: Select all
static void putc(unsigned char c) { switch(c) { case '\0': return; case '\b': if(curPos_x != 0) curPos_x--; break; case ' ': curPos_x++; break; case '\t': curPos_x = (curPos_x + 8) & ~(8 - 1); break; case '\r': curPos_x = 0; break; case '\n': curPos_x = 0; curPos_y++; break; default: { if(isprint(c)) { uint16_t *where = vmemptr + (curPos_y * TEXTMODE_MAX_X + curPos_x); *where = c | (attribute << 8); curPos_x++; } break; } } if(curPos_x >= TEXTMODE_MAX_X) { curPos_x = 0; curPos_y++; } if(curPos_y >= TEXTMODE_MAX_Y) { uint16_t blank = 0x20 | (attribute << 8); uint16_t temp = curPos_y - TEXTMODE_MAX_Y + 1; memcpy (vmemptr, vmemptr + temp * TEXTMODE_MAX_X, (TEXTMODE_MAX_Y - temp) * TEXTMODE_MAX_X * 2); memsetw (vmemptr + (TEXTMODE_MAX_Y - temp) * TEXTMODE_MAX_X, blank, TEXTMODE_MAX_X); curPos_y = TEXTMODE_MAX_Y - 1; } updatecursor(); }
Re: How do i read/get the cursor position?
You are printing the release scancode. As you haven't allowed for this it is printing a random character, which happens to be blank.
Re: How do i read/get the cursor position?
I know that, but I don't know what the release scancode is (it's neither 0x80 or 0x81).iansjack wrote:You are printing the release scancode. As you haven't allowed for this it is printing a random character, which happens to be blank.
Re: How do i read/get the cursor position?
If you mean the characters above 0x80, this does not work (scancode < 0x80 doesn't work).
-
- Member
- Posts: 501
- Joined: Wed Jun 17, 2015 9:40 am
- Libera.chat IRC: glauxosdever
- Location: Athens, Greece
Re: How do i read/get the cursor position?
Hi,
I've decided to stop trying to help him anymore - he clearly needs to mature first.
Regards,
glauxosdever
And not only that, he is ungrateful we try to help him. He even went and spammed the channel.iansjack wrote:I've been following your train-wreck on #osdev. You don't listen so there is little point in anyone wasting their time to help you.
I've decided to stop trying to help him anymore - he clearly needs to mature first.
Regards,
glauxosdever