Printing text in 640x480 graphics mode is not working

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Printing text in 640x480 graphics mode is not working

Post by osdever »

It's not printing any character. Here's the code of vgaPutchar function:

Code: Select all

void vgaPutchar(char c,word x,word y,byte fg,byte bg)
{
	int i,j = 0;
	word x_ = x;
	while(i != 8)
	{
		while(j != 8)
		{
			if(font[(int)c][j+i] == '1')
			{
				VGAPix16(x_+j,y+i,fg,640,480);
			}
			else
			{
				VGAPix16(x_+j,y+i,bg,640,480);
			}
                        j++;
		}
		i++;
		y++;
		x_ = x;
	}
}
The fonts are stored as a char array. 1 is foreground, 0 is background.
Last edited by osdever on Fri May 01, 2015 12:43 pm, edited 1 time in total.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: Printing text in 640x480 graphics mode is not working

Post by Candy »

Where do you increment j?

Please try basic debugging before asking questions.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by osdever »

Now it's printing me only first line of 8 total.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
Unsigned
Posts: 24
Joined: Thu Sep 20, 2012 6:46 pm

Re: Printing text in 640x480 graphics mode is not working

Post by Unsigned »

catnikita255 wrote: int i,j = 0;
You are initializing j and not i. You really need to initialize i, and in fact you don't need to initialize j here.
catnikita255 wrote: word x_ = x;
I think you don't need x_ at all. Delete this and substiture references to x_ by x.
catnikita255 wrote: while(j != 8)
You need to initialize j to 0 just before this line. You are incrementing j in the j loop, but you're never resetting it to 0.
catnikita255 wrote: y++;
Don't do this. You are already computing y+i, so y must not be changed.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by Brendan »

Hi,
catnikita255 wrote:Now it's printing me only first line of 8 total.
This is extremely slow anyway - so slow that it needs to be written properly regardless of whether you fix it or not, so there's no point fixing the current code. ;)

The font data is a one bit per pixel mask for each row, and in "640*480 with 16 colour" mode each byte (in each plane) is also one bit per pixel. This means that you can do 8 pixels in parallel with AND and OR (e.g. "*address = (foreground & mask) | (background & ~mask);"). You can also calculate the address of the next byte to modify with "address += 640/8" (a simple/fast addition per row); instead of doing a more expensive "address = buffer + y*680/8 + x/8" and doing that for every single pixel.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
mallard
Member
Member
Posts: 280
Joined: Tue May 13, 2014 3:02 am
Location: Private, UK

Re: Printing text in 640x480 graphics mode is not working

Post by mallard »

If you're going to write the same byte(s) to multiple bitplanes, you can use the slightly more advanced features of the VGA and get even better performance...

If you set the "Map Mask" register to a non-power-2 value, your writes will go to multiple planes simultaneously. If you're, for instance, writing white/colour text on a black background, that's all you need to do; set the map mask to the colour and then write 1bpp font data to video memory.

If you don't have a black background, check out VGA Write Mode 3. It basically allows you to choose a colour, then write 1bpp data which will be overlaid onto the current screen contents in the colour you've chosen, perfect for writing text (and many other graphics operations!). Michael Abrash (well-know programmer who'se worked for ID, Valve, Microsoft and now Oculus) has written about this, see chapter 26 (the other VGA chapters are also worth looking at).
Image
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by Brendan »

Hi,
mallard wrote:If you're going to write the same byte(s) to multiple bitplanes, you can use the slightly more advanced features of the VGA and get even better performance...
Yes; but software should never work like that.

Mostly (to avoid tearing and other unwanted effects) you should have a buffer in normal RAM, do all the drawing in that buffer, then copy from buffer to display memory as fast as possible (e.g. while avoiding areas that weren't changed, and using a "rep movsd" to minimise PCI bus transactions). This typically means that (for "640 * 480 with 16 colours") you end up changing the plane 4 times per frame (and there's no other reason to mess with slow IO ports; which means you can leave the "index" alone and set the plane with a single "out" instruction).

Of course it's more fun to do all your drawing in a standard format (e.g. 32-bits per pixel) and then convert to whatever the video mode actually wants while copying from RAM to display memory (so that you can support all pixel formats easily, without rewriting all your drawing code for each pixel format). In that case, "16 colours" is unlike everything else (because each pixel is spread across multiple planes it's too hard/slow to do the conversion while copying to display memory) and you end up with 2 buffers - one that's 32-bits per pixel that gets converted to "1-bit per plane" in a second buffer (where the second buffer is copied to display memory).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
mallard
Member
Member
Posts: 280
Joined: Tue May 13, 2014 3:02 am
Location: Private, UK

Re: Printing text in 640x480 graphics mode is not working

Post by mallard »

Brendan wrote:Hi,
mallard wrote:If you're going to write the same byte(s) to multiple bitplanes, you can use the slightly more advanced features of the VGA and get even better performance...
Yes; but software should never work like that.

Why on earth not? If your video driver model provides a higher-level API than just simple pixel access, it's fairly easy to provide these sorts of optimisations, while keeping application software generic. I know 2D acceleration has gone out of fashion these days, but it's still there and still provides advantages over the simple "framebuffer" model, especially when, like on the VGA, there isn't a nice byte-aligned linear framebuffer.
Brendan wrote: Mostly (to avoid tearing and other unwanted effects) you should have a buffer in normal RAM, do all the drawing in that buffer, then copy from buffer to display memory as fast as possible (e.g. while avoiding areas that weren't changed, and using a "rep movsd" to minimise PCI bus transactions).
While that's a perfectly reasonable and common approach (and one that Michael talks about), it's not necessarily the fastest way to do it, depending on the circumstances. (Also, note that there's not enough time to write the entire screen is the vertical refresh interval and the VGA doesn't have enough memory to do page-flipping at 640x480x4bpp, so tearing is inevitable when a high proportion of the screen changes).

There's always a cost/benefit tradeoff. My video driver model requires that the driver provide read/write/seek methods on what appears to be a linear framebuffer. That means that for VGA, the driver has to convert the data between planar and linear formats and the best optimisation that can be done is limiting plane switches to 4 per read/write operation. That's mostly good enough for my purposes.

However, if I were, for instance, implementing a unicode-based software text-mode within the VGA driver, better use of the VGA hardware would certainly be considered.
Image
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by osdever »

Again not working. Help, please.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by Brendan »

Hi,
catnikita255 wrote:Again not working. Help, please.
Typically when someone says something isn't working, it means that either they're mistaken (it does work but they expected it to do something different) and/or there's one or more problems. Note that the former may indicate a problem in the way a product was marketted, or the documentation or design. For the latter case, finding the actual cause of the problem can mostly be broken down into 3 steps:
  • Gathering symptoms
  • Analysing those symptoms to determine potential causes
  • Investing to prove or disprove potential causes; and returning to a previous step (getting more information about symptoms and trying to think of more potential causes) if all potential causes were disproven.
Of course for software, you need the executable code to gather symptoms, and you need to know the symptoms before you can theorise about potential causes, and often you need all of the code to prove or disprove a potential cause (e.g. so you can make a change and see if/how the change effected the symptom/s).

Basically; given the complete lack of any usable information (e.g. "Again not working.") and our inability to guess how the symptoms have changed since last time (are the symptoms the same, do you get a blank screen/nothing, does it cause an exception and if so which one, does it display characters that are "horizontally flipped" or in the wrong colour or...) or predict how the code has been modified since last time (did you fix all the problems that Unsigned mentioned, did you completely rewrite it like I mentioned, did you make any of many other changes?); it's impossible for anyone here to do anything to help fix the problem (other than describing generic problem solving techniques that apply to everything).

Fortunately; "describing generic problem solving techniques that apply to everything" may be what helps you the most (even if it's not what you're asking for), because the ability to find and fix bugs is a very important skill (and not just for OS developers).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by osdever »

It displays me same that it displayed before, just 1 line, not all character. Is

Code: Select all

while(i != 8)
repeats only 1 time?
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by Brendan »

Hi,
catnikita255 wrote:It displays me same that it displayed before, just 1 line, not all character. Is

Code: Select all

while(i != 8)
repeats only 1 time?
I've analysed the symptom and (based on all available information) formed a theory about the root cause. My hypothesis is that the root cause is a programmer that failed to listen.

Specifically, I suspect you ignored this:
Unsigned wrote:
catnikita255 wrote: int i,j = 0;
You are initializing j and not i. You really need to initialize i, and in fact you don't need to initialize j here.
..and you still aren't initialising i, causing i to have undefined behaviour.

Furthermore, I assume that something that executed before you called "vgaPutchar" happened to leave the value 7 on the stack (which happened to become the value of i). This seems potentially likely to me; as the code that executed before you called "vgaPutchar" is likely to be the previous invocation of "vgaPutchar"; and the compiler may have optimised the loop to something more like "{ next: i++; ...; if(i != 7) goto next;}" to remove a branch from the first iteration of the loop (which can be omitted as it depends on undefined behaviour).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by osdever »

1) i is initializing after definition, 2) I'm using vgaPutchar only once to print 'a' letter.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by Brendan »

Hi,
catnikita255 wrote:1) i is initializing after definition, 2) I'm using vgaPutchar only once to print 'a' letter.
Then we need more symptoms - e.g. is the loop doing 8 iterations but the pixels aren't being set or is the loop actually only doing one iteration; is something in "putpixel()" dodgy and interfering with the loop; if you call "vgaPutchar" multiple times do you get the same symptoms for all characters or just the first; etc.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Printing text in 640x480 graphics mode is not working

Post by osdever »

Brendan wrote:Hi,
catnikita255 wrote:1) i is initializing after definition, 2) I'm using vgaPutchar only once to print 'a' letter.
Then we need more symptoms - e.g. is the loop doing 8 iterations but the pixels aren't being set or is the loop actually only doing one iteration; is something in "putpixel()" dodgy and interfering with the loop; if you call "vgaPutchar" multiple times do you get the same symptoms for all characters or just the first; etc.


Cheers,

Brendan
1) I can't check it, because i can't print text. 2) Same symptoms. P.S. I'm fully filled first line of letters with '1' symbols, so i can see that it's printing it.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
Post Reply