DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/vga.h
00001  /*
00002  *  Copyright (C) 2002-2019  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA.
00017  */
00018 
00019 
00020 #ifndef DOSBOX_VGA_H
00021 #define DOSBOX_VGA_H
00022 
00023 #ifndef DOSBOX_DOSBOX_H
00024 #include "dosbox.h"
00025 #endif
00026 #include <iostream>
00027 
00028 #define VGA_LFB_MAPPED
00029 
00030 #define S3_LFB_BASE_DEFAULT       0xE0000000u
00031 
00032 class PageHandler;
00033 
00034 enum VGAModes {
00035     M_CGA2,         // 0
00036     M_CGA4,
00037     M_EGA,
00038     M_VGA,
00039     M_LIN4,
00040     M_LIN8,         // 5
00041     M_LIN15,
00042     M_LIN16,
00043     M_LIN24,
00044     M_LIN32,
00045     M_TEXT,         // 10
00046     M_HERC_GFX,
00047     M_HERC_TEXT,
00048     M_CGA16,
00049     M_TANDY2,
00050     M_TANDY4,       // 15
00051     M_TANDY16,
00052     M_TANDY_TEXT,
00053     M_AMSTRAD,
00054     M_PC98,
00055     M_FM_TOWNS,     // 20 STUB
00056     M_PACKED4,
00057     M_ERROR,
00058 
00059     M_MAX
00060 };
00061 
00062 extern const char* const mode_texts[M_MAX];
00063 
00064 enum VGA_Vsync {
00065         VS_Off,
00066         VS_On,
00067         VS_Force,
00068         VS_Host,
00069 };
00070 
00071 struct vsync_state {
00072         double period;
00073         bool manual;            // use manual vsync timing
00074         bool persistent;        // use persistent timer (to keep in sync even after internal mode switches)
00075         bool faithful;          // use faithful framerate adjustment
00076 };
00077 
00078 extern struct vsync_state vsync;
00079 extern float uservsyncjolt;
00080 
00081 #define CLK_25 25175u
00082 #define CLK_28 28322u
00083 
00084 #define MIN_VCO 180000u
00085 #define MAX_VCO 360000u
00086 
00087 #define S3_CLOCK_REF    14318u  /* KHz */
00088 #define S3_CLOCK(_M,_N,_R)      ((S3_CLOCK_REF * (((Bitu)_M) + 2ul)) / ((((Bitu)_N) + 2ul) * ((Bitu)1ul << ((Bitu)_R))))
00089 #define S3_MAX_CLOCK    150000u /* KHz */
00090 
00091 #define S3_XGA_1024             0x00u
00092 #define S3_XGA_1152             0x01u
00093 #define S3_XGA_640              0x40u
00094 #define S3_XGA_800              0x80u
00095 #define S3_XGA_1280             0xc0u
00096 #define S3_XGA_1600             0x81u
00097 #define S3_XGA_WMASK    (S3_XGA_640|S3_XGA_800|S3_XGA_1024|S3_XGA_1152|S3_XGA_1280)
00098 
00099 #define S3_XGA_8BPP  0x00u
00100 #define S3_XGA_16BPP 0x10u
00101 #define S3_XGA_32BPP 0x30u
00102 #define S3_XGA_CMASK (S3_XGA_8BPP|S3_XGA_16BPP|S3_XGA_32BPP)
00103 
00104 typedef struct {
00105         bool attrindex;
00106 } VGA_Internal;
00107 
00108 typedef struct {
00109 /* Video drawing */
00110         Bitu display_start;
00111         Bitu real_start;
00112         bool retrace;                                   /* A retrace is active */
00113         Bitu scan_len;
00114         Bitu cursor_start;
00115 
00116 /* Some other screen related variables */
00117         Bitu line_compare;
00118         bool chained;                                   /* Enable or Disabled Chain 4 Mode */
00119         bool compatible_chain4;
00120 
00121         /* Pixel Scrolling */
00122         Bit8u pel_panning;                              /* Amount of pixels to skip when starting horizontal line */
00123         Bit8u hlines_skip;
00124         Bit8u bytes_skip;
00125         Bit8u addr_shift;
00126 
00127 /* Specific stuff memory write/read handling */
00128         
00129         Bit8u read_mode;
00130         Bit8u write_mode;
00131         Bit8u read_map_select;
00132         Bit8u color_dont_care;
00133         Bit8u color_compare;
00134         Bit8u data_rotate;
00135         Bit8u raster_op;
00136 
00137         Bit32u full_bit_mask;
00138         Bit32u full_map_mask;
00139         Bit32u full_not_map_mask;
00140         Bit32u full_set_reset;
00141         Bit32u full_not_enable_set_reset;
00142         Bit32u full_enable_set_reset;
00143         Bit32u full_enable_and_set_reset;
00144 } VGA_Config;
00145 
00146 typedef enum {
00147         DRAWLINE,
00148         EGALINE
00149 } Drawmode;
00150 
00151 typedef struct {
00152         bool resizing;
00153         Bitu width;
00154         Bitu height;
00155         Bitu blocks;
00156         Bitu address;
00157         Bitu panning;
00158         Bitu bytes_skip;
00159         Bit8u *linear_base;
00160         Bitu linear_mask;
00161     Bitu planar_mask;
00162         Bitu address_add;
00163         Bitu line_length;
00164         Bitu address_line_total;
00165         Bitu address_line;
00166         Bitu lines_total;
00167         Bitu vblank_skip;
00168         Bitu lines_done;
00169         Bitu split_line;
00170         Bitu byte_panning_shift;
00171     Bitu render_step,render_max;
00172         struct {
00173                 double framestart;
00174                 double vrstart, vrend;          // V-retrace
00175                 double hrstart, hrend;          // H-retrace
00176                 double hblkstart, hblkend;      // H-blanking
00177                 double vblkstart, vblkend;      // V-Blanking
00178                 double vdend, vtotal;
00179                 double hdend, htotal;
00180                 float singleline_delay;
00181         } delay;
00182         double screen_ratio;
00183         Bit8u font[516*1024]; /* enlarged to 516KB for PC-98 character font data (256*16) + (128*2*128*16) */
00184         Bit8u * font_tables[2];
00185         Bitu blinking;
00186         bool blink;
00187         bool char9dot;
00188         struct {
00189                 Bitu address;
00190                 Bit8u sline,eline;
00191                 Bit8u count,delay;
00192                 Bit8u enabled;
00193         } cursor;
00194         Drawmode mode;
00195         bool has_split;
00196         bool vret_triggered;
00197         bool vga_override;
00198         bool doublescan_set;
00199         bool doublescan_effect;
00200         bool char9_set;
00201         Bitu bpp;
00202         double clock;
00203         double oscclock;
00204         Bit8u cga_snow[80];                     // one bit per horizontal column where snow should occur
00205 
00206         /*Color and brightness for monochrome display*/
00207         Bit8u monochrome_pal;
00208         Bit8u monochrome_bright;
00209 } VGA_Draw;
00210 
00211 /* enable switch for the "alternative video system" */
00212 extern bool vga_alt_new_mode;
00213 
00214 /* NTS: Usage of this general struct will vary between the various video modes.
00215  *
00216  *      MDA/Hercules/CGA/PCjr/Tandy: Video hardware is based on the 6845 which
00217  *      counts horizontal AND vertical timing based on character cells. The
00218  *      fact that vertical timing is based on character cells is the reason
00219  *      why changing character cell height requires reprogramming the vertical
00220  *      timings. Most video modes are not entirely a multiple of the character
00221  *      cell height, which is why the 6845 has a "vertical adjust" to add to
00222  *      the total. For example, CGA produces a video signal with NTSC timing
00223  *      by programming enough character cells vertically with a vertical adjust
00224  *      to bring video output to the 262 scanlines required by one field of
00225  *      NTSC video, or 524 scanlines per frame. This isn't quite NTSC since
00226  *      CGA does not emit the half-a-scanline needed for interlaced (to produce
00227  *      262.5 lines per field or 525 scanlines per frame) but it happens to
00228  *      work with most TV sets (although incompatible with Happauge video
00229  *      capture cards).
00230  *
00231  *      Note that the CGA is not the only 80s hardware to emit non-interlaced
00232  *      NTSC, most video game consoles of the time period do as well. Your
00233  *      old Nintendo Entertainment System does it too.
00234  *
00235  *      Because of the character cell-based vertical timing, CGA emulation here
00236  *      will probably not rely so much on vert.total as it will on counting
00237  *      scan lines of the character cell.
00238  *
00239  *
00240  *      EGA/VGA/SVGA: Horizontal timing is based on character cells (which
00241  *      varies according to the mode and configuration). Vertical timing is
00242  *      based on scanlines, which is why it is easy to change character cell
00243  *      height without having to reprogram vertical timing.
00244  *
00245  *      Because of that, VGA emulation will count vertical timing entirely by
00246  *      vert.current and vert.total.
00247  *
00248  *
00249  *      MCGA: Not sure. This is weird hardware. Needs more study. It looks a
00250  *      lot like the marriage of CGA with a VGA DAC and a 256-color mode tied
00251  *      to 64KB of memory, and a CRTC that emulates a 6845 but generally ignores
00252  *      some horizontal and vertical values and hacks others and possibly
00253  *      carries video line doubling circuitry in order to produce 400-line video
00254  *      from 200-line video timings (except the 640x480 2-color mode).
00255  *
00256  *
00257  *      NEC PC-98: Two instances of this C++ class will be used in parallel,
00258  *      with the same dot clock, to emulate the text and graphics "layers" of
00259  *      PC-98 video. Both instances will generally have the same horizontal
00260  *      and vertical timing but they don't have to, in which case the VGA
00261  *      render code will generate the gibberish that would occur on real
00262  *      hardware when the two are not synchronized.
00263  */
00264 typedef struct {
00265     template <typename T> struct pix_char_t {
00266         T                       pixels;
00267         T                       chars;
00268 
00269         pix_char_t() { }
00270         pix_char_t(const T val) : pixels(val), chars(val) { }
00271     };
00272 
00273     template <typename T> struct start_end_t {
00274         T                       start;
00275         T                       end;
00276 
00277         start_end_t() { }
00278         start_end_t(const T val) : start(val), end(val) { }
00279         start_end_t(const unsigned int val) : start(val), end(val) { }
00280     };
00281 
00282     /* pixel 0 is start of display area.
00283      * next scanline starts when current == total before drawing next pixel.
00284      */
00285     struct general_dim {
00286         // CRTC counter address (H) / CRTC counter address at start of line (V)
00287         unsigned int                                crtc_addr = 0;
00288 
00289         // CRTC counter address to add per character clock (H) / per scan line (V)
00290         unsigned int                                crtc_addr_add = 0;
00291 
00292         // current position in pixels within scan line (H) / number of scan line (V)
00293         pix_char_t<unsigned int>                    current = 0;
00294 
00295         // total pixels in scan line (H) / total scan lines (V)
00296         pix_char_t<unsigned int>                    total = 0;
00297 
00298         // first pixel (H) / scan line (V) that active display STARTs, ENDs (start == 0 usually)
00299         start_end_t< pix_char_t<unsigned int> >     active = 0;
00300 
00301         // first pixel (H) / scan line (V) that blanking BEGINs, ENDs
00302         start_end_t< pix_char_t<unsigned int> >     blank = 0;
00303 
00304         // first pixel (H) / scan line (V) that retrace BEGINs, ENDs
00305         start_end_t< pix_char_t<unsigned int> >     retrace = 0;
00306 
00307         // largest horizontal active.end value during the entire frame (H) for demos like DoWhackaDo.
00308         // largest vertical active.end value during the entire frame (V).
00309         // reset to active.end at start of active display. (H/V)
00310         pix_char_t<unsigned int>                    active_max = 0;
00311 
00312         // start of scan line (H) / frame (V) PIC full index time
00313         pic_tickindex_t                             time_begin = 0;
00314 
00315         // length of scan line (H) / length of frame (V)
00316         pic_tickindex_t                             time_duration = 0;
00317 
00318         // current pixel position (H) / scan line (V) within character cell
00319         unsigned char                               current_char_pixel = 0;
00320 
00321         // width (H) / scan lines (V) of a character cell
00322         unsigned char                               char_pixels = 0;
00323 
00324         // bit mask for character row compare
00325         unsigned char                               char_pixel_mask = 0;
00326 
00327         bool                                        blank_enable = false;           // blank enable
00328         bool                                        display_enable = false;         // display enable (active area)
00329         bool                                        retrace_enable = false;         // retrace enable
00330     };
00331 
00332     // NTS: If start < end, cell starts with enable = false. at start of line,
00333     //      toggle enable (true) when line == start, then toggle enable (false) when
00334     //      line == end, then draw.
00335     //
00336     //      If start >= end, cell starts with enable = true, at start of line,
00337     //      toggle enable (false) when line == start, then toggle enable (true) when
00338     //      line == end, then draw.
00339 
00340     bool                        cursor_enable = false;  // if set, show cursor
00341 
00342     unsigned char               cursor_start = 0;       // cursor starts on this line (toggle cursor enable)
00343     unsigned char               cursor_end = 0;         // cursor stops on this line (first line to toggle again to disable)
00344 
00345     unsigned int                crtc_cursor_addr = 0;   // crtc address to display cursor at
00346 
00347     unsigned int                crtc_mask = 0;      // draw from memory ((addr & mask) + add)
00348     unsigned int                crtc_add = 0;       // NTS: For best results crtc_add should only change bits that are masked off
00349 
00350     inline unsigned int crtc_addr_fetch(void) const {
00351         return (horz.crtc_addr & crtc_mask) + crtc_add;
00352     }
00353 
00354     inline unsigned int crtc_addr_fetch_and_advance(void) {
00355         const unsigned int ret = crtc_addr_fetch();
00356         horz.crtc_addr += horz.crtc_addr_add;
00357         return ret;
00358     }
00359 
00360     unsigned int                raster_scanline = 0;    // actual scan line out to display
00361 
00362     unsigned char               doublescan_count = 0;   // VGA doublescan counter
00363     unsigned char               doublescan_max = 0;     // Advance scanline at this count
00364 
00365     // NTS: horz.char_pixels == 8 for CGA/MDA/etc and EGA/VGA text, but EGA/VGA can select 9 pixels/char.
00366     //      VGA 320x200x256-color mode will have 4 pixels/char. A hacked version of 320x200x256-color mode
00367     //      in which the 8BIT bit is cleared (which makes it a sort of 640x200x256-color-ish mode that
00368     //      reveals the intermediate register states normally hidden) will have 8 pixels/char.
00369     //
00370     //      MCGA 320x200x256-color will have horz.char_pixels == 8. A register dump from real hardware shows
00371     //      that Mode 13 has the same horizontal timings as every other mode (as if 320x200 CGA graphics!).
00372     //      This is very different from VGA where 320x200x256 is programmed as if a 640x200 graphics mode.
00373     //
00374     //      PC-98 will render as if horz.char_pixels == 8 on the text layer. It may set horz.char_pixels == 16
00375     //      on some text cells if the hardware is to render a double-wide character. The graphics layer is
00376     //      generally programmed into WORDs mode which means horz.char_pixels == 16 at all times. If it is
00377     //      ever programmed into byte mode then it will set horz.char_pixels == 8.
00378 
00379     struct dotclock_t {
00380         double                  rate_invmult = 0;
00381         double                  rate_mult = 0;
00382         double                  rate = 0;
00383         pic_tickindex_t         base = 0;
00384         signed long long        ticks = 0;
00385         signed long long        ticks_prev = 0;
00386 
00387         void reset(const pic_tickindex_t now) {
00388             ticks = ticks_prev = 0;
00389             base = now;
00390         }
00391 
00392         // do not call unless all ticks processed
00393         void set_rate(const double new_rate,const pic_tickindex_t now) {
00394             if (rate != new_rate) {
00395                 update(now);
00396                 rebase();
00397 
00398                 if ((rate <= 0) || (fabs(now - base) > (0.5 * rate_invmult)))
00399                     base = now;
00400 
00401                 if (new_rate > 0) {
00402                     rate_invmult = 1000 / new_rate; /* Hz -> ms */
00403                     rate_mult = new_rate / 1000; /* ms -> Hz */
00404                     rate = new_rate;
00405                 }
00406                 else {
00407                     rate_invmult = 0;
00408                     rate_mult = 0;
00409                     rate = 0;
00410                 }
00411 
00412                 update(now);
00413                 ticks_prev = ticks;
00414             }
00415         }
00416 
00417         inline pic_tickindex_t ticks2pic_relative(const signed long long t,const pic_tickindex_t now) const {
00418             return (t * rate_invmult) + (base - now);/* group float operations to maintain precision */
00419         }
00420 
00421         inline pic_tickindex_t ticks2pic(const signed long long t) const {
00422             return (t * rate_invmult) + base;
00423         }
00424 
00425         inline signed long long pic2ticks(const pic_tickindex_t now) const {
00426             /* typecasting rounds down to 0 apparently. floor() is slower. */
00427             return (signed long long)((now - base) * rate_mult);
00428         }
00429 
00430         // inline and minimal for performance!
00431         inline void update(const pic_tickindex_t now) {
00432             /* NTS: now = PIC_FullIndex() which is time in ms (1/1000 of a sec) */
00433             ticks = pic2ticks(now);
00434         }
00435 
00436         // retrival of tick count and reset of counter
00437         inline signed long long delta_peek(void) const {
00438             return ticks - ticks_prev;
00439         }
00440 
00441         inline signed long long delta_get(void) {
00442             signed long long ret = delta_peek();
00443             ticks_prev = ticks;
00444             return ret;
00445         }
00446 
00447         // rebase of the counter.
00448         // call this every so often (but not too often) in order to prevent floating point
00449         // precision loss over time as the numbers get larger and larger.
00450         void rebase(void) {
00451             if (rate_mult > 0) {
00452                 base += ticks * rate_invmult;
00453                 ticks = ticks_prev = 0;
00454             }
00455         }
00456     };
00457 
00458     /* integer fraction.
00459      * If you need more precision (4.1:3 instead of 4:3) just scale up the values (4.1:3 -> 41:30) */
00460     struct int_fraction_t {
00461         unsigned int            numerator = 0;
00462         unsigned int            denominator = 0;
00463 
00464         int_fraction_t() { }
00465         int_fraction_t(const unsigned int n,const unsigned int d) : numerator(n), denominator(d) { }
00466     };
00467 
00468     /* 2D display dimensions */
00469     struct dimensions_t {
00470         unsigned int            width = 0;
00471         unsigned int            height = 0;
00472 
00473         dimensions_t() { }
00474         dimensions_t(const unsigned int w,const unsigned int h) : width(w), height(h) { }
00475     };
00476 
00477     /* 2D coordinate */
00478     struct int_point2d_t {
00479         int                     x = 0;
00480         int                     y = 0;
00481 
00482         int_point2d_t() { }
00483         int_point2d_t(const int nx,const int ny) : x(nx), y(ny) { }
00484     };
00485 
00486     // use the dot clock to map advancement of emulator time to dot clock ticks.
00487     // apply the dot clock ticks against the horizontal and vertical current position
00488     // to emulate the raster of the video output over time.
00489     //
00490     // if anything changes dot clock rate, process all ticks and advance hardware
00491     // state, then set the rate and process all dot clock ticks after that point
00492     // at the new rate.
00493 
00494     dotclock_t                  dotclock;
00495     general_dim                 horz,vert;
00496 
00497     // monitor emulation
00498     dimensions_t                monitor_display;                // image sent to GFX (may include overscan, blanking, etc)
00499     int_point2d_t               monitor_start_point;            // pixel(x)/scanline(y) counter of the CRTC that is start of line(x)/frame(y)
00500     int_fraction_t              monitor_aspect_ratio = {4,3};   // display aspect ratio of the video frame
00501 
00502     // The GFX/scaler system will be sent a frame of dimensions monitor_display.
00503     // The start of the frame will happen when the CRTC pixel count matches the monitor_start_point.
00504     // monitor_start_point will be set to 0,0 if DOSBox-X is set only to show active area.
00505     // it will be set to match on the first clock/scanline of the non-blanking area (overscan), upper left corner if set to do so.
00506     // it will be set to some point of the blanking area if asked to do so to approximate how a VGA monitor centers the image.
00507     // finally, a debug mode will be offered to show the ENTIRE frame (htotal/vtotal) with markings for retrace if wanted by the user.
00508 
00509     // Pointers to draw from. This represents CRTC character clock 0.
00510     Bit8u*                      draw_base = NULL;
00511 
00512     template <typename T> inline const T* drawptr(const size_t offset) const {
00513         return (const T*)draw_base + offset; /* equiv T* ptr = (T*)draw_base; return &ptr[offset]; */
00514     }
00515 
00516     template <typename T> inline T* drawptr_rw(const size_t offset) const {
00517         return (T*)draw_base + offset; /* equiv T* ptr = (T*)draw_base; return &ptr[offset]; */
00518     }
00519 } VGA_Draw_2;
00520 
00521 typedef struct {
00522         Bit8u curmode;
00523         Bit16u originx, originy;
00524         Bit8u fstackpos, bstackpos;
00525         Bit8u forestack[4];
00526         Bit8u backstack[4];
00527         Bit16u startaddr;
00528         Bit8u posx, posy;
00529         Bit8u mc[64][64];
00530 } VGA_HWCURSOR;
00531 
00532 typedef struct {
00533         Bit8u reg_lock1;
00534         Bit8u reg_lock2;
00535         Bit8u reg_31;
00536         Bit8u reg_35;
00537         Bit8u reg_36; // RAM size
00538         Bit8u reg_3a; // 4/8/doublepixel bit in there
00539         Bit8u reg_40; // 8415/A functionality register
00540         Bit8u reg_41; // BIOS flags 
00541         Bit8u reg_42; // CR42 Mode Control
00542         Bit8u reg_43;
00543         Bit8u reg_45; // Hardware graphics cursor
00544         Bit8u reg_50;
00545         Bit8u reg_51;
00546         Bit8u reg_52;
00547         Bit8u reg_55;
00548         Bit8u reg_58;
00549         Bit8u reg_6b; // LFB BIOS scratchpad
00550         Bit8u ex_hor_overflow;
00551         Bit8u ex_ver_overflow;
00552         Bit16u la_window;
00553         Bit8u misc_control_2;
00554         Bit8u ext_mem_ctrl;
00555         Bitu xga_screen_width;
00556         VGAModes xga_color_mode;
00557         struct {
00558                 Bit8u r;
00559                 Bit8u n;
00560                 Bit8u m;
00561         } clk[4],mclk;
00562         struct {
00563                 Bit8u lock;
00564                 Bit8u cmd;
00565         } pll;
00566         VGA_HWCURSOR hgc;
00567 } VGA_S3;
00568 
00569 typedef struct {
00570         Bit8u mode_control;
00571         Bit8u enable_bits;
00572         bool blend;
00573 } VGA_HERC;
00574 
00575 typedef struct {
00576         Bit32u mask_plane;
00577         Bit8u write_plane;
00578         Bit8u read_plane;
00579         Bit8u border_color;
00580 } VGA_AMSTRAD;
00581 
00582 typedef struct {
00583         Bit8u index;
00584         Bit8u htotal;
00585         Bit8u hdend;
00586         Bit8u hsyncp;
00587         Bit8u hsyncw;
00588         Bit8u vtotal;
00589         Bit8u vdend;
00590         Bit8u vadjust;
00591         Bit8u vsyncp;
00592         Bit8u vsyncw;
00593         Bit8u max_scanline;
00594         Bit16u lightpen;
00595         bool lightpen_triggered;
00596         Bit8u cursor_start;
00597         Bit8u cursor_end;
00598     Bit8u mcga_mode_control;
00599 } VGA_OTHER;
00600 
00601 typedef struct {
00602         Bit8u pcjr_flipflop;
00603         Bit8u mode_control;
00604         Bit8u color_select;
00605         Bit8u disp_bank;
00606         Bit8u reg_index;
00607         Bit8u gfx_control;
00608         Bit8u palette_mask;
00609         Bit8u extended_ram;
00610         Bit8u border_color;
00611         Bit8u line_mask, line_shift;
00612         Bit8u draw_bank, mem_bank;
00613         Bit8u *draw_base, *mem_base;
00614         Bitu addr_mask;
00615 } VGA_TANDY;
00616 
00617 typedef struct {
00618         Bit8u index;
00619         Bit8u reset;
00620         Bit8u clocking_mode;
00621         Bit8u map_mask;
00622         Bit8u character_map_select;
00623         Bit8u memory_mode;
00624 } VGA_Seq;
00625 
00626 typedef struct {
00627         Bit8u palette[16];
00628         Bit8u mode_control;
00629         Bit8u horizontal_pel_panning;
00630         Bit8u overscan_color;
00631         Bit8u color_plane_enable;
00632         Bit8u color_select;
00633         Bit8u index;
00634         Bit8u disabled; // Used for disabling the screen.
00635                                         // Bit0: screen disabled by attribute controller index
00636                                         // Bit1: screen disabled by sequencer index 1 bit 5
00637                                         // These are put together in one variable for performance reasons:
00638                                         // the line drawing function is called maybe 60*480=28800 times/s,
00639                                         // and we only need to check one variable for zero this way.
00640 } VGA_Attr;
00641 
00642 typedef struct {
00643         Bit8u horizontal_total;
00644         Bit8u horizontal_display_end;
00645         Bit8u start_horizontal_blanking;
00646         Bit8u end_horizontal_blanking;
00647         Bit8u start_horizontal_retrace;
00648         Bit8u end_horizontal_retrace;
00649         Bit8u vertical_total;
00650         Bit8u overflow;
00651         Bit8u preset_row_scan;
00652         Bit8u maximum_scan_line;
00653         Bit8u cursor_start;
00654         Bit8u cursor_end;
00655         Bit8u start_address_high;
00656         Bit8u start_address_low;
00657         Bit8u cursor_location_high;
00658         Bit8u cursor_location_low;
00659         Bit8u vertical_retrace_start;
00660         Bit8u vertical_retrace_end;
00661         Bit8u vertical_display_end;
00662         Bit8u offset;
00663         Bit8u underline_location;
00664         Bit8u start_vertical_blanking;
00665         Bit8u end_vertical_blanking;
00666         Bit8u mode_control;
00667         Bit8u line_compare;
00668 
00669         Bit8u index;
00670         bool read_only;
00671 } VGA_Crtc;
00672 
00673 typedef struct {
00674         Bit8u index;
00675         Bit8u set_reset;
00676         Bit8u enable_set_reset;
00677         Bit8u color_compare;
00678         Bit8u data_rotate;
00679         Bit8u read_map_select;
00680         Bit8u mode;
00681         Bit8u miscellaneous;
00682         Bit8u color_dont_care;
00683         Bit8u bit_mask;
00684 } VGA_Gfx;
00685 
00686 typedef struct  {
00687         Bit8u red;
00688         Bit8u green;
00689         Bit8u blue;
00690 } RGBEntry;
00691 
00692 typedef struct {
00693         Bit8u bits;                                             /* DAC bits, usually 6 or 8 */
00694         Bit8u pel_mask;
00695         Bit8u pel_index;        
00696         Bit8u state;
00697         Bit8u write_index;
00698         Bit8u read_index;
00699         Bitu first_changed;
00700         Bit8u combine[16];
00701         RGBEntry rgb[0x100];
00702         Bit16u xlat16[256];
00703         Bit32u xlat32[256];
00704         Bit8u hidac_counter;
00705         Bit8u reg02;
00706 } VGA_Dac;
00707 
00708 typedef struct {
00709         Bitu    readStart, writeStart;
00710         Bitu    bankMask;
00711         Bitu    bank_read_full;
00712         Bitu    bank_write_full;
00713         Bit8u   bank_read;
00714         Bit8u   bank_write;
00715         Bitu    bank_size;
00716 } VGA_SVGA;
00717 
00718 typedef union CGA_Latch {
00719         Bit16u d;
00720     Bit8u b[2] = {};
00721 
00722     CGA_Latch() { }
00723     CGA_Latch(const Bit16u raw) : d(raw) { }
00724 } CGA_Latch;
00725 
00726 typedef union VGA_Latch {
00727         Bit32u d;
00728     Bit8u b[4] = {};
00729 
00730     VGA_Latch() { }
00731     VGA_Latch(const Bit32u raw) : d(raw) { }
00732 } VGA_Latch;
00733 
00734 typedef struct {
00735         Bit8u*      linear = NULL;
00736         Bit8u*      linear_orgptr = NULL;
00737 
00738     uint32_t    memsize = 0;
00739     uint32_t    memmask = 0;
00740     uint32_t    memmask_crtc = 0;       // in CRTC-visible units (depends on byte/word/dword mode)
00741 } VGA_Memory;
00742 
00743 typedef struct {
00744         Bit32u page;
00745         Bit32u addr;
00746         Bit32u mask;
00747         PageHandler *handler;
00748 } VGA_LFB;
00749 
00750 static const size_t VGA_Draw_2_elem = 2;
00751 
00752 typedef struct {
00753         VGAModes mode;                                                          /* The mode the vga system is in */
00754         VGAModes lastmode;
00755         Bit8u misc_output;
00756     VGA_Draw_2 draw_2[VGA_Draw_2_elem];         /* new parallel video emulation. PC-98 mode will use both, all others only the first. */
00757         VGA_Draw draw;
00758         VGA_Config config;
00759         VGA_Internal internal;
00760 /* Internal module groups */
00761         VGA_Seq seq;
00762         VGA_Attr attr;
00763         VGA_Crtc crtc;
00764         VGA_Gfx gfx;
00765         VGA_Dac dac;
00766         VGA_Latch latch;
00767         VGA_S3 s3;
00768         VGA_SVGA svga;
00769         VGA_HERC herc;
00770         VGA_TANDY tandy;
00771         VGA_AMSTRAD amstrad;
00772         VGA_OTHER other;
00773         VGA_Memory mem;
00774         VGA_LFB lfb;
00775 } VGA_Type;
00776 
00777 
00778 /* Hercules Palette function */
00779 void Herc_Palette(void);
00780 
00781 /* CGA Mono Palette function */
00782 void Mono_CGA_Palette(void);
00783 
00784 /* Functions for different resolutions */
00785 void VGA_SetMode(VGAModes mode);
00786 void VGA_DetermineMode(void);
00787 void VGA_SetupHandlers(void);
00788 void VGA_StartResize(Bitu delay=50);
00789 void VGA_SetupDrawing(Bitu val);
00790 void VGA_CheckScanLength(void);
00791 void VGA_ChangedBank(void);
00792 
00793 /* Some DAC/Attribute functions */
00794 void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
00795 void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
00796 void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
00797 
00798 typedef enum {CGA, EGA, MONO} EGAMonitorMode;
00799 
00800 typedef enum {AC_4x4, AC_low4/*4low*/} ACPalRemapMode;
00801 
00802 extern unsigned char VGA_AC_remap;
00803 
00804 void VGA_ATTR_SetEGAMonitorPalette(EGAMonitorMode m);
00805 
00806 /* The VGA Subfunction startups */
00807 void VGA_SetupAttr(void);
00808 void VGA_SetupMemory(void);
00809 void VGA_SetupDAC(void);
00810 void VGA_SetupMisc(void);
00811 void VGA_SetupGFX(void);
00812 void VGA_SetupSEQ(void);
00813 void VGA_SetupOther(void);
00814 void VGA_SetupXGA(void);
00815 
00816 /* Some Support Functions */
00817 void VGA_SetClock(Bitu which,Bitu target);
00818 void VGA_StartUpdateLFB(void);
00819 void VGA_SetBlinking(Bitu enabled);
00820 void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
00821 void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
00822 void VGA_ActivateHardwareCursor(void);
00823 void VGA_KillDrawing(void);
00824 
00825 void VGA_SetOverride(bool vga_override);
00826 
00827 extern VGA_Type vga;
00828 
00829 /* Support for modular SVGA implementation */
00830 /* Video mode extra data to be passed to FinishSetMode_SVGA().
00831    This structure will be in flux until all drivers (including S3)
00832    are properly separated. Right now it contains only three overflow
00833    fields in S3 format and relies on drivers re-interpreting those.
00834    For reference:
00835    ver_overflow:X|line_comp10|X|vretrace10|X|vbstart10|vdispend10|vtotal10
00836    hor_overflow:X|X|X|hretrace8|X|hblank8|hdispend8|htotal8
00837    offset is not currently used by drivers (useful only for S3 itself)
00838    It also contains basic int10 mode data - number, vtotal, htotal
00839    */
00840 typedef struct {
00841         Bit8u ver_overflow;
00842         Bit8u hor_overflow;
00843         Bitu offset;
00844         Bitu modeNo;
00845         Bitu htotal;
00846         Bitu vtotal;
00847 } VGA_ModeExtraData;
00848 
00849 // Vector function prototypes
00850 typedef void (*tWritePort)(Bitu reg,Bitu val,Bitu iolen);
00851 typedef Bitu (*tReadPort)(Bitu reg,Bitu iolen);
00852 typedef void (*tFinishSetMode)(Bitu crtc_base, VGA_ModeExtraData* modeData);
00853 typedef void (*tDetermineMode)();
00854 typedef void (*tSetClock)(Bitu which,Bitu target);
00855 typedef Bitu (*tGetClock)();
00856 typedef bool (*tHWCursorActive)();
00857 typedef bool (*tAcceptsMode)(Bitu modeNo);
00858 typedef void (*tSetupDAC)();
00859 typedef void (*tINT10Extensions)();
00860 
00861 struct SVGA_Driver {
00862         tWritePort write_p3d5;
00863         tReadPort read_p3d5;
00864         tWritePort write_p3c5;
00865         tReadPort read_p3c5;
00866         tWritePort write_p3c0;
00867         tReadPort read_p3c1;
00868         tWritePort write_p3cf;
00869         tReadPort read_p3cf;
00870 
00871         tFinishSetMode set_video_mode;
00872         tDetermineMode determine_mode;
00873         tSetClock set_clock;
00874         tGetClock get_clock;
00875         tHWCursorActive hardware_cursor_active;
00876         tAcceptsMode accepts_mode;
00877         tSetupDAC setup_dac;
00878         tINT10Extensions int10_extensions;
00879 };
00880 
00881 extern SVGA_Driver svga;
00882 extern int enableCGASnow;
00883 
00884 void SVGA_Setup_S3Trio(void);
00885 void SVGA_Setup_TsengET4K(void);
00886 void SVGA_Setup_TsengET3K(void);
00887 void SVGA_Setup_ParadisePVGA1A(void);
00888 void SVGA_Setup_Driver(void);
00889 
00890 // Amount of video memory required for a mode, implemented in int10_modes.cpp
00891 Bitu VideoModeMemSize(Bitu mode);
00892 
00893 extern Bit32u ExpandTable[256];
00894 extern Bit32u FillTable[16];
00895 extern Bit32u CGA_2_Table[16];
00896 extern Bit32u CGA_4_Table[256];
00897 extern Bit32u CGA_4_HiRes_Table[256];
00898 extern Bit32u CGA_16_Table[256];
00899 extern Bit32u TXT_Font_Table[16];
00900 extern Bit32u TXT_FG_Table[16];
00901 extern Bit32u TXT_BG_Table[16];
00902 extern Bit32u Expand16Table[4][16];
00903 extern Bit32u Expand16BigTable[0x10000];
00904 
00905 void VGA_DAC_UpdateColorPalette();
00906 
00907 extern uint32_t GFX_Rmask;
00908 extern unsigned char GFX_Rshift;
00909 
00910 extern uint32_t GFX_Gmask;
00911 extern unsigned char GFX_Gshift;
00912 
00913 extern uint32_t GFX_Bmask;
00914 extern unsigned char GFX_Bshift;
00915 
00916 extern uint32_t GFX_Amask;
00917 extern unsigned char GFX_Ashift;
00918 
00919 extern unsigned char GFX_bpp;
00920 
00921 /* current dosplay page (controlled by A4h) */
00922 extern unsigned char *pc98_pgraph_current_display_page;
00923 /* current CPU page (controlled by A6h) */
00924 extern unsigned char *pc98_pgraph_current_cpu_page;
00925 
00926 /* functions to help cleanup memory map access instead of hardcoding offsets.
00927  * your C++ compiler should be smart enough to inline these into the body of this function. */
00928 
00929 /* TODO: Changes to memory layout relative to vga.mem.linear:
00930  *
00931  *       Text to take 0x00000-0x03FFF instead of 0x00000-0x07FFF.
00932  *
00933  *       Graphics to start at 0x04000
00934  *
00935  *       Each bitplane will be 64KB (0x10000) bytes long, and the page flip bit in 0xA6
00936  *       will select which 32KB half within the 64KB block to use, or if another bit is
00937  *       set as documented in Undocumented PC-98, the full 64KB block.
00938  *
00939  *       The 512KB + 32KB will be reduced slightly to 512KB + 16KB to match the layout.
00940  *
00941  *       The bitplane layout change will permit emulating an 8 bitplane 256-color mode
00942  *       suggested by Yksoft1 that early PC-9821 systems supported and that the 256-color
00943  *       driver shipped with Windows 3.1 (for PC-98) uses. Based on Windows 3.1 behavior
00944  *       that also means the linear framebuffer at 0xF00000 must also change in planar
00945  *       mode to spread all 8 bits across the planes on write and gather all 8 bits
00946  *       on read. As far as I can tell the Windows 3.1 256-color driver uses planar
00947  *       and EGC functions as it would in 16-color mode, but draws bitmaps using the
00948  *       LFB. The picture is wrong EXCEPT when Windows icons and bitmaps are drawn.
00949  *
00950  *       256-color packed mode will be retained as direct LFB mapping from the start of
00951  *       graphics RAM.
00952  *
00953  *       On a real PC-9821 laptop, contents accessible to the CPU noticeably shift order
00954  *       and position when you switch on/off 256-color packed mode, suggesting that the
00955  *       planar mode is simply reordered memory access in hardware OR that 256-color
00956  *       mode is "chained" (much like 256-color packed mode on IBM VGA hardware) across
00957  *       bitplanes. */
00958 
00959 #define PC98_VRAM_TEXT_OFFSET           ( 0x00000u )        /* 16KB memory (8KB text + 8KB attributes) */
00960 #define PC98_VRAM_GRAPHICS_OFFSET       ( 0x04000u )        /* where graphics memory begins */
00961 
00962 #define PC98_VRAM_BITPLANE_SIZE         ( 0x10000u )        /* one bitplane */
00963 
00964 #define PC98_VRAM_PAGEFLIP_SIZE         ( 0x08000u )        /* add this amount for the second page in 8/16/256-color planar mode */
00965 #define PC98_VRAM_PAGEFLIP256_SIZE      ( 0x40000u )        /* add this amount for the second page in 256-color packed mode */
00966 
00967 #define PC98_VRAM_256BANK_SIZE          ( 0x08000u )        /* window/bank size (256-color packed) */
00968 
00969 extern uint32_t pc98_pegc_banks[2];
00970 
00971 static inline unsigned char *pc98_vram_text(void) {
00972     return vga.mem.linear + PC98_VRAM_TEXT_OFFSET;
00973 }
00974 
00975 /* return value is relative to current CPU page or current display page ptr */
00976 static inline constexpr unsigned int pc98_pgram_bitplane_offset(const unsigned int b) {
00977     /* WARNING: b is not range checked for performance! Do not call with b >= 8 if memsize = 512KB or b >= 4 if memsize >= 256KB */
00978     return (b * PC98_VRAM_BITPLANE_SIZE);
00979 }
00980 
00981 static inline unsigned char *pc98_vram_256bank_from_window(const unsigned int b) {
00982     /* WARNING: b is not range checked for performance! Do not call with b >= 2 */
00983     return vga.mem.linear + PC98_VRAM_GRAPHICS_OFFSET + pc98_pegc_banks[b];
00984 }
00985 
00986 #define VRAM98_TEXT         ( pc98_vram_text() )
00987 
00988 #endif