Mail Archives: djgpp/2001/10/14/12:19:07
"Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il> writes:
> > From: Felix Natter <f DOT natter AT ndh DOT net>
> > Newsgroups: comp.os.msdos.djgpp
> > Date: 13 Oct 2001 12:20:47 +0200
> >
> > with code like this:
> >
> > __dpmi_meminfo meminf;
> > meminf.address = vbe_modeinfo.PhysicalBasePtr;
> > meminf.size = screensize;
> > if (__dpmi_physical_address_mapping(&meminf) == - 1)
> > => error
> >
> > "__dpmi_physical_address_mapping" fails on Windows 2000 (both in the DOS
> > box or when I select Dos on startup).
> >
> > I am using cwsdpmi (the version that comes with djdev2.02).
>
> Please post a minimal complete program which can be compiled and which
> exhibits this behavior. (The main detail you left out are the values
> of the base address and the size you pass to __dpmi_physical_address_mapping.)
the values are computed from getVBEModeInfo(mode) (see below).
The struct is defined in the header-file
(http://www.ndh.net/home/natter/vbetwo.h)
I will try a small program on Monday.
here is the complete code of the function that fails:
bool openVBE(int width, int height, unsigned char bpp = 8)
{
if (!initVBE())
{
printf("\nNo VBE 2.0 loaded.\n");
abort();
}
int modeidx = 0;
unsigned short mode;
while (1)
{
mode = AvailableModes[modeidx++];
if (mode == 0xFFFF)
return false;
if (getVBEModeInfo(mode) == false)
continue;
if (vbe_modeinfo.XResolution != width)
continue;
if (vbe_modeinfo.YResolution != height)
continue;
if (vbe_modeinfo.BitsPerPixel != bpp)
continue;
break;
}
getBDA8x8charpattern();
settextsize(8, 8);
xres = vbe_modeinfo.XResolution;
yres = vbe_modeinfo.YResolution;
BPP = vbe_modeinfo.BitsPerPixel;
CLIP_LEFT = 0;
CLIP_TOP = 0;
CLIP_RIGHT = xres - 1;
CLIP_BOTTOM = yres - 1;
BytesPerScanline = vbe_modeinfo.BytesPerScanline;
unsigned long screensize = BytesPerScanline * yres;
if (screensize % 4)
handleError(ErrorMessage("Screensize [PARAM1] isn't dword-aligned.", "", screensize));
offscreen = (char*)xmalloc(screensize);
screensize_dword = screensize / 4;
if (sizeof(Scanline) != 32)
handleError(ErrorMessage("Compiler DOES pad 'Scanline's at the end!!!", "", sizeof(Scanline)));
scanline_list = (Scanline*)xmalloc(yres * sizeof(Scanline));
contrast_lookup = (unsigned char*)xmalloc(0x100);
__dpmi_meminfo meminf;
meminf.address = vbe_modeinfo.PhysicalBasePtr;
meminf.size = screensize;
if (__dpmi_physical_address_mapping(&meminf) == - 1)
handleError(ErrorMessage("physical-address mapping failed", "", meminf.address));
LFB_linear_address = meminf.address;
LFBselector = __dpmi_allocate_ldt_descriptors(1);
if (LFBselector == -1)
handleError(ErrorMessage("allocating ldt-descriptors failed"));
if (__dpmi_set_segment_base_address(LFBselector, LFB_linear_address) == -1)
handleError(ErrorMessage("setting selector base address to [PARAM1] failed", "", LFB_linear_address));
if (__dpmi_set_segment_limit(LFBselector, meminf.size) == -1)
handleError(ErrorMessage("setting selector limit to [PARAM1] failed", "", meminf.size));
__dpmi_regs regs;
regs.x.ax = 0x4F02;
regs.x.bx = mode | VBE_MODEFLAG_LFB;
safe_int(0x10, ®s);
if (regs.x.ax != 0x004F)
return false;
//if ((LogicalPixelsPerScanline = getLogicalScanlineWidthPixels()) == 0)
// handleError(ErrorMessage("Couldn't get logical scanline-width."));
LogicalBytesPerScanline = BytesPerScanline;
//if (setLogicalScanlineWidthPixels(LogicalPixelsPerScanline = xres) != 1)
// handleError(ErrorMessage("Couldn't set logical scanline-width.", "", xres));
//if (getDisplayStart(&DisplayStartX, &DisplayStartY) != 1)
// handleError(ErrorMessage("Couldn't get display-start."));
DisplayStartX = 0;
DisplayStartY = 0;
//if (setDisplayStart(DisplayStartX, DisplayStartY) != 1)
// handleError(ErrorMessage("Couldn't set display-start.", "", DisplayStartX, DisplayStartY));
/*
the following is taken from someone's vesa-driver for s3-cards;
I didn't notice any difference back when I had an s3-card
*/
//come_on_push_it(); // S3 (and only S3!) S-P-E-E-D-U-P
updatecolors();
return true;
};
and here are the functions that are called:
static void safe_int(int vect, __dpmi_regs* pregs)
{
if (__dpmi_int(vect, pregs) != 0)
handleError(ErrorMessage("Error issuing RM-int (dpmi failed)", "", vect));
};
void saveScreen(const char* szfilename, char* pal)
{
FILE* scr = fopen(szfilename, "wb");
short x_res = (short)xres, y_res = (short)yres;
char curpal[0x300];
if (pal == NULL)
{
getpal(curpal);
fwrite(curpal, 0x300, 1, scr);
}
else
fwrite(pal, 0x300, 1, scr);
fwrite(&x_res, sizeof(short), 1, scr);
fwrite(&y_res, sizeof(short), 1, scr);
fwrite(offscreen, screensize_dword, 4, scr);
fclose(scr);
};
static bool initVBE()
{
__dpmi_regs regs;
strncpy(vbe_info.VESASignature, "VESA", 4);
dosmemput(&vbe_info, sizeof(VBEINFO), __tb);
regs.x.ax = 0x4F00;
regs.x.es = __tb / 16;
regs.x.di = 0x0000;
safe_int(0x10, ®s);
dosmemget(__tb, sizeof(VBEINFO), &vbe_info);
if (regs.x.ax != 0x004F || vbe_info.VBEVersion < 0x0200)
return false;
int modelist_physical = (vbe_info.VideoModePtrSegment * 16) + vbe_info.VideoModePtrOffset;
int lenbytes = 0;
unsigned short word;
do
{
dosmemget(modelist_physical + lenbytes, 2, &word);
lenbytes += 2;
} while (word != 0xFFFF);
AvailableModes = (unsigned short*)xmalloc(lenbytes);
dosmemget(modelist_physical, lenbytes, AvailableModes);
regs.x.ax = 0x4F0A;
regs.h.bl = 0x00;
safe_int(0x10, ®s);
VBE_PM_Interface* vbe_PMI = (VBE_PM_Interface*)xmalloc(regs.x.cx);
dosmemget((regs.x.es * 16) + regs.x.di, regs.x.cx, vbe_PMI);
PMI_setDisplayStart = (void*)((char*)vbe_PMI + vbe_PMI->setDisplayStart);
PMI_setPrimaryPalette = (void*)((char*)vbe_PMI + vbe_PMI->setPrimaryPalette);
return true;
};
static bool getVBEModeInfo(unsigned short mode)
{
__dpmi_regs regs;
regs.x.ax = 0x4F01;
regs.x.cx = mode;
regs.x.es = __tb / 16;
regs.x.di = 0x0000;
safe_int(0x10, ®s);
dosmemget(__tb, sizeof(VBE_MODEINFO), &vbe_modeinfo);
if (regs.x.ax != 0x004F || !(vbe_modeinfo.ModeAttributes & vbeModeAvailablewithLFB))
return false;
else
return true;
};
> Also, how exactly does it fail? do you get -1 from the function? If
> not, please tell the details about the failure.
yes, -1.
> > does a more recent version of cwsdpmi fix this or is there another
> > workaround ?
>
> The latest CWSDPMI does indeed fix a subtle problem with this DPMI
> function, but CWSDPMI has nothing to do with running your program on
> Windows, only on DOS. So it's not at all clear that this is a CWSDPMI
> issue.
the problem occurs both in the "DOS-Box" and when I boot DOS
(the version of DOS that comes with Windows 2000).
I will try to use cwsdpmi 5 on Monday.
--
Felix Natter
- Raw text -