Date: Mon, 21 Aug 1995 11:30:06 +0300 (IDT) From: Eli Zaretskii To: Tapio Vocadlo Cc: djgpp AT sun DOT soe DOT clarkson DOT edu Subject: Re: GPF when accessing video memory directly On Sun, 20 Aug 1995, Tapio Vocadlo wrote: > Using the _farpokeb and related functions in sys/farptr.h > compiles fine, but then GPFs with a 'unsupported int 0x0D' > message when run. All I'm doing is > > #include > > unsigned char gc=65; > > _farpokeb(0xb800,0,gc); What you should do is this: _farpokeb(_go32_conventional_mem_selector(), 0xb8000, gc); (the 3 `0's in B8000h is NOT a typo, see below). This is explained in the DJGPP FAQ list (available as faq102.zip from the same place you get DJGPP): 10.6 Q: I try to access the video memory at 0xa0000, but get Segmentation violation... A: Absolute addresses of certain memory-mapped devices are mapped differently under DJGPP, which is protected-mode environment. You can't just poke any address, that's what protected mode is all about. In non-DPMI mode, the entire graphics video memory is mapped 1:1 starting at 0xD0000000 in the program's address space; the DJGPP paging mechanism understands how SuperVGA's map their memory onto the AT bus and automatically swaps pages as the program tries to access them. The program sees a linear range from 0xD0000000 to 0xD0100000 that corresponds to each pixel in the 256-color modes of SuperVGAs. For this to work correctly, you will have to set the GO32 environment variable to the graphics driver suitable for your SuperVGA card, like this: SET GO32=driver c:\djgpp\drivers\ati.grd gw 640 gh 480 tw 132 th 43 In DPMI mode this won't work. As DJGPP v2.0 will be DPMI-only environment, this means that, after GRX 2.0 arrives, the above method should be used only as last resort. If you want to write a program which will compile and run unchanged in v2.0, use functions described in (see chapter 18 below for details). And then section 18.4 says: 18.4 Q: How can I move data between my program and the transfer buffer? Q: How do I access my peripheral card which is memory-mapped to an address between 640K and 1M? Q: How can I read or change a value of one of the variables in the BIOS data area? Q: How can I peek at an address whose far pointer I get from an INT 21h call? A: Depending on your specific needs, you can use one of three methods: * If you want to access a byte, a 16-bit word, or a 32-bit double word, use the ``far pointer'' functions documented on the sys/farptr.h header file. You should convert any real-mode far pointer segment:offset pair into a linear address (segment*16 + offset), and use _go32_conventional_mem_selector() to get the selector which allows access to conventional memory, like this: u_char value = _farpeekb(_go32_conventional_mem_selector(), segment*16 + offset); Use _farpeekw() to peek at 16-bit shorts and _farpeekl() to peek at 32-bit longs. If you need to access several (non-contiguous) values in a loop, use corresponding _farnspeekX() functions which allow you to set the selector only once, as opposed to passing it with every call.