Message-ID: <329528C4.47DF@gbrmpa.gov.au> Date: Fri, 22 Nov 1996 12:24:36 +0800 From: Leath Muller Reply-To: leathm AT gbrmpa DOT gov DOT au Organization: Great Barrier Reef Marine Park Authority MIME-Version: 1.0 To: "G.P. Tootell" CC: djgpp AT delorie DOT com Subject: Re: boo hoo i can't make this work :( (vesa stuff) References: <5728a5$sgq AT lyra DOT csx DOT cam DOT ac DOT uk> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit > i'm trying to get the info about modes supported by a video card, now under real > mode there was no problem, i just followed the pointer, but despite various > (sometimes random) attempts at getting this to work under djgpp i can't do it :( > could someone please just tell me where i've gone wrong. > (the code should return the first supported screen mode into 'value', eventually > i want to return all the supported screen modes and find one that matches the > specs i supply.) > ps. yes i know the seg and off calculations are really screwy, this is like the > 454365436th rewrite of this code and i was clutching at straws by this time :) > it is true to say the pointer returned can be cast as a long in this way tho > right? at least under standard dos it was.. and the calculation for farpeek i got > from chapter 18 of the faq :( > #define PACKED __attribute__ ((packed)) > #pragma pack(1) > /* SuperVGA information block */ > typedef struct { > char VESASignature[4] PACKED; /* 'VESA' 4 byte signature */ > short VESAVersion PACKED; /* VBE version number */ > char *OEMStringPtr PACKED; /* Pointer to OEM string */ > long Capabilities PACKED; /* Capabilities of video card */ > short *VideoModePtr PACKED; /* Pointer to supported modes */ > short TotalMemory PACKED; /* Number of 64kb memory blocks */ > char reserved[236] PACKED; /* Pad to 256 byte block size */ > } VBE_VgaInfo; > #pragma pack() I don't think you need the pragma's if you including packed with every line... > void VBE_detect(VBE_VgaInfo *vbeinfo) { > __dpmi_regs regs; > short value,seg,off; > assert(sizeof(*vbeinfo)<_go32_info_block.size_of_transfer_buffer); > regs.x.ax=0x4F00; > regs.x.di=__tb & 0x0F; > regs.x.es=(__tb>>4) & 0xFFFF; > dosmemput(vbeinfo,sizeof(*vbeinfo),__tb); > __dpmi_int(0x10, ®s); > dosmemget(__tb,sizeof(*vbeinfo),vbeinfo); > if (strncmp(vbeinfo->VESASignature,"VESA",4)!=0) { > printf("vesa not supported.\n"); > exit(0); > } > else { > seg=(unsigned long)vbeinfo->VideoModePtr>>16; > off=(unsigned long)vbeinfo->VideoModePtr & 0xffff; > value=_farpeekw(_dos_ds,seg*16+off); > printf("%d ",value); > } > } Ok, you setting your registers up wrong, and only have to do this: regs.x.ax = 0x4F00; regs.x.es = __tb / 16; // this could be __tb >> 4; regs.x.di = 0; // This is always 0 __dpmi_int(0x10, ®s); Note I didn't dosmemput first, as the GetVESAInfo BIOS call doesn't require anything to be put first for VBE 1.2 and before. If your using VBE 2.0, your should set VESASignature to VBE2 and then dosmemput. (Although, I don't do this, and the code works fine for me...) When your doing a dosmemget, your getting the sizeof(*vbeinfo), which is 4 (a pointer is only 4 bytes), when you should be getting the sizeof(vbeinfo). To convert the VideoModePtr to segment/offset format, you must to the following: seg = (VideoModePtr & 0xFFFF0000) >> 12; off = VideoModePtr & 0xFFFF; value = _farpeekw(_dos_ds, seg + off); The VideoModePtr is stored in a really strange format. The segment is in the 4 most significant bits of the 16 most significant bits of the 32 bit VideoModePtr... easy eh? ;) The segment is in the least significant bits of the 32 bit VideoModePtr. Once you understand this, its no problem... :) You perform an AND operation to gather the top 16 bits of the VideoModePtr, and then shift these right 12 bits to make the 4 MSB the 4 LSB, which is a plain segment value in the 0-15 range, which is what you want, and where you went wrong... :) Leathal.