Setting Vesa Video Modes

Street Raider

This article is a reaction to "How to code 16 bit color graphics" by Rawhed / Sensory Overload, published in Hugi #16. It deals with coding in hi-color modes. Here is some code from that article which was used to set the VESA hi-color mode:

        mov ax,4f02       ;the "setmode" function (hex)
        mov bx,10e        ;the video mode to set (hex)
        int 10h

This is a simple way to decrease the number of people able to view demos. The reason is that another video card can have a different mode number to set the wanted resolution and color depth. The VESA standard allows that.

So, what should you do to set the mode you want? The solution is to retrive information about supported video modes and choose the desired one. The VideoModePtr field of the VesaInfoBlock structure points to such a list of supported modes. But that list might not contain all modes, so the better way is to directly enumerate each possible value. I recommend using values in the range from 100h to 400h. Higher values lead to higher detection probability and to higher delay in case of mode absence.

Here is an example of a routine to set a mode with specified resolution and color depth. The full sources are included with this issue of the Hugi magazine.

        int SetDisplayMode(int Width, int Height, int bpp, int lfb = 0)
        {
          DPMIRegs Regs;
          DosHandle Handle;
          ModeInfoBlock *ModeInfo;
          int ModeDepth;
          int VideoMode = 0;
          int n;

          @X07// enumerate modes

          Handle = AllocDosMemory(sizeof(ModeInfoBlock) >> 4);
          ModeInfo = (ModeInfoBlock*) (DosHandle_Segment(Handle) << 4);

          for (n = 0x100; n < 0x400; n++)
          {
            memset(&Regs, 0, sizeof(DPMIRegs));
            Regs.ES = DosHandle_Segment(Handle);
            Regs.ECX = n;
            Regs.EAX = 0x4F01;
            RealModeInterrupt(0x10, &Regs);

            @X07// check if mode exists
            if ((Regs.EAX & 0xFFFF) != 0x004F) continue;
            if ((ModeInfo->ModeAttributes & 1) == 0) continue;

            if (ModeInfo->MemoryModel == 4) ModeDepth = 8;
            else if (ModeInfo->MemoryModel == 6)
              ModeDepth = (ModeInfo->RedMaskSize + ModeInfo->GreenMaskSize +
                ModeInfo->BlueMaskSize + ModeInfo->RsvdMaskSize);
            else continue;

            if ((Width == ModeInfo->XResolution) &&
                (Height == ModeInfo->YResolution) &&
                (bpp == ModeDepth))
            {
              if (lfb && !((ModeInfo->ModeAttributes) & 0x80)) continue;

              VideoMode = lfb ? (n | VESA_LFB) : n;

              if (SetVesaMode(VideoMode) != VESA_SUCCESS)
              {
                VideoMode = 0;
                continue;
              }

              break; @X07// break loop
            }
          }

          FreeDosMemory(Handle);

          return VideoMode;
        }

The function returns the number of the set video mode, or zero if no matching modes have been found.

And I recommend you do not spend too much time on coding such things. It would be better if you used a more decent API than VESA. It could be PTC or some DirectX wrapper.

Happy coding!

Street Raider // DDT Ent.