/******************************************************************************
 * r128bios.c - Chapter 3 sample code                                         *
 *                                                                            *
 * This module contains functions pertaining to the RAGE128 BIOS function     *
 * calls, including:                                                          *
 *       BYTE R128_SetMode (int xres, int yres, int bpp)                      *
 *                                                                            *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.             *
 ******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <i86.h>
#include "defines.h"
#include "main.h"


/******************************************************************************
 * R128_SetMode                                                               *
 *  Function: sets a graphics mode for the RAGE128 video card using           *
 *            RAGE128 BIOS call 00h.  Also sets up R128_AdapterInfo global.   *
 *    Inputs: xres - spatial x resolution                                     *
 *                   (320, 512, 640, 800, 1024, 1280, 1600)                   *
 *                   restricted by memory and monitor limitations             *
 *            yres - spatial resolution                                       *
 *                   (200, 240, 384, 480, 600, 768, 1024, 1200)               *
 *                   restricted by memory and monitor limitations             *
 *            bpp - pixel depth (8, 15, 16, 24, 32)                           *
 *   Outputs: 0 - unsuccessful                                                *
 *            1 - successful                                                  *
 ******************************************************************************/
BYTE R128_SetMode (WORD xres, WORD yres, BYTE bpp)
{
    union REGS r;
    CRTCInfoBlock *mtable;
    BYTE retval = 0;
    WORD test = 0;

    if (R128_AdapterInfo.FLAGS & R128_USE_BIOS)
    {
        memset (&r, 0, sizeof (r));
        r.w.ax = 0xA000;                    // Function 00h: Set Mode.

        // Determine requested resolution.
        if (xres == 320)
        {
            switch (yres)
            {
                case 200:   r.h.ch = 0xE2;
                            break;
                case 240:   r.h.ch = 0xE3;
                            break;
                default:    // Unsupported X resolution!
                            return (0);
                            break;
            }
        }
        else if (xres == 640)
        {
            switch (yres)
            {
                case 350:   r.h.ch = 0xE6;
                            break;
                case 400:   r.h.ch = 0xE1;
                            break;
                case 480:   r.h.ch = 0x12;
                            break;
                default:    // Unsupported Y resolution!
                            return (0);
                            break;
            }
        }
        else
        {
            switch (xres)
            {
                case 400:   r.h.ch = 0xE5;
                            yres = 300;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                case 512:   r.h.ch = 0xE4;
                            yres = 384;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                case 640:   r.h.ch = 0x12;
                            break;
                case 800:   r.h.ch = 0x6A;
                            yres = 600;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                case 1024:  r.h.ch = 0x55;
                            yres = 768;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                case 1280:  r.h.ch = 0x83;
                            yres = 1024;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                case 1600:  r.h.ch = 0x84;
                            yres = 1200;
                            R128_AdapterInfo.xres = xres;
                            R128_AdapterInfo.yres = yres;
                            break;
                default:    // Unsupported X resolution!
                            return (0);
                            break;
            }
        } // if/else

        R128_AdapterInfo.xres = xres;
        R128_AdapterInfo.yres = yres;

            // Determine requested pixel depth
        switch (bpp)
        {
            case 8:     r.h.cl = 0x02;
                        break;
            case 15:    r.h.cl = 0x03;
                        break;
            case 16:    r.h.cl = 0x04;
                        break;
            case 24:    r.h.cl = 0x05;
                        break;
            case 32:    r.h.cl = 0x06;
                        break;
            default:    // Unsupported pixel depth!
                        return (0);
                        break;
        } // switch

        R128_AdapterInfo.bpp = bpp;
        if (bpp == 24)
        {
            R128_AdapterInfo.pitch = xres/8 * 3;
        }
        else
        {
            R128_AdapterInfo.pitch = xres/8;
        }

        // Call the BIOS to set the mode.
        int386 (0x10, &r, &r);
        if (r.h.ah)
        {
                return (0);                     // Error setting mode.
        }
        else
        {
                return (1);
        } // if

    }
    else
    {
        R128_AdapterInfo.xres = xres;
        R128_AdapterInfo.yres = yres;
        R128_AdapterInfo.bpp = bpp;
        R128_AdapterInfo.pitch = xres/8;
        if (bpp == 24)
        {
            R128_AdapterInfo.pitch *= 3;
        }

        switch (R128_AdapterInfo.xres)
        {
            case 320:   mtable = &mode320_60;
                        break;
            case 400:   mtable = &mode400_75;
                        break;
            case 512:   mtable = &mode512;
                        break;
            case 640:   mtable = &mode640_60;
                        break;
            case 720:   mtable = &mode720_60;
                        break;
            case 800:   mtable = &mode800_60;
                        break;
            case 848:   mtable = &mode848_88;
                        break;
            case 864:   mtable = &mode864_60;
                        break;
            case 1024:  mtable = &mode1024_60;
                        break;
            case 1152:  mtable = &mode1152_60;
                        break;
            case 1280:  mtable = &mode1280_60;
                        break;
            case 1600:  mtable = &mode1600_60;
                        break;
            case 1920:  mtable = &mode1920_60;
                        break;
            default:    mtable = &mode640_60;
                        break;
        }

    test = (WORD)R128_GetBPPValue (R128_AdapterInfo.bpp);

    retval = R128_SetModeNB (xres, yres, test, mtable);

    return (retval);
    } // else

} // R128_SetMode


