Hi!

I have no knowledge for protected mode. I think you need this for
OpenWatcom C compiler. This is the only reason to use DJGPP compiler. Am I
right?  Else the initializing you show on the YouTube Videos is very simple
for OpenWatcom.

I think (check the youtube videos with examples by Jim) OpenWatcom C
ships with libraries for convenient graphics access functionality.

Both OpenWatcom C compiled 32-bit apps and DJGPP compiled 32-bit apps
automatically use protected mode, for example by calling or including
a DOS extender or DPMI host, so you do not have to know how to use it
on the hardware level unless your apps have to do very special things.

However, because they (and all other 32-bit C compilers, I assume)
use protected mode, some things will work differently compared to
what you would see in, for example 16-bit Borland Turbo C apps.

For example access to raw memory locations or hooking int handlers
will be different. On the other hand, once you include the right
header files and use the right calls, 32-bit compilers let you do
MORE. A good example is being able to map a large high resolution
graphics framebuffer above the 1st MB of RAM to a simple C array.

For app-internal purposes, using 32 bits is trivial: You can malloc
larger amounts of memory and use larger variables and arrays. Your
pointers will often be 32-bit unsigned integers instead of either
16-bit (tiny and small 16-bit model) or pairs of 16-bit (large or
huge 16-bit model) values which you may know from 16-bit compilers.

Only for special cases, pointers will combine 32-bit offsets and
16-bit selectors values, but macros will help you in those cases.

Here are some examples for directly accessing individual bytes or
words (for dwords, use farpeekl and farpokel) in 16-bit DOS RAM
while the rest of your app naturally works as 32-bit application.

#include <pc.h> /* things like inportb() */
#include <go32.h> /* only for _dos_ds... */
#include <sys/farptr.h> /* e.g. _farpeekb(_dos_ds, linear) */
#include <dos.h> /* int86, union REGS */

typedef unsigned int uint32;

/* o is offset, s is segment, v is value. All of them "DOS-wise": */
#define peek(s, o)      _farpeekw( _dos_ds, ((uint32)(s)<<4)+(o) )
#define peekb(s, o)     _farpeekb( _dos_ds, ((uint32)(s)<<4)+(o) )
#define poke(s, o, v)   _farpokew( _dos_ds, ((uint32)(s)<<4)+(o), (v) )
#define pokeb(s, o, v)  _farpokeb( _dos_ds, ((uint32)(s)<<4)+(o), (v) )

Because the first megabyte is special (shared with DOS, with
predictable absolute addresses of some data structures etc.)
you have to access it with macros like farpeekw or farpokew,
using the pre-defined "_dos_ds".

Similarly, to access a frame buffer, you pin the memory area and
create a selector for it, then read and write pixels with farpeek
(b, w, or l for 8, 16 or 32-bit values) and farpoke (b, w, or l).

#include <dpmi.h>       /* to call the BIOS -- or use dos.h */

    __dpmi_meminfo memory_mapping;

memory_mapping.address = the physical linear address of your frame buffer according to what the VESA BIOS told you when you selected a graphics mode of your choice. memory_mapping.size = the size of your framebuffer in bytes. Note that the number of bytes per line can be larger than screen width * bytes per pixel. Use what the VESA BIOS tells you.

   __dpmi_physical_address_mapping(&memory_mapping);
   __dpmi_lock_linear_region(&memory_mapping);

   int lfbSel = __dpmi_allocate_ldt_descriptors(1);
   __dpmi_set_segment_base_address(lfbSel, memory_mapping.address);
   __dpmi_set_segment_limit(lfbSel, memory_mapping.size - 1);

Now you can access the framebuffer by defining a macro such as,
in this example for 16-bit (32k or 64k high color) and true color:

#define putpixel16(x,y,c) _farpokew(lfbSel, \
  (((x)*2) + (vesamode.bytes_line*(y))), (c))

#define putpixel32(x,y,c) _farpokel(lfbSel, \
  (((x)*4) + (vesamode.bytes_line*(y))), (c))

For NORMAL variables or arrays, where you will NOT need to
know which absolute linear memory addresses are used, you just
use NORMAL pointers as you would do in Linux apps. No macros.

You can also call the BIOS using __dpmi_int(...) to have extra
control over how mappings are treated, but DJGPP will handle
many popular cases AUTOMATICALLY if you use int86(...) with
__dpmi_regs from dos.h, for example if you want to call a
mouse driver via interrupt 0x33.

So you will often NOT need to use _dpmi_allocate_dos_memory()
or _dpmi_free_dos_memory(). Instead, you will use DJGPP library
functions for all common things. Accessing files will feel not
so different from accessing files in Linux with GCC compiled
apps, of course within the file size limits imposed by DOS.

SVGA is possible with the used board by installing a firmware.

Again, do you also have firmware for VESA VBE framebuffers?
That would make access fast and convenient. Of course, if you
use the graphics library of OpenWatcom C, or if you use the
Allegro library available for DJGPP, none of the convenience
issues will matter for you, as the libraries will do all the
work. Still, framebuffers have advantages regarding speed.

When using Allegro or the OpenWatcom graphics primitives,
you may not have to worry about any of the relatively low
level examples for DJGPP framebuffer access shown above.

Regards, Eric




_______________________________________________
Freedos-devel mailing list
Freedos-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freedos-devel

Reply via email to