How to find closest Bochs VBE Mode to Screen Width, Height and Depth using C?

os-dev

(isoftech) #1

I am in the middle of building a small VBE Driver, for Bochs.

And i need to select the best Video Mode for the Width and Height and depth that i desire! i know how to apply the video mode to VBE, but i don’t know how to get the Best match or closest matching video mode.

thanks


(Yassine) #2

As VESA stopped supported assigned Codes for video modes, you will have to query your Graphics card for the modes it supports before choosing the one to use, thus you will need to go through all supported modes by your graphics cards and compare them with the criteria you need the C method below is mostly taken from this link: Getting VBE Mode Info, it explains all about VBE, but the function below should be crystal clear:

uint16_t vbe_mode_best_match(int x, int y, int depth)
{
    struct VbeInfoBlock *vbeInfo = (VbeInfoBlock *)0x2000;
    struct ModeInfoBlock *modeInfo = (ModeInfoBlock *)0x3000;
    uint16_t *modes;
    int i;
    uint16_t best_match = 0x13;
    int pixdiff, bestpixdiff = DIFF(320 * 200, x * y);
    int depthdiff, bestdepthdiff = 8 >= depth ? 8 - depth : (depth - 8) * 2;
    
    strncpy(vbeInfo->VbeSignature, "VBE2", 4);
    intV86(0x10, "ax,es:di", 0x4F00, 0, vbeInfo);       // Query VBE information block.
    
    if ((uint16_t)v86.tss.eax != 0x004F) return best_match;
 
    modes = (uint16_t *)REALPTR(vbeInfo->VideoModePtr); // get the modes array, returned by the call above.
    for (i = 0 ; modes[i] != 0xFFFF ; i++)
    {
        intV86(0x10, "ax,cx,es:di", 0x4F01, modes[i], 0, modeInfo); // Acquire current mode Information.
        
        if ((uint16_t)v86.tss.eax != 0x004F ) continue;
        
        // Does the current mode supports linear frame buffer, if not skip it.
        if ((modeInfo->attributes & 0x90) != 0x90) continue;
        
        // Not a packed pixel nor a direct color mode...
        if (modeInfo->memory_model != 4 && modeInfo->memory_model != 6) continue;
        
        // Check if this is the exact mode we were looking for, and return directly if it's exact match.
        if (x == modeInfo->XResolution && y == modeInfo->YResolution && depth == modeInfo->BitsPerPixel)
            return modes[i];
            
        // Otherwise, compare to the closest match so far, set it as best if needed.
        pixdiff = DIFF(modeInfo->Xres * modeInfo->Yres, x * y);
        depthdiff = (modeInfo->bpp >= depth)? modeInfo->bpp - depth : (depth - modeInfo->bpp) * 2;
        
        if (bestpixdiff > pixdiff || (bestpixdiff == pixdiff && bestdepthdiff > depthdiff))
        {
            best_match = modes[i];
            bestpixdiff = pixdiff;
            bestdepthdiff = depthdiff;
        }
    }
    if ( x == 640 && y == 480 && depth == 1 ) return 0x11;
        return best_match;
}

I hope that’s what you need otherwise you will need to rephrase your question!