//
// VBE Interface class for PTC 2.0 C++ API
// Copyright (c) 1998 Jonathan Matthew (jmatthew@uq.net.au)
// The PTC 2.0 C++ API is (c) 1998 Glenn Fiedler (ptc@gaffer.org)
// This source code is licensed under the GNU LGPL
//


#ifndef __PTC_VBE_H
#define __PTC_VBE_H

#include "Types.h"
#include "Format.h"
#include "dpmi.h"

class VBE
{
    public:

        // constructor (finds and sets a video mode)
        VBE(int xres, int yres, int format, int direct, int flags);

        // destructor (returns to text mode)
        ~VBE();

        // page flipping
        void page_flip(int page, int wvr);

        // banked mode pixel load
        void banked_load(char *src, int destpage, int wvr);
        void banked_area_load(char *src, int top, int left, int bottom,
            int right, int destpage, int wvr);

        // "locking"
        void *lock(int page);
        void unlock();

        // palette setting
        void palette(const int32 palette[]);

        // data access
        inline int pitch();
        inline int height();
        inline int width();
        inline int pages();
        inline int banked();
        Format &format();

    private:

        // vesa error check
        int vesa_error(int eax);

        // pixel format identification
        int identify_pixel_format();

        // mode finding
        int find_vid_mode(int *mode, int mt, int xres, int yres, int flags);

        // virtual mode finding
        void find_virtual_mode(int *mode, int type, int xres, int yres, int flags);

        // vesa initialisation
        void vesa_init();

        // mode setting
        void set_vid_mode(int mode, int xres=0, int yres=0, int flags=0);

        // setup
        void page_set_init();

        // bank setting
        void set_bank(int bank);

        void clear_video_memory();

        // data structures
        #pragma pack(1)
        typedef struct vbe_info_block
        {
            int vbe_sig;
            unsigned char vbe_min_ver;
            unsigned char vbe_maj_ver;
            int oem_str_ptr;
            char caps[4];
            int vid_mode_ptr;
            short total_mem;
            short oem_sware_rev;
            int oem_vend_name;
            int oem_prod_name_ptr;
            int oem_prod_rev_ptr;
            char data[478];
        } vbe_info_block;

        typedef struct mode_info_block {
            short mode_attr;
            unsigned char win_a_attr;
            unsigned char win_b_attr;
            short win_gran;
            short win_size;
            short win_a_seg;
            short win_b_seg;
            int win_funcPtr;
            short bytes_per_scanline;
	
            short x_res;
            short y_res;
            unsigned char x_char_size;
            unsigned char y_char_size;
            unsigned char num_planes;
            unsigned char bits_per_pixel;
            unsigned char num_banks;
            unsigned char mem_model;
            unsigned char bank_size;
            unsigned char num_image_pages;
            unsigned char reserved1;
	
            unsigned char red_mask_size;
            unsigned char red_pos;
            unsigned char green_mask_size;
            unsigned char green_pos;
            unsigned char blue_mask_size;
            unsigned char blue_pos;
            unsigned char rsvd_mask_size;
            unsigned char rsvd_pos;
            unsigned char dir_col_mode_info;
	
            int phys_base_ptr;
            int off_scr_mem_ofs;
            short off_scr_mem_size;
            unsigned char reserved2[206];
        } mode_info_block;
        #pragma pack()

        int m_init;                 // initialisation flag
        int m_lfb;                  // lfb mapping flag
        int m_format;               // pixel format
        Format m_ptcformat;         // ptc style pixel format
        int m_iwidth;               // internal screen width
        int m_iheight;              // internal screen height
        int m_width;                // screen mode width
        int m_height;               // screen mode height
        int m_pitch;                // screen pitch
        int m_blacksize;            // unused scanlines between pages
        int m_bpp;                  // bytes per pixel
        int m_pages;                // number of pages available
        int m_mode_type;            // 0=linear, 1=banked
        DPMI dpmi;                  // dpmi
        DPMI::dpmi_ptr m_dosmem;    // dos memory block
        VBE::vbe_info_block *m_vib;      // vbe info block
        VBE::mode_info_block *m_mib;     // mode info block
        short *m_modelist;          // list of mode numbers
        int m_mode;                 // mode number selected
        char *m_screen;             // pointer to screen
        int m_page_cx[3], m_page_dx[3]; // parameters to page setting
        int m_page_addr[3];         // page addresses
        int m_page_bank[3][2];      // page starting banks
        int m_current_page;         // current page
        int m_wide_dac;             // wide dac in use?
        int m_locked;               // currently locked?
        int m_vbe_ver;              // VBE version (0=1.x, 1=later)

        // banked mode pixel load variables:
        int m_banksize;             // bank size
        int m_bankinc;
        int m_granularity;

        // protected mode interface
        char *m_pmode_interface;    // pmode interface memory
        void *m_pm_page_flip;       // pointer to page_flip function
        void *m_pm_set_bank;        // pointer to set_bank function
        void *m_pm_palette;         // pointer to palette function

};

inline int VBE::height()
{
    return m_height;
}

inline int VBE::width()
{
    return m_width;
}

inline int VBE::pitch()
{
    return m_pitch;
}

inline int VBE::pages()
{
    return m_pages;
}

inline int VBE::banked()
{
    return m_mode_type;
}

#endif
