DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 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 along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 VGA_Experimental_Model_1_t { 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 VGA_Memory_t { 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 VGA_Type_t { 00753 VGAModes mode = {}; /* The mode the vga system is in */ 00754 VGAModes lastmode = {}; 00755 Bit8u misc_output = 0; 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