[comp.sys.ibm.pc] How do I point to the frame buffer?

dan@juniper.UUCP (Dan Galewsky) (06/28/88)

Could someone please tell me how to set up a  pointer to the frame buffer
on my PC's CGA from Microsoft C? I know that the frame buffer starts at 
0xb800. So I tried the following :

far char *Screen;
Screen = (char *)0Xb800;

for (i=0;i<FBSIZE;i++)
    *Screen++ = SOMEVALUE;

I believe that this should work (but my PC does not...)
So - what am I doing wrong? Misuse of the far pointer? Wrong memory model?
Wrong address?? 

			Puzzled...
			    -Dan
Dan Galewsky
{...}sun!austsun!galewsky
galewsky%asc@sdr.slb.com

bright@Data-IO.COM (Walter Bright) (06/30/88)

In article <2784@juniper.UUCP> dan@juniper.UUCP (Dan Galewsky) writes:
<Could someone please tell me how to set up a  pointer to the frame buffer
<on my PC's CGA from Microsoft C?
<So I tried the following :
<
<far char *Screen;
<Screen = (char *)0Xb800;
<for (i=0;i<FBSIZE;i++)
<    *Screen++ = SOMEVALUE;

Try:
	unsigned short far *p;
	p = (unsigned short far *) 0xB8000000;
	for (i = 0; i < 80*25; i++)
		*p++ = 0x0700 + 'c';	/* fill screen with 'c'	*/
Video memory is 16 bits/char, the 0x0700 is the attribute for normal text.

haugj@pigs.UUCP (Joe Bob Willie) (06/30/88)

In article <2784@juniper.UUCP>, dan@juniper.UUCP (Dan Galewsky) writes:
> Could someone please tell me how to set up a  pointer to the frame buffer
> on my PC's CGA from Microsoft C? I know that the frame buffer starts at 
> 0xb800. So I tried the following :
> 
> far char *Screen;
> Screen = (char *)0Xb800;
>-- 
> 			Puzzled...

Dear Puzzled,

Your C program hates you because you used the wrong address.  Now, I'm
not a big PC jockey, but perhaps you should have used

far	char	*Screen = 0xb8000;

as the video memory address.

Sincerly,
Joe Bob Willie Landers
-- 
 The Beach Bum                                 Big "D" Home for Wayward Hackers
 UUCP: ...!killer!rpp386!jfh                          jfh@rpp386.uucp :SMAILERS

 "You are in a twisty little maze of UUCP connections, all alike" -- fortune

psc@lznv.ATT.COM (Paul S. R. Chisholm) (07/01/88)

< "Would you buy a used operating system from these guys?" >

In article <2784@juniper.UUCP>, dan@juniper.UUCP (Dan Galewsky) writes:
> Could someone please tell me how to set up a  pointer to the frame buffer
> on my PC's CGA from Microsoft C? I know that the frame buffer starts at 
> 0xb800. So I tried the following :
> 
> far char *Screen;
> Screen = (char *)0Xb800;
 Dan Galewsky, {...}sun!austsun!galewsky, galewsky%asc@sdr.slb.com

The frame buffer starts at B800:0000, which would be 0xB8000 if the
8088 had a linear address space.  It doesn't.  The right way to do this
in MS or Turbo C is

	#include <dos.h>
	far char * const Screen = MK_FP( 0xB800, 0 );

(The "const" is optional; it tells the compiler that Screen is a
constant, and that no one should be allowed to muck with it.)

Comments?

-Paul S. R. Chisholm, {ihnp4,cbosgd,allegra,rutgers}!mtune!lznv!psc
AT&T Mail !psrchisholm, Internet psc@lznv.att.com
I'm not speaking for my employer, I'm just speaking my mind.

izumi@violet.berkeley.edu (Izumi Ohzawa) (07/01/88)

In article <222@pigs.UUCP> haugj@pigs.UUCP (Joe Bob Willie) writes:
>In article <2784@juniper.UUCP>, dan@juniper.UUCP (Dan Galewsky) writes:
>> Could someone please tell me how to set up a  pointer to the frame buffer
>> on my PC's CGA from Microsoft C? I know that the frame buffer starts at 
>> 0xb800. So I tried the following :
>> far char *Screen;
>> Screen = (char *)0Xb800;
>> 			Puzzled...
>Dear Puzzled,
>far	char	*Screen = 0xb8000;

That doesn't work.  At least with Microsoft C, far pointer has
to be specified in the Segment:Offset format with an unsigned long
number.  So try;

far char *Screen = 0xb8000000;

or 
far char *Screen = 0xb8000000L;

izumi ohzawa
izumi@violet.berkeley.edu

haugj@pigs.UUCP (Joe Bob Willie) (07/06/88)

In article <11544@agate.BERKELEY.EDU> izumi@violet.berkeley.edu (Izumi Ohzawa) writes:
]In article <222@pigs.UUCP> haugj@pigs.UUCP (Joe Bob Willie) writes:
]>)In article <2784@juniper.UUCP>, dan@juniper.UUCP (Dan Galewsky) writes:
]>)> 0xb800. So I tried the following :
]>)> far char *Screen;
]>)> Screen = (char *)0Xb800;
]>)> 			Puzzled...
]>)Dear Puzzled,
]>)far	char	*Screen = 0xb8000;
]}
]That doesn't work.  At least with Microsoft C, far pointer has
]to be specified in the Segment:Offset format with an unsigned long
]number.  So try;
]}
]far char *Screen = 0xb8000000;

OKAY, let me rephrase what i said,

char	*Screen = 0xb8000;

does work on a '386 running SCO Xenix which uses the Microsoft C
compiler.  the actual location of the screen memory is b800:0000
in 8086 mode.  since the 80386 has 32bit segments, there isn't
much of a need for segment numbers.

i suppose the correct answer is there is no one single correct
answer.

- john.
-- 
 Joe Bob Willie                                             Big "D" Oil and Gas
 UUCP: ...!killer!rpp386!jfh                            jfh@rpp386.uucp :DOMAIN
 **** Trivia question of the day: VYARZERZIMANIMORORSEZASSEZANSERAREORSES? ****
 "You are in a twisty little maze of UUCP connections, all alike" -- fortune

bright@Data-IO.COM (Walter Bright) (07/07/88)

In article <1391@lznv.ATT.COM> psc@lznv.ATT.COM (Paul S. R. Chisholm) writes:
>The frame buffer starts at B800:0000, which would be 0xB8000 if the
>8088 had a linear address space.  It doesn't.  The right way to do this
>in MS or Turbo C is
	or Zortech C
>	#include <dos.h>
>	far char * const Screen = MK_FP( 0xB800, 0 );
>(The "const" is optional; it tells the compiler that Screen is a
>constant, and that no one should be allowed to muck with it.)
> Comments?

Replace "const" with "volatile". All hardware device locations (except
ROM ones) should be "volatile", since they can be modified by an interrupt
routine (like a TSR). One example is the ^C that appears on the screen
when you type a control C.

Also, you've declared a <const pointer to><far char>. Try instead:
	volatile unsigned short far *Screen = ...
which is <far pointer to><volatile unsigned short>. The unsigned short
instead of char is because the display memory is actually organized as
words instead of bytes. The high byte is the attribute, the low byte
the character.
Note also that "const" and "volatile" are left-associative. "far" and
"near" are right-associative. Confusing? You bet!

psc@lznv.ATT.COM (Paul S. R. Chisholm) (07/08/88)

< "Would you buy a used operating system from these guys?" >

In article <1584@dataio.Data-IO.COM>, bright@Data-IO.COM (Walter Bright) writes:
> In article <1391@lznv.ATT.COM> psc@lznv.ATT.COM (Paul S. R. Chisholm) writes:
> >The frame buffer starts at B800:0000, which would be 0xB8000 if the
> >8088 had a linear address space.  It doesn't.  The right way to do this
> >in MS or Turbo C or Zortech C is
> >	#include <dos.h>
> >	far char * const Screen = MK_FP( 0xB800, 0 );
> >(The "const" is optional; it tells the compiler that Screen is a
> >constant, and that no one should be allowed to muck with it.)

> Replace "const" with "volatile". All hardware device locations (except
> ROM ones) should be "volatile", since they can be modified by an interrupt
> routine (like a TSR). One example is the ^C that appears on the screen
> when you type a control C.

I don't think that any compiler would generate different code with the
"volatile" keyword, but that's not a bad idea.

> Also, you've declared a <const pointer to><far char>. Try instead:
> 	volatile unsigned short far *Screen = ...
> which is <far pointer to><volatile unsigned short>. The unsigned short
> instead of char is because the display memory is actually organized as
> words instead of bytes. The high byte is the attribute, the low byte
> the character.

Using an short pointer is a good idea; even on an 8/16 bit 8088, it's
faster to move one word once than one byte twice.

But I *meant* to have a constant pointer!  I didn't want anyone mucking
around with Screen.

	volatile unsigned short far * const Screen;

> Note also that "const" and "volatile" are left-associative. "far" and
> "near" are right-associative. Confusing? You bet!

"TYPE const * foo" means that *foo (the thing foo points to) is constant.
"TYPE * const foo" means that foo (the pointer itself) is constant.

Do we have you all sufficiently confused now?  Good, try this trivia
question (answer after the .sig and ^L):  When might you use this?

	volatile TYPE const * const foo;

-Paul S. R. Chisholm, {ihnp4,cbosgd,allegra,rutgers}!mtune!lznv!psc
AT&T Mail !psrchisholm, Internet psc@lznv.att.com
I'm not speaking for my employer, I'm just speaking my mind.

volatile time_t const far * const Timer = TIMER_ADDR;

Our code isn't allowed to change either Timer or the data it points to;
but the data there may change all by itself.  A real time clock!