DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/vga.cpp
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 /* NTS: Hardware notes
00020  *
00021  * S3 Virge DX (PCI):
00022  *
00023  *   VGA 256-color chained mode appears to work differently than
00024  *   expected. Groups of 4 pixels are spread across the VGA planes
00025  *   as expected, but actual memory storage of those 32-bit quantities
00026  *   are 4 "bytes" apart (probably the inspiration for DOSBox's
00027  *   chain emulation using addr = ((addr & ~3) << 2) + (addr & 3) when
00028  *   emulating chained mode).
00029  *
00030  *   The attribute controller has a bug where if you attempt to read
00031  *   the palette indexes 0x00-0x0F with PAS=1 (see FreeVGA for more
00032  *   info) the returned value will be correct except for bit 5 which
00033  *   will be 1 i.e. if palette index 0x2 is read in this way and
00034  *   contains 0x02 you will get 0x22 instead. The trick is to write
00035  *   the index with PAS=0 and read the data, then issue the index with
00036  *   PAS=1. Related: the S3 acts as if there are different flip-flops
00037  *   associated with reading vs writing i.e. writing to 0x3C0, then
00038  *   reading port 0x3C1, then writing port 0x3C0, will treat the second
00039  *   write to 0x3C0 as data still, not as an index. Both flip flops are
00040  *   reset by reading 3xAh though.
00041  *
00042  *   VGA BIOS does not support INT 10h TTY functions in VESA BIOS modes.
00043  *
00044  *   Raw planar dumps of the VGA memory in alphanumeric modes suggest
00045  *   that, not only do the cards direct even writes to 0/2 and odd to 1/3,
00046  *   it does so without shifting down the address. So in a raw planar
00047  *   dump, you will see on plane 0 something like "C : \ > " where the
00048  *   spaces are hex 0x00, and in plane 1, something like 0x07 0x00 0x07 0x00 ...
00049  *   the card however (in even/odd mode) does mask out bit A0 which
00050  *   explains why the Plane 1 capture is 0x07 0x00 ... not 0x00 0x07.
00051  *
00052  * ATI Rage 128 (AGP):
00053  *
00054  *   VGA 256-color chained mode appears to work in the same weird way
00055  *   that S3 Virge DX does (see above).
00056  *
00057  *   VGA BIOS supports TTY INT 10h functions in 16 & 256-color modes
00058  *   only. There are apparently INT 10h functions for 15/16bpp modes
00059  *   as well, but they don't appear to render anything except shades
00060  *   of green.
00061  *
00062  *   The VESA BIOS interface seems to have INT 10h aliases for many
00063  *   VBE 1.2 modes i.e. mode 0x110 is also mode 0x42.
00064  *
00065  *   The Attribute Controller palette indexes work as expected in all
00066  *   VGA modes, however in SVGA VESA BIOS modes, the Attribute Controller
00067  *   palette has no effect on output EXCEPT in 16-color (4bpp) VESA BIOS
00068  *   modes.
00069  *
00070  *   Raw planar layout of alphanumeric text modes apply the same rules
00071  *   as mentioned above in the S3 Virge DX description.
00072  *
00073  * Compaq Elite LTE 4/50CX laptop:
00074  *
00075  *   No SVGA modes. All modes work as expected.
00076  *
00077  *   VGA 256-color chained mode acts the same weird way as described
00078  *   above, seems to act like addr = ((addr & ~3) << 2) + (addr & 3)
00079  *
00080  *   There seems to be undocumented INT 10h modes:
00081  *
00082  *        0x22:  640x480x?? INT 10h text is all green and garbled
00083  *        0x28:  320x200x?? INT 10h text is all green and garbled
00084  *        0x32:  640x480x?? INT 10h text is all yellow and garbled
00085  *        0x5E:  640x400x256-color with bank switching
00086  *        0x5F:  640x480x256-color with bank switching
00087  *        0x62:  640x480x?? INT 10h text is all dark gray
00088  *        0x68:  320x200x?? INT 10h text is all dark gray
00089  *        0x72:  640x480x?? INT 10h text is all dark gray
00090  *        0x78:  320x200x?? INT 10h text is all dark gray
00091  *
00092  *   And yet, the BIOS does not implement VESA BIOS extensions. Hm..
00093  *
00094  * Sharp PC-9030 with Cirrus SVGA (1996):
00095  *
00096  *   VGA 256-color chained mode acts the same weird way, as if:
00097  *   addr = ((addr & ~3) << 2) + (addr & 3)
00098  * 
00099  *   All VESA BIOS modes support INT 10h TTY output.
00100  *
00101  * Tseng ET4000AX:
00102  *
00103  *   The ET4000 cards appear to be the ONLY SVGA chipset out there
00104  *   that does NOT do the odd VGA 256-color chained mode that
00105  *   other cards do.
00106  *
00107  *   Chained 256-color on ET4000:
00108  *       addr = addr                             (addr >> 2) byte in planar space, plane select by (addr & 3)
00109  *
00110  *   Other VGA cards:
00111  *       addr = ((addr & ~3) << 2) + (addr & 3)  (addr & ~3) byte in planar space, plane select by (addr & 3)
00112  *
00113  *   I suspect that this difference may be the reason several 1992-1993-ish DOS demos have problems clearing
00114  *   VRAM. It's possible they noticed that zeroing RAM was faster in planar mode, and coded their routines
00115  *   around ET4000 cards, not knowing that Trident, Cirrus, and every VGA clone thereafter implemented the
00116  *   chained 256-color modes differently.
00117  */
00118 
00119 #include "dosbox.h"
00120 #include "setup.h"
00121 #include "video.h"
00122 #include "pic.h"
00123 #include "vga.h"
00124 #include "inout.h"
00125 #include "programs.h"
00126 #include "support.h"
00127 #include "setup.h"
00128 #include "timer.h"
00129 #include "mem.h"
00130 #include "util_units.h"
00131 #include "control.h"
00132 #include "pc98_cg.h"
00133 #include "pc98_dac.h"
00134 #include "pc98_gdc.h"
00135 #include "pc98_gdc_const.h"
00136 #include "mixer.h"
00137 #include "menu.h"
00138 #include "mem.h"
00139 #include "render.h"
00140 
00141 #include <string.h>
00142 #include <stdlib.h>
00143 #include <string>
00144 #include <stdio.h>
00145 
00146 #if defined(_MSC_VER)
00147 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
00148 #endif
00149 
00150 #include "zipfile.h"
00151 
00152 using namespace std;
00153 
00154 Bitu pc98_read_9a8(Bitu /*port*/,Bitu /*iolen*/);
00155 void pc98_write_9a8(Bitu port,Bitu val,Bitu iolen);
00156 
00157 bool VGA_IsCaptureEnabled(void);
00158 void VGA_UpdateCapturePending(void);
00159 bool VGA_CaptureHasNextFrame(void);
00160 void VGA_CaptureStartNextFrame(void);
00161 void VGA_CaptureMarkError(void);
00162 bool VGA_CaptureValidateCurrentFrame(void);
00163 
00164 /* current dosplay page (controlled by A4h) */
00165 unsigned char*                      pc98_pgraph_current_display_page;
00166 /* current CPU page (controlled by A6h) */
00167 unsigned char*                      pc98_pgraph_current_cpu_page;
00168 
00169 bool                                vga_8bit_dac = false;
00170 bool                                vga_alt_new_mode = false;
00171 bool                                enable_vga_8bit_dac = true;
00172 
00173 bool                                pc98_crt_mode = false;      // see port 6Ah command 40h/41h.
00174                                                                 // this boolean is the INVERSE of the bit.
00175 
00176 extern int                          vga_memio_delay_ns;
00177 extern bool                         gdc_5mhz_mode;
00178 extern bool                         gdc_5mhz_mode_initial;
00179 extern bool                         enable_pc98_egc;
00180 extern bool                         enable_pc98_grcg;
00181 extern bool                         enable_pc98_16color;
00182 extern bool                         enable_pc98_256color;
00183 extern bool                         enable_pc98_256color_planar;
00184 extern bool                         enable_pc98_188usermod;
00185 extern bool                         GDC_vsync_interrupt;
00186 extern uint8_t                      GDC_display_plane;
00187 extern bool                         pc98_256kb_boundary;
00188 extern bool                         want_fm_towns;
00189 
00190 extern uint8_t                      pc98_gdc_tile_counter;
00191 extern uint8_t                      pc98_gdc_modereg;
00192 extern uint8_t                      pc98_gdc_vramop;
00193 extern egc_quad                     pc98_gdc_tiles;
00194 
00195 extern uint8_t                      pc98_egc_srcmask[2]; /* host given (Neko: egc.srcmask) */
00196 extern uint8_t                      pc98_egc_maskef[2]; /* effective (Neko: egc.mask2) */
00197 extern uint8_t                      pc98_egc_mask[2]; /* host given (Neko: egc.mask) */
00198 
00199 uint32_t S3_LFB_BASE =              S3_LFB_BASE_DEFAULT;
00200 
00201 bool                                enable_pci_vga = true;
00202 
00203 SDL_Rect                            vga_capture_rect = {0,0,0,0};
00204 SDL_Rect                            vga_capture_current_rect = {0,0,0,0};
00205 uint32_t                            vga_capture_current_address = 0;
00206 uint32_t                            vga_capture_write_address = 0; // literally the address written
00207 uint32_t                            vga_capture_address = 0;
00208 uint32_t                            vga_capture_stride = 0;
00209 uint32_t                            vga_capture_state = 0;
00210 
00211 SDL_Rect &VGA_CaptureRectCurrent(void) {
00212     return vga_capture_current_rect;
00213 }
00214 
00215 SDL_Rect &VGA_CaptureRectFromGuest(void) {
00216     return vga_capture_rect;
00217 }
00218 
00219 VGA_Type vga;
00220 SVGA_Driver svga;
00221 int enableCGASnow;
00222 int vesa_modelist_cap = 0;
00223 int vesa_mode_width_cap = 0;
00224 int vesa_mode_height_cap = 0;
00225 bool vesa_bios_modelist_in_info = false;
00226 bool vga_3da_polled = false;
00227 bool vga_page_flip_occurred = false;
00228 bool enable_page_flip_debugging_marker = false;
00229 bool enable_vretrace_poll_debugging_marker = false;
00230 bool vga_enable_hretrace_effects = false;
00231 bool vga_enable_hpel_effects = false;
00232 bool vga_enable_3C6_ramdac = false;
00233 bool vga_sierra_lock_565 = false;
00234 bool enable_vga_resize_delay = false;
00235 bool vga_ignore_hdispend_change_if_smaller = false;
00236 bool ignore_vblank_wraparound = false;
00237 bool non_cga_ignore_oddeven = false;
00238 bool non_cga_ignore_oddeven_engage = false;
00239 bool vga_palette_update_on_full_load = true;
00240 bool vga_double_buffered_line_compare = false;
00241 bool pc98_allow_scanline_effect = true;
00242 bool pc98_allow_4_display_partitions = false;
00243 bool pc98_graphics_hide_odd_raster_200line = false;
00244 bool pc98_attr4_graphic = false;
00245 bool pc98_40col_text = false;
00246 bool gdc_analog = true;
00247 bool pc98_31khz_mode = false;
00248 bool int10_vesa_map_as_128kb = false;
00249 
00250 unsigned char VGA_AC_remap = AC_4x4;
00251 
00252 unsigned int vga_display_start_hretrace = 0;
00253 float hretrace_fx_avg_weight = 3;
00254 
00255 bool allow_vesa_4bpp_packed = true;
00256 bool allow_vesa_lowres_modes = true;
00257 bool allow_unusual_vesa_modes = true;
00258 bool allow_explicit_vesa_24bpp = true;
00259 bool allow_hd_vesa_modes = true;
00260 bool vesa12_modes_32bpp = true;
00261 bool allow_vesa_32bpp = true;
00262 bool allow_vesa_24bpp = true;
00263 bool allow_vesa_16bpp = true;
00264 bool allow_vesa_15bpp = true;
00265 bool allow_vesa_8bpp = true;
00266 bool allow_vesa_4bpp = true;
00267 bool allow_vesa_tty = true;
00268 
00269 void gdc_5mhz_mode_update_vars(void);
00270 void pc98_port6A_command_write(unsigned char b);
00271 void pc98_wait_write(Bitu port,Bitu val,Bitu iolen);
00272 void pc98_crtc_write(Bitu port,Bitu val,Bitu iolen);
00273 void pc98_port68_command_write(unsigned char b);
00274 Bitu pc98_read_9a0(Bitu /*port*/,Bitu /*iolen*/);
00275 void pc98_write_9a0(Bitu port,Bitu val,Bitu iolen);
00276 Bitu pc98_crtc_read(Bitu port,Bitu iolen);
00277 Bitu pc98_a1_read(Bitu port,Bitu iolen);
00278 void pc98_a1_write(Bitu port,Bitu val,Bitu iolen);
00279 void pc98_gdc_write(Bitu port,Bitu val,Bitu iolen);
00280 Bitu pc98_gdc_read(Bitu port,Bitu iolen);
00281 Bitu pc98_egc4a0_read(Bitu port,Bitu iolen);
00282 void pc98_egc4a0_write(Bitu port,Bitu val,Bitu iolen);
00283 Bitu pc98_egc4a0_read_warning(Bitu port,Bitu iolen);
00284 void pc98_egc4a0_write_warning(Bitu port,Bitu val,Bitu iolen);
00285 
00286 void page_flip_debug_notify() {
00287     if (enable_page_flip_debugging_marker)
00288         vga_page_flip_occurred = true;
00289 }
00290 
00291 void vsync_poll_debug_notify() {
00292     if (enable_vretrace_poll_debugging_marker)
00293         vga_3da_polled = true;
00294 }
00295 
00296 Bit32u CGA_2_Table[16];
00297 Bit32u CGA_4_Table[256];
00298 Bit32u CGA_4_HiRes_Table[256];
00299 Bit32u CGA_16_Table[256];
00300 Bit32u TXT_Font_Table[16];
00301 Bit32u TXT_FG_Table[16];
00302 Bit32u TXT_BG_Table[16];
00303 Bit32u ExpandTable[256];
00304 Bit32u Expand16Table[4][16];
00305 Bit32u FillTable[16];
00306 Bit32u ColorTable[16];
00307 double vga_force_refresh_rate = -1;
00308 
00309 void VGA_SetModeNow(VGAModes mode) {
00310     if (vga.mode == mode) return;
00311     vga.mode=mode;
00312     VGA_SetupHandlers();
00313     VGA_StartResize(0);
00314 }
00315 
00316 
00317 void VGA_SetMode(VGAModes mode) {
00318     if (vga.mode == mode) return;
00319     vga.mode=mode;
00320     VGA_SetupHandlers();
00321     VGA_StartResize();
00322 }
00323 
00324 void VGA_DetermineMode(void) {
00325     if (svga.determine_mode) {
00326         svga.determine_mode();
00327         return;
00328     }
00329     /* Test for VGA output active or direct color modes */
00330     switch (vga.s3.misc_control_2 >> 4) {
00331     case 0:
00332         if (vga.attr.mode_control & 1) { // graphics mode
00333             if (IS_VGA_ARCH && ((vga.gfx.mode & 0x40)||(vga.s3.reg_3a&0x10))) {
00334                 // access above 256k?
00335                 if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN8);
00336                 else VGA_SetMode(M_VGA);
00337             }
00338             else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4);
00339             else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2);
00340             else {
00341                 // access above 256k?
00342                 if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN4);
00343                 else VGA_SetMode(M_EGA);
00344             }
00345         } else {
00346             VGA_SetMode(M_TEXT);
00347         }
00348         break;
00349     case 1:VGA_SetMode(M_LIN8);break;
00350     case 3:VGA_SetMode(M_LIN15);break;
00351     case 5:VGA_SetMode(M_LIN16);break;
00352     case 7:VGA_SetMode(M_LIN24);break;
00353     case 13:VGA_SetMode(M_LIN32);break;
00354     case 15:VGA_SetMode(M_PACKED4);break;// hacked
00355     }
00356 }
00357 
00358 void VGA_StartResize(Bitu delay /*=50*/) {
00359     if (!vga.draw.resizing) {
00360         /* even if the user disables the delay, we can avoid a lot of window resizing by at least having 1ms of delay */
00361         if (!enable_vga_resize_delay && delay > 1) delay = 1;
00362 
00363         vga.draw.resizing=true;
00364         if (vga.mode==M_ERROR) delay = 5;
00365         /* Start a resize after delay (default 50 ms) */
00366         if (delay==0) VGA_SetupDrawing(0);
00367         else PIC_AddEvent(VGA_SetupDrawing,(float)delay);
00368     }
00369 }
00370 
00371 #define IS_RESET ((vga.seq.reset&0x3)!=0x3)
00372 #define IS_SCREEN_ON ((vga.seq.clocking_mode&0x20)==0)
00373 //static bool hadReset = false;
00374 
00375 // disabled for later improvement
00376 // Idea behind this: If the sequencer was reset and screen off we can
00377 // Problem is some programs measure the refresh rate after switching mode,
00378 // and get it wrong because of the 50ms guard time.
00379 // On the other side, buggers like UniVBE switch the screen mode several
00380 // times so the window is flickering.
00381 // Also the demos that switch display end on screen (Dowhackado)
00382 // would need some attention
00383 
00384 void VGA_SequReset(bool reset) {
00385     (void)reset;//UNUSED
00386     //if(!reset && !IS_SCREEN_ON) hadReset=true;
00387 }
00388 
00389 void VGA_Screenstate(bool enabled) {
00390     (void)enabled;//UNUSED
00391     /*if(enabled && hadReset) {
00392         hadReset=false;
00393         PIC_RemoveEvents(VGA_SetupDrawing);
00394         VGA_SetupDrawing(0);
00395     }*/
00396 }
00397 
00398 void VGA_SetClock(Bitu which,Bitu target) {
00399     if (svga.set_clock) {
00400         svga.set_clock(which, target);
00401         return;
00402     }
00403     struct{
00404         Bitu n,m;
00405         Bits err;
00406     } best;
00407     best.err=(Bits)target;
00408     best.m=1u;
00409     best.n=1u;
00410     Bitu r;
00411 
00412     for (r = 0; r <= 3; r++) {
00413         Bitu f_vco = target * ((Bitu)1u << (Bitu)r);
00414         if (MIN_VCO <= f_vco && f_vco < MAX_VCO) break;
00415     }
00416     for (Bitu n=1;n<=31;n++) {
00417         Bits m=(Bits)((target * (n + 2u) * ((Bitu)1u << (Bitu)r) + (S3_CLOCK_REF / 2u)) / S3_CLOCK_REF) - 2;
00418         if (0 <= m && m <= 127) {
00419             Bitu temp_target = (Bitu)S3_CLOCK(m,n,r);
00420             Bits err = (Bits)(target - temp_target);
00421             if (err < 0) err = -err;
00422             if (err < best.err) {
00423                 best.err = err;
00424                 best.m = (Bitu)m;
00425                 best.n = (Bitu)n;
00426             }
00427         }
00428     }
00429     /* Program the s3 clock chip */
00430     vga.s3.clk[which].m=best.m;
00431     vga.s3.clk[which].r=r;
00432     vga.s3.clk[which].n=best.n;
00433     VGA_StartResize();
00434 }
00435 
00436 void VGA_SetCGA2Table(Bit8u val0,Bit8u val1) {
00437     const Bit8u total[2] = {val0,val1};
00438     for (Bitu i=0;i<16u;i++) {
00439         CGA_2_Table[i]=
00440 #ifdef WORDS_BIGENDIAN
00441             ((Bitu)total[(i >> 0u) & 1u] << 0u  ) | ((Bitu)total[(i >> 1u) & 1u] << 8u  ) |
00442             ((Bitu)total[(i >> 2u) & 1u] << 16u ) | ((Bitu)total[(i >> 3u) & 1u] << 24u );
00443 #else 
00444             ((Bitu)total[(i >> 3u) & 1u] << 0u  ) | ((Bitu)total[(i >> 2u) & 1u] << 8u  ) |
00445             ((Bitu)total[(i >> 1u) & 1u] << 16u ) | ((Bitu)total[(i >> 0u) & 1u] << 24u );
00446 #endif
00447     }
00448 
00449     if (machine == MCH_MCGA) {
00450         VGA_DAC_CombineColor(0x0,val0);
00451         VGA_DAC_CombineColor(0x1,val1);
00452     }
00453 }
00454 
00455 void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) {
00456     const Bit8u total[4] = {val0,val1,val2,val3};
00457     for (Bitu i=0;i<256u;i++) {
00458         CGA_4_Table[i]=
00459 #ifdef WORDS_BIGENDIAN
00460             ((Bitu)total[(i >> 0u) & 3u] << 0u  ) | ((Bitu)total[(i >> 2u) & 3u] << 8u  ) |
00461             ((Bitu)total[(i >> 4u) & 3u] << 16u ) | ((Bitu)total[(i >> 6u) & 3u] << 24u );
00462 #else
00463             ((Bitu)total[(i >> 6u) & 3u] << 0u  ) | ((Bitu)total[(i >> 4u) & 3u] << 8u  ) |
00464             ((Bitu)total[(i >> 2u) & 3u] << 16u ) | ((Bitu)total[(i >> 0u) & 3u] << 24u );
00465 #endif
00466         CGA_4_HiRes_Table[i]=
00467 #ifdef WORDS_BIGENDIAN
00468             ((Bitu)total[((i >> 0u) & 1u) | ((i >> 3u) & 2u)] << 0u  ) | (Bitu)(total[((i >> 1u) & 1u) | ((i >> 4u) & 2u)] << 8u  ) |
00469             ((Bitu)total[((i >> 2u) & 1u) | ((i >> 5u) & 2u)] << 16u ) | (Bitu)(total[((i >> 3u) & 1u) | ((i >> 6u) & 2u)] << 24u );
00470 #else
00471             ((Bitu)total[((i >> 3u) & 1u) | ((i >> 6u) & 2u)] << 0u  ) | (Bitu)(total[((i >> 2u) & 1u) | ((i >> 5u) & 2u)] << 8u  ) |
00472             ((Bitu)total[((i >> 1u) & 1u) | ((i >> 4u) & 2u)] << 16u ) | (Bitu)(total[((i >> 0u) & 1u) | ((i >> 3u) & 2u)] << 24u );
00473 #endif
00474     }
00475 
00476     if (machine == MCH_MCGA) {
00477         VGA_DAC_CombineColor(0x0,val0);
00478         VGA_DAC_CombineColor(0x1,val1);
00479         VGA_DAC_CombineColor(0x2,val2);
00480         VGA_DAC_CombineColor(0x3,val3);
00481     }
00482 }
00483 
00484 class VFRCRATE : public Program {
00485 public:
00486     void Run(void) {
00487         WriteOut("Locks or unlocks the video refresh rate.\n\n");
00488         if (cmd->FindExist("/?", false)) {
00489                         WriteOut("VFRCRATE [SET [OFF|PAL|NTSC|rate]\n");
00490                         WriteOut("  SET OFF   Unlock the refresh rate\n");
00491                         WriteOut("  SET PAL   Lock to PAL frame rate\n");
00492                         WriteOut("  SET NTSC  Lock to NTSC frame rate\n");
00493                         WriteOut("  SET rate  Lock to integer frame rate, e.g. 15\n");
00494                         WriteOut("  SET rate  Lock to decimal frame rate, e.g. 29.97\n");
00495                         WriteOut("  SET rate  Lock to fractional frame rate, e.g. 60000/1001\n");
00496                         return;
00497                 }
00498         if (cmd->FindString("SET",temp_line,false)) {
00499             char *x = (char*)temp_line.c_str();
00500 
00501             if (!strncasecmp(x,"off",3))
00502                 vga_force_refresh_rate = -1;
00503             else if (!strncasecmp(x,"ntsc",4))
00504                 vga_force_refresh_rate = 60000.0/1001;
00505             else if (!strncasecmp(x,"pal",3))
00506                 vga_force_refresh_rate = 50;
00507             else if (strchr(x,'.'))
00508                 vga_force_refresh_rate = atof(x);
00509             else {
00510                 /* fraction */
00511                 int major = -1,minor = 0;
00512                 major = strtol(x,&x,0);
00513                 if (*x == '/' || *x == ':') {
00514                     x++; minor = strtol(x,NULL,0);
00515                 }
00516 
00517                 if (major > 0) {
00518                     vga_force_refresh_rate = (double)major;
00519                     if (minor > 1) vga_force_refresh_rate /= minor;
00520                 }
00521             }
00522 
00523             VGA_SetupHandlers();
00524             VGA_StartResize();
00525         }
00526 
00527         if (vga_force_refresh_rate > 0)
00528             WriteOut("Locked to %.3f fps\n",vga_force_refresh_rate);
00529         else
00530             WriteOut("Unlocked\n");
00531     }
00532 };
00533 
00534 static void VFRCRATE_ProgramStart(Program * * make) {
00535     *make=new VFRCRATE;
00536 }
00537 
00544 class CGASNOW : public Program {
00545 public:
00548     void Run(void) {
00549         if(cmd->FindExist("ON")) {
00550             WriteOut("CGA snow enabled\n");
00551             enableCGASnow = 1;
00552             if (vga.mode == M_TEXT || vga.mode == M_TANDY_TEXT) {
00553                 VGA_SetupHandlers();
00554                 VGA_StartResize();
00555             }
00556         }
00557         else if(cmd->FindExist("OFF")) {
00558             WriteOut("CGA snow disabled\n");
00559             enableCGASnow = 0;
00560             if (vga.mode == M_TEXT || vga.mode == M_TANDY_TEXT) {
00561                 VGA_SetupHandlers();
00562                 VGA_StartResize();
00563             }
00564         }
00565         else {
00566             WriteOut("CGA snow currently %s\n",
00567                 enableCGASnow ? "enabled" : "disabled");
00568         }
00569     }
00570 };
00571 
00572 static void CGASNOW_ProgramStart(Program * * make) {
00573     *make=new CGASNOW;
00574 }
00575 
00576 /* TODO: move to general header */
00577 static inline unsigned int int_log2(unsigned int val) {
00578     unsigned int log = 0;
00579     while ((val >>= 1u) != 0u) log++;
00580     return log;
00581 }
00582 
00583 extern bool pcibus_enable;
00584 extern int hack_lfb_yadjust;
00585 extern uint8_t GDC_display_plane_wait_for_vsync;
00586 
00587 void VGA_VsyncUpdateMode(VGA_Vsync vsyncmode);
00588 
00589 VGA_Vsync VGA_Vsync_Decode(const char *vsyncmodestr) {
00590     if (!strcasecmp(vsyncmodestr,"off")) return VS_Off;
00591     else if (!strcasecmp(vsyncmodestr,"on")) return VS_On;
00592     else if (!strcasecmp(vsyncmodestr,"force")) return VS_Force;
00593     else if (!strcasecmp(vsyncmodestr,"host")) return VS_Host;
00594     else
00595         LOG_MSG("Illegal vsync type %s, falling back to off.",vsyncmodestr);
00596 
00597     return VS_Off;
00598 }
00599 
00600 bool has_pcibus_enable(void);
00601 Bit32u MEM_get_address_bits();
00602 
00603 void VGA_Reset(Section*) {
00604     Section_prop * section=static_cast<Section_prop *>(control->GetSection("dosbox"));
00605         Section_prop * pc98_section=static_cast<Section_prop *>(control->GetSection("pc98"));
00606         
00607     bool lfb_default = false;
00608     string str;
00609     int i;
00610 
00611     Bit32u cpu_addr_bits = MEM_get_address_bits();
00612 //    Bit64u cpu_max_addr = (Bit64u)1 << (Bit64u)cpu_addr_bits;
00613 
00614     LOG(LOG_MISC,LOG_DEBUG)("VGA_Reset() reinitializing VGA emulation");
00615 
00616     GDC_display_plane_wait_for_vsync = pc98_section->Get_bool("pc-98 buffer page flip");
00617 
00618     enable_pci_vga = section->Get_bool("pci vga");
00619 
00620     S3_LFB_BASE = (uint32_t)section->Get_hex("svga lfb base");
00621     if (S3_LFB_BASE == 0) {
00622         if (cpu_addr_bits >= 32)
00623             S3_LFB_BASE = S3_LFB_BASE_DEFAULT;
00624         else if (cpu_addr_bits >= 26)
00625             S3_LFB_BASE = (enable_pci_vga && has_pcibus_enable()) ? 0x02000000 : 0x03400000;
00626         else if (cpu_addr_bits >= 24)
00627             S3_LFB_BASE = 0x00C00000;
00628         else
00629             S3_LFB_BASE = S3_LFB_BASE_DEFAULT;
00630 
00631         lfb_default = true;
00632     }
00633 
00634     /* no farther than 32MB below the top */
00635     if (S3_LFB_BASE > 0xFE000000UL)
00636         S3_LFB_BASE = 0xFE000000UL;
00637 
00638     /* if the user WANTS the base address to be PCI misaligned, then turn off PCI VGA emulation */
00639     if (enable_pci_vga && has_pcibus_enable() && (S3_LFB_BASE & 0x1FFFFFFul)) {
00640         if (!lfb_default)
00641             LOG(LOG_VGA,LOG_DEBUG)("S3 linear framebuffer was set by user to an address not aligned to 32MB, switching off PCI VGA emulation");
00642 
00643         enable_pci_vga = false;
00644     }
00645     /* if memalias is below 26 bits, PCI VGA emulation is impossible */
00646     if (cpu_addr_bits < 26) {
00647         if (IS_VGA_ARCH && enable_pci_vga && has_pcibus_enable())
00648             LOG(LOG_VGA,LOG_DEBUG)("CPU memalias setting is below 26 bits, switching off PCI VGA emulation");
00649 
00650         enable_pci_vga = false;
00651     }
00652 
00653     if (enable_pci_vga && has_pcibus_enable()) {
00654         /* must be 32MB aligned (PCI) */
00655         S3_LFB_BASE +=  0x0FFFFFFUL;
00656         S3_LFB_BASE &= ~0x1FFFFFFUL;
00657     }
00658     else {
00659         /* must be 64KB aligned (ISA) */
00660         S3_LFB_BASE +=  0x7FFFUL;
00661         S3_LFB_BASE &= ~0xFFFFUL;
00662     }
00663 
00664     /* must not overlap system RAM */
00665     if (S3_LFB_BASE < (MEM_TotalPages()*4096))
00666         S3_LFB_BASE = (MEM_TotalPages()*4096);
00667 
00668     /* if the constraints we imposed make it impossible to maintain the alignment required for PCI,
00669      * then just switch off PCI VGA emulation. */
00670     if (IS_VGA_ARCH && enable_pci_vga && has_pcibus_enable()) {
00671         if (S3_LFB_BASE & 0x1FFFFFFUL) { /* not 32MB aligned */
00672             LOG(LOG_VGA,LOG_DEBUG)("S3 linear framebuffer is not 32MB aligned, switching off PCI VGA emulation");
00673             enable_pci_vga = false;
00674         }
00675     }
00676 
00677     /* announce LFB framebuffer address only if actually emulating the S3 */
00678     if (IS_VGA_ARCH && svgaCard == SVGA_S3Trio)
00679         LOG(LOG_VGA,LOG_DEBUG)("S3 linear framebuffer at 0x%lx%s as %s",
00680             (unsigned long)S3_LFB_BASE,lfb_default?" by default":"",
00681             (enable_pci_vga && has_pcibus_enable()) ? "PCI" : "(E)ISA");
00682 
00683     /* other applicable warnings: */
00684     /* Microsoft Windows 3.1 S3 driver:
00685      *   If the LFB is set to an address below 16MB, the driver will program the base to something
00686      *   odd like 0x73000000 and access MMIO through 0x74000000.
00687      *
00688      *   Because of this, if memalias < 31 and LFB is below 16MB mark, Windows won't use the
00689      *   accelerated features of the S3 emulation properly.
00690      *
00691      *   If memalias=24, the driver hangs and nothing appears on screen.
00692      *
00693      *   As far as I can tell, it's mapping for the LFB, not the MMIO. It uses the MMIO in the
00694      *   A0000-AFFFF range anyway. The failure to blit and draw seems to be caused by mapping the
00695      *   LFB out of range like that and then trying to draw on the LFB.
00696      *
00697      *   As far as I can tell from http://www.vgamuseum.info and the list of S3 cards, the S3 chipsets
00698      *   emulated by DOSBox-X and DOSBox SVN here are all EISA and PCI cards, so it's likely the driver
00699      *   is written around the assumption that memory addresses are the full 32 bits to the card, not
00700      *   just the low 24 seen on the ISA slot. So it is unlikely the driver could ever support the
00701      *   card on a 386SX nor could such a card work on a 386SX. It shouldn't even work on a 486SX
00702      *   (26-bit limit), but it could. */
00703     if (IS_VGA_ARCH && svgaCard == SVGA_S3Trio && cpu_addr_bits <= 24)
00704         LOG(LOG_VGA,LOG_WARN)("S3 linear framebuffer warning: memalias setting is known to cause the Windows 3.1 S3 driver to crash");
00705     if (IS_VGA_ARCH && svgaCard == SVGA_S3Trio && cpu_addr_bits < 31 && S3_LFB_BASE < 0x1000000ul) /* below 16MB and memalias == 31 bits */
00706         LOG(LOG_VGA,LOG_WARN)("S3 linear framebuffer warning: A linear framebuffer below the 16MB mark in physical memory when memalias < 31 is known to have problems with the Windows 3.1 S3 driver");
00707 
00708     pc98_allow_scanline_effect = pc98_section->Get_bool("pc-98 allow scanline effect");
00709     mainMenu.get_item("pc98_allow_200scanline").check(pc98_allow_scanline_effect).refresh_item(mainMenu);
00710 
00711     // whether the GDC is running at 2.5MHz or 5.0MHz.
00712     // Some games require the GDC to run at 5.0MHz.
00713     // To enable these games we default to 5.0MHz.
00714     // NTS: There are also games that refuse to run if 5MHz switched on (TH03)
00715     gdc_5mhz_mode = pc98_section->Get_bool("pc-98 start gdc at 5mhz");
00716     mainMenu.get_item("pc98_5mhz_gdc").check(gdc_5mhz_mode).refresh_item(mainMenu);
00717 
00718     // record the initial setting.
00719     // the guest can change it later.
00720     // however the 8255 used to hold dip switch settings needs to reflect the
00721     // initial setting.
00722     gdc_5mhz_mode_initial = gdc_5mhz_mode;
00723 
00724     enable_pc98_egc = pc98_section->Get_bool("pc-98 enable egc");
00725     enable_pc98_grcg = pc98_section->Get_bool("pc-98 enable grcg");
00726     enable_pc98_16color = pc98_section->Get_bool("pc-98 enable 16-color");
00727     enable_pc98_256color = pc98_section->Get_bool("pc-98 enable 256-color");
00728     enable_pc98_188usermod = pc98_section->Get_bool("pc-98 enable 188 user cg");
00729     enable_pc98_256color_planar = pc98_section->Get_bool("pc-98 enable 256-color planar");
00730 
00731 #if 0//TODO: Do not enforce until 256-color mode is fully implemented.
00732      //      Some users out there may expect the EGC, GRCG, 16-color options to disable the emulation.
00733      //      Having 256-color mode on by default, auto-enable them, will cause surprises and complaints.
00734     // 256-color mode implies EGC, 16-color, GRCG
00735     if (enable_pc98_256color) enable_pc98_grcg = enable_pc98_16color = true;
00736 #endif
00737 
00738     // EGC implies GRCG
00739     if (enable_pc98_egc) enable_pc98_grcg = true;
00740 
00741     // EGC implies 16-color
00742     if (enable_pc98_16color) enable_pc98_16color = true;
00743 
00744     str = section->Get_string("vga attribute controller mapping");
00745     if (str == "4x4")
00746         VGA_AC_remap = AC_4x4;
00747     else if (str == "4low")
00748         VGA_AC_remap = AC_low4;
00749     else {
00750         /* auto:
00751          *
00752          * 4x4 by default.
00753          * except for ET4000 which is 4low */
00754         VGA_AC_remap = AC_4x4;
00755         if (IS_VGA_ARCH) {
00756             if (svgaCard == SVGA_TsengET3K || svgaCard == SVGA_TsengET4K)
00757                 VGA_AC_remap = AC_low4;
00758         }
00759     }
00760 
00761     str = pc98_section->Get_string("pc-98 video mode");
00762     if (str == "31khz")
00763         pc98_31khz_mode = true;
00764     else if (str == "15khz")/*TODO*/
00765         pc98_31khz_mode = false;
00766     else
00767         pc98_31khz_mode = false;
00768     //TODO: Announce 31-KHz mode in BIOS config area. --yksoft1
00769     
00770     i = pc98_section->Get_int("pc-98 allow 4 display partition graphics");
00771     pc98_allow_4_display_partitions = (i < 0/*auto*/ || i == 1/*on*/);
00772     mainMenu.get_item("pc98_allow_4partitions").check(pc98_allow_4_display_partitions).refresh_item(mainMenu);
00773     // TODO: "auto" will default to true if old PC-9801, false if PC-9821, or
00774     //       a more refined automatic choice according to actual hardware.
00775 
00776     mainMenu.get_item("pc98_enable_egc").check(enable_pc98_egc).refresh_item(mainMenu);
00777     mainMenu.get_item("pc98_enable_grcg").check(enable_pc98_grcg).refresh_item(mainMenu);
00778     mainMenu.get_item("pc98_enable_analog").check(enable_pc98_16color).refresh_item(mainMenu);
00779     mainMenu.get_item("pc98_enable_analog256").check(enable_pc98_256color).refresh_item(mainMenu);
00780     mainMenu.get_item("pc98_enable_188user").check(enable_pc98_188usermod).refresh_item(mainMenu);
00781 
00782     vga_force_refresh_rate = -1;
00783     str=section->Get_string("forcerate");
00784     if (str == "ntsc")
00785         vga_force_refresh_rate = 60000.0 / 1001;
00786     else if (str == "pal")
00787         vga_force_refresh_rate = 50;
00788     else if (str.find_first_of('/') != string::npos) {
00789         char *p = (char*)str.c_str();
00790         int num = 1,den = 1;
00791         num = strtol(p,&p,0);
00792         if (*p == '/') p++;
00793         den = strtol(p,&p,0);
00794         if (num < 1) num = 1;
00795         if (den < 1) den = 1;
00796         vga_force_refresh_rate = (double)num / den;
00797     }
00798     else {
00799         vga_force_refresh_rate = atof(str.c_str());
00800     }
00801 
00802     enableCGASnow = section->Get_bool("cgasnow");
00803     vesa_modelist_cap = section->Get_int("vesa modelist cap");
00804     vesa_mode_width_cap = section->Get_int("vesa modelist width limit");
00805     vesa_mode_height_cap = section->Get_int("vesa modelist height limit");
00806     vga_enable_3C6_ramdac = section->Get_bool("sierra ramdac");
00807     vga_enable_hpel_effects = section->Get_bool("allow hpel effects");
00808     vga_sierra_lock_565 = section->Get_bool("sierra ramdac lock 565");
00809     hretrace_fx_avg_weight = section->Get_double("hretrace effect weight");
00810     ignore_vblank_wraparound = section->Get_bool("ignore vblank wraparound");
00811     int10_vesa_map_as_128kb = section->Get_bool("vesa map non-lfb modes to 128kb region");
00812     vga_enable_hretrace_effects = section->Get_bool("allow hretrace effects");
00813     enable_page_flip_debugging_marker = section->Get_bool("page flip debug line");
00814     vga_palette_update_on_full_load = section->Get_bool("vga palette update on full load");
00815     non_cga_ignore_oddeven = section->Get_bool("ignore odd-even mode in non-cga modes");
00816     enable_vretrace_poll_debugging_marker = section->Get_bool("vertical retrace poll debug line");
00817     vga_double_buffered_line_compare = section->Get_bool("double-buffered line compare");
00818     hack_lfb_yadjust = section->Get_int("vesa lfb base scanline adjust");
00819     allow_vesa_lowres_modes = section->Get_bool("allow low resolution vesa modes");
00820     vesa12_modes_32bpp = section->Get_bool("vesa vbe 1.2 modes are 32bpp");
00821     allow_vesa_4bpp_packed = section->Get_bool("allow 4bpp packed vesa modes");
00822     allow_explicit_vesa_24bpp = section->Get_bool("allow explicit 24bpp vesa modes");
00823     allow_hd_vesa_modes = section->Get_bool("allow high definition vesa modes");
00824     allow_unusual_vesa_modes = section->Get_bool("allow unusual vesa modes");
00825     allow_vesa_32bpp = section->Get_bool("allow 32bpp vesa modes");
00826     allow_vesa_24bpp = section->Get_bool("allow 24bpp vesa modes");
00827     allow_vesa_16bpp = section->Get_bool("allow 16bpp vesa modes");
00828     allow_vesa_15bpp = section->Get_bool("allow 15bpp vesa modes");
00829     allow_vesa_8bpp = section->Get_bool("allow 8bpp vesa modes");
00830     allow_vesa_4bpp = section->Get_bool("allow 4bpp vesa modes");
00831     allow_vesa_tty = section->Get_bool("allow tty vesa modes");
00832     enable_vga_resize_delay = section->Get_bool("enable vga resize delay");
00833     vga_ignore_hdispend_change_if_smaller = section->Get_bool("resize only on vga active display width increase");
00834     vesa_bios_modelist_in_info = section->Get_bool("vesa vbe put modelist in vesa information");
00835 
00836     /* sanity check: "VBE 1.2 modes 32bpp" doesn't make any sense if neither 24bpp or 32bpp is enabled */
00837     if (!allow_vesa_32bpp && !allow_vesa_24bpp)
00838         vesa12_modes_32bpp = 0;
00839     /* sanity check: "VBE 1.2 modes 32bpp=true" doesn't make sense if the user disabled 32bpp */
00840     else if (vesa12_modes_32bpp && !allow_vesa_32bpp)
00841         vesa12_modes_32bpp = 0;
00842     /* sanity check: "VBE 1.2 modes 32bpp=false" doesn't make sense if the user disabled 24bpp */
00843     else if (!vesa12_modes_32bpp && !allow_vesa_24bpp && allow_vesa_32bpp)
00844         vesa12_modes_32bpp = 1;
00845 
00846     if (vga_force_refresh_rate > 0)
00847         LOG(LOG_VGA,LOG_NORMAL)("VGA forced refresh rate active = %.3f",vga_force_refresh_rate);
00848 
00849     vga.draw.resizing=false;
00850 
00851     vga_8bit_dac = false;
00852     enable_vga_8bit_dac = section->Get_bool("enable 8-bit dac");
00853 
00854     vga_memio_delay_ns = section->Get_int("vmemdelay");
00855     if (vga_memio_delay_ns < 0) {
00856         if (IS_EGAVGA_ARCH) {
00857             if (pcibus_enable) {
00858                 /* some delay based on PCI bus protocol with frame start, turnaround, and burst transfer */
00859                 double t = (1000000000.0 * clockdom_PCI_BCLK.freq_div * (1/*turnaround*/+1/*frame start*/+1/*burst*/-0.25/*fudge*/)) / clockdom_PCI_BCLK.freq;
00860                 vga_memio_delay_ns = (int)floor(t);
00861             }
00862             else {
00863                 /* very optimistic setting, ISA bus cycles are longer than 2, but also the 386/486/Pentium pipeline
00864                  * instruction decoding. so it's not a matter of sucking up enough CPU cycle counts to match the
00865                  * duration of a memory I/O cycle, because real hardware probably has another instruction decode
00866                  * going while it does it.
00867                  *
00868                  * this is long enough to fix some demo's raster effects to work properly but not enough to
00869                  * significantly bring DOS games to a crawl. Apparently, this also fixes Future Crew "Panic!"
00870                  * by making the shadebob take long enough to allow the 3D rotating dot object to finish it's
00871                  * routine just in time to become the FC logo, instead of sitting there waiting awkwardly
00872                  * for 3-5 seconds. */
00873                 double t = (1000000000.0 * clockdom_ISA_BCLK.freq_div * 3.75) / clockdom_ISA_BCLK.freq;
00874                 vga_memio_delay_ns = (int)floor(t);
00875             }
00876         }
00877         else if (machine == MCH_CGA || machine == MCH_HERC || machine == MCH_MDA) {
00878             /* default IBM PC/XT 4.77MHz timing. this is carefully tuned so that Trixter's CGA test program
00879              * times our CGA emulation as having about 305KB/sec reading speed. */
00880             double t = (1000000000.0 * clockdom_ISA_OSC.freq_div * 143) / (clockdom_ISA_OSC.freq * 3);
00881             vga_memio_delay_ns = (int)floor(t);
00882         }
00883         else {
00884             /* dunno. pick something */
00885             double t = (1000000000.0 * clockdom_ISA_BCLK.freq_div * 6) / clockdom_ISA_BCLK.freq;
00886             vga_memio_delay_ns = (int)floor(t);
00887         }
00888     }
00889 
00890     LOG(LOG_VGA,LOG_DEBUG)("VGA memory I/O delay %uns",vga_memio_delay_ns);
00891 
00892     /* mainline compatible vmemsize (in MB)
00893      * plus vmemsizekb for KB-level control.
00894      * then we round up a page.
00895      *
00896      * FIXME: If PCjr/Tandy uses system memory as video memory,
00897      *        can we get away with pointing at system memory
00898      *        directly and not allocate a dedicated char[]
00899      *        array for VRAM? Likewise for VGA emulation of
00900      *        various motherboard chipsets known to "steal"
00901      *        off the top of system RAM, like Intel and
00902      *        Chips & Tech VGA implementations? */
00903     {
00904         int sz_m = section->Get_int("vmemsize");
00905         int sz_k = section->Get_int("vmemsizekb");
00906 
00907         if (sz_m >= 0 || sz_k > 0) {
00908             vga.mem.memsize  = _MB_bytes((unsigned int)sz_m);
00909             vga.mem.memsize += _KB_bytes((unsigned int)sz_k);
00910             vga.mem.memsize  = (vga.mem.memsize + 0xFFFu) & (~0xFFFu);
00911             /* mainline compatible: vmemsize == 0 means 512KB */
00912             if (vga.mem.memsize == 0) vga.mem.memsize = _KB_bytes(512);
00913 
00914             /* round up to the nearest power of 2 (TODO: Any video hardware that uses non-power-of-2 sizes?).
00915              * A lot of DOSBox's VGA emulation code assumes power-of-2 VRAM sizes especially when wrapping
00916              * memory addresses with (a & (vmemsize - 1)) type code. */
00917             if (!is_power_of_2(vga.mem.memsize)) {
00918                 vga.mem.memsize = 1u << (int_log2(vga.mem.memsize) + 1u);
00919                 LOG(LOG_VGA,LOG_WARN)("VGA RAM size requested is not a power of 2, rounding up to %uKB",vga.mem.memsize>>10);
00920             }
00921         }
00922         else {
00923             vga.mem.memsize = 0; /* machine-specific code will choose below */
00924         }
00925     }
00926 
00927     /* sanity check according to adapter type.
00928      * FIXME: Again it was foolish for DOSBox to standardize on machine=
00929      * for selecting machine type AND video card. */
00930     switch (machine) {
00931         case MCH_HERC:
00932             if (vga.mem.memsize < _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64);
00933             break;
00934         case MCH_MDA:
00935             if (vga.mem.memsize < _KB_bytes(4)) vga.mem.memsize = _KB_bytes(4);
00936             break;
00937         case MCH_CGA:
00938             if (vga.mem.memsize < _KB_bytes(16)) vga.mem.memsize = _KB_bytes(16);
00939             break;
00940         case MCH_TANDY:
00941         case MCH_PCJR:
00942             if (vga.mem.memsize < _KB_bytes(128)) vga.mem.memsize = _KB_bytes(128); /* FIXME: Right? */
00943             break;
00944         case MCH_EGA:
00945                  // EGA cards supported either 64KB, 128KB or 256KB.
00946                  if (vga.mem.memsize == 0)              vga.mem.memsize = _KB_bytes(256);//default
00947             else if (vga.mem.memsize <= _KB_bytes(64))  vga.mem.memsize = _KB_bytes(64);
00948             else if (vga.mem.memsize <= _KB_bytes(128)) vga.mem.memsize = _KB_bytes(128);
00949             else                                        vga.mem.memsize = _KB_bytes(256);
00950             break;
00951         case MCH_VGA:
00952             // TODO: There are reports of VGA cards that have less than 256KB in the early days of VGA.
00953             //       How does that work exactly, especially when 640x480 requires about 37KB per plane?
00954             //       Did these cards have some means to chain two bitplanes odd/even in the same way
00955             //       tha EGA did it?
00956             if (vga.mem.memsize != 0 || svgaCard == SVGA_None) {
00957                 if (vga.mem.memsize < _KB_bytes(256)) vga.mem.memsize = _KB_bytes(256);
00958             }
00959             break;
00960         case MCH_AMSTRAD:
00961             if (vga.mem.memsize < _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64); /* FIXME: Right? */
00962             break;
00963         case MCH_PC98:
00964             if (vga.mem.memsize < _KB_bytes(544)) vga.mem.memsize = _KB_bytes(544); /* 544 = 512KB graphics + 32KB text */
00965             break;
00966         case MCH_MCGA:
00967             if (vga.mem.memsize < _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64);
00968             break;
00969         default:
00970             E_Exit("Unexpected machine");
00971     }
00972 
00973     /* I'm sorry, emulating 640x350 4-color chained EGA graphics is
00974      * harder than I thought and would require revision of quite a
00975      * bit of VGA planar emulation to update only bitplane 0 and 2
00976      * in such a manner. --J.C. */
00977     if (IS_EGA_ARCH && vga.mem.memsize < _KB_bytes(128))
00978         LOG_MSG("WARNING: EGA 64KB emulation is very experimental and not well supported");
00979 
00980     // prepare for transition
00981     if (want_fm_towns) {
00982         if (vga.mem.memsize < _KB_bytes(640)) vga.mem.memsize = _KB_bytes(640); /* "640KB of RAM, 512KB VRAM and 128KB sprite RAM" */
00983     }
00984 
00985     if (!IS_PC98_ARCH)
00986         SVGA_Setup_Driver();        // svga video memory size is set here, possibly over-riding the user's selection
00987 
00988     // NTS: This is WHY the memory size must be a power of 2
00989     vga.mem.memmask = vga.mem.memsize - 1u;
00990 
00991     LOG(LOG_VGA,LOG_NORMAL)("Video RAM: %uKB",vga.mem.memsize>>10);
00992 
00993     // TODO: If S3 emulation, and linear framebuffer bumps up against the CPU memalias limits,
00994     //       trim Video RAM to fit (within reasonable limits) or else E_Exit() to let the user
00995     //       know of impossible constraints.
00996 
00997     mainMenu.get_item("debug_pageflip").check(enable_page_flip_debugging_marker).refresh_item(mainMenu);
00998     mainMenu.get_item("debug_retracepoll").check(enable_vretrace_poll_debugging_marker).refresh_item(mainMenu);
00999 
01000     VGA_SetupMemory();      // memory is allocated here
01001     if (!IS_PC98_ARCH) {
01002         VGA_SetupMisc();
01003         VGA_SetupDAC();
01004         VGA_SetupGFX();
01005         VGA_SetupSEQ();
01006         VGA_SetupAttr();
01007         VGA_SetupOther();
01008         VGA_SetupXGA();
01009         VGA_SetClock(0,CLK_25);
01010         VGA_SetClock(1,CLK_28);
01011         /* Generate tables */
01012         VGA_SetCGA2Table(0,1);
01013         VGA_SetCGA4Table(0,1,2,3);
01014     }
01015 
01016     Section_prop * section2=static_cast<Section_prop *>(control->GetSection("vsync"));
01017 
01018     const char * vsyncmodestr;
01019     vsyncmodestr=section2->Get_string("vsyncmode");
01020     void change_output(int output);
01021     change_output(8);
01022     VGA_VsyncUpdateMode(VGA_Vsync_Decode(vsyncmodestr));
01023 
01024     const char * vsyncratestr;
01025     vsyncratestr=section2->Get_string("vsyncrate");
01026     double vsyncrate=70;
01027     if (!strcasecmp(vsyncmodestr,"host")) {
01028 #if defined (WIN32)
01029         DEVMODE devmode;
01030 
01031         if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode))
01032             vsyncrate=devmode.dmDisplayFrequency;
01033         else
01034             sscanf(vsyncratestr,"%lf",&vsyncrate);
01035 #endif
01036     }
01037     else {
01038         sscanf(vsyncratestr,"%lf",&vsyncrate);
01039     }
01040 
01041     vsync.period = (1000.0F)/vsyncrate;
01042 
01043     // TODO: Code to remove programs added by PROGRAMS_MakeFile
01044 
01045     if (machine == MCH_CGA) PROGRAMS_MakeFile("CGASNOW.COM",CGASNOW_ProgramStart);
01046     PROGRAMS_MakeFile("VFRCRATE.COM",VFRCRATE_ProgramStart);
01047 
01048     if (IS_PC98_ARCH) {
01049         void VGA_OnEnterPC98(Section *sec);
01050         void VGA_OnEnterPC98_phase2(Section *sec);
01051         void PC98_FM_OnEnterPC98(Section *sec);
01052 
01053         VGA_OnEnterPC98(NULL);
01054         VGA_OnEnterPC98_phase2(NULL);
01055 
01056         // TODO: Move to separate file
01057         PC98_FM_OnEnterPC98(NULL);
01058     }
01059 }
01060 
01061 extern void VGA_TweakUserVsyncOffset(float val);
01062 void INT10_PC98_CurMode_Relocate(void);
01063 void VGA_UnsetupMisc(void);
01064 void VGA_UnsetupAttr(void);
01065 void VGA_UnsetupDAC(void);
01066 void VGA_UnsetupGFX(void);
01067 void VGA_UnsetupSEQ(void);
01068 
01069 #define gfx(blah) vga.gfx.blah
01070 #define seq(blah) vga.seq.blah
01071 #define crtc(blah) vga.crtc.blah
01072 
01073 void VGA_OnEnterPC98(Section *sec) {
01074     (void)sec;//UNUSED
01075     VGA_UnsetupMisc();
01076     VGA_UnsetupAttr();
01077     VGA_UnsetupDAC();
01078     VGA_UnsetupGFX();
01079     VGA_UnsetupSEQ();
01080 
01081     LOG_MSG("PC-98: GDC is running at %.1fMHz.",gdc_5mhz_mode ? 5.0 : 2.5);
01082 
01083     pc98_egc_srcmask[0] = 0xFF;
01084     pc98_egc_srcmask[1] = 0xFF;
01085     pc98_egc_maskef[0] = 0xFF;
01086     pc98_egc_maskef[1] = 0xFF;
01087     pc98_egc_mask[0] = 0xFF;
01088     pc98_egc_mask[1] = 0xFF;
01089 
01090     for (unsigned int i=0;i < 8;i++)
01091         pc98_pal_digital[i] = i;
01092 
01093     for (unsigned int i=0;i < 8;i++) {
01094         pc98_pal_analog[(i*3) + 0] = (i & 4) ? 0x0F : 0x00;
01095         pc98_pal_analog[(i*3) + 1] = (i & 2) ? 0x0F : 0x00;
01096         pc98_pal_analog[(i*3) + 2] = (i & 1) ? 0x0F : 0x00;
01097 
01098         if (i != 0) {
01099             pc98_pal_analog[((i+8)*3) + 0] = (i & 4) ? 0x0A : 0x00;
01100             pc98_pal_analog[((i+8)*3) + 1] = (i & 2) ? 0x0A : 0x00;
01101             pc98_pal_analog[((i+8)*3) + 2] = (i & 1) ? 0x0A : 0x00;
01102         }
01103         else {
01104             pc98_pal_analog[((i+8)*3) + 0] = 0x07;
01105             pc98_pal_analog[((i+8)*3) + 1] = 0x07;
01106             pc98_pal_analog[((i+8)*3) + 2] = 0x07;
01107         }
01108     }
01109 
01110     for (unsigned int i=0;i < 256;i++) {
01111         pc98_pal_vga[(i*3)+0] = i;
01112         pc98_pal_vga[(i*3)+1] = i;
01113         pc98_pal_vga[(i*3)+2] = i;
01114     }
01115 
01116     pc98_update_palette();
01117 
01118     {
01119         for (unsigned int i=0;i < 8;i++) {
01120             unsigned char r = (i & 2) ? 255 : 0;
01121             unsigned char g = (i & 4) ? 255 : 0;
01122             unsigned char b = (i & 1) ? 255 : 0;
01123 
01124             if (GFX_bpp >= 24) /* FIXME: Assumes 8:8:8. What happens when desktops start using the 10:10:10 format? */
01125                 pc98_text_palette[i] = ((Bitu)(((Bitu)b << GFX_Bshift) + ((Bitu)g << GFX_Gshift) + ((Bitu)r << GFX_Rshift) + (Bitu)GFX_Amask));
01126             else {
01127                 /* FIXME: PC-98 mode renders as 32bpp regardless (at this time), so we have to fake 32bpp order */
01128                 /*        Since PC-98 itself has 4-bit RGB precision, it might be best to offer a 16bpp rendering mode,
01129                  *        or even just have PC-98 mode stay in 16bpp entirely. */
01130                 if (GFX_Bshift == 0)
01131                     pc98_text_palette[i] = (Bitu)(((Bitu)b <<  0U) + ((Bitu)g <<  8U) + ((Bitu)r << 16U));
01132                 else
01133                     pc98_text_palette[i] = (Bitu)(((Bitu)b << 16U) + ((Bitu)g <<  8U) + ((Bitu)r <<  0U));
01134             }
01135         }
01136     }
01137 
01138     pc98_gdc_tile_counter=0;
01139     pc98_gdc_modereg=0;
01140     for (unsigned int i=0;i < 4;i++) pc98_gdc_tiles[i].w = 0;
01141 
01142     vga.dac.pel_mask = 0xFF;
01143     vga.crtc.maximum_scan_line = 15;
01144 
01145     /* 200-line tradition on PC-98 seems to be to render only every other scanline */
01146     pc98_graphics_hide_odd_raster_200line = true;
01147     pc98_256kb_boundary = false;         /* port 6Ah command 68h/69h */
01148 
01149     // as a transition to PC-98 GDC emulation, move VGA alphanumeric buffer
01150     // down to A0000-AFFFFh.
01151     gdc_analog = false;
01152     pc98_gdc_vramop &= ~(1 << VOPBIT_ANALOG);
01153     gfx(miscellaneous) &= ~0x0C; /* bits[3:2] = 0 to map A0000-BFFFF */
01154     VGA_DetermineMode();
01155     VGA_SetupHandlers();
01156     VGA_DAC_UpdateColorPalette();
01157     INT10_PC98_CurMode_Relocate(); /* make sure INT 10h knows */
01158 
01159     if(!pc98_31khz_mode) { /* Set up 24KHz hsync 56.42Hz rate */
01160         vga.crtc.horizontal_total = 106 - 5;
01161         vga.crtc.vertical_total = (440 - 2) & 0xFF;
01162         vga.crtc.end_vertical_blanking = (440 - 2 - 8) & 0xFF; // FIXME
01163         vga.crtc.vertical_retrace_start = (440 - 2 - 30) & 0xFF; // FIXME
01164         vga.crtc.vertical_retrace_end = (440 - 2 - 28) & 0xFF; // FIXME
01165         vga.crtc.start_vertical_blanking = (400 + 8) & 0xFF; // FIXME
01166         vga.crtc.overflow |=  0x01;
01167         vga.crtc.overflow &= ~0x20;
01168     } else { //Set up 31-KHz mode. Values guessed according to other 640x400 modes in int10_modes.cpp.
01169         //TODO: Find the right values by inspecting a real PC-9821 system.
01170         vga.crtc.horizontal_total = 100 - 5;
01171         vga.crtc.vertical_total = (449 - 2) & 0xFF;
01172         vga.crtc.end_vertical_blanking = (449 - 2 - 8) & 0xFF; // FIXME
01173         vga.crtc.vertical_retrace_start = (449 - 2 - 30) & 0xFF; // FIXME
01174         vga.crtc.vertical_retrace_end = (449 - 2 - 28) & 0xFF; // FIXME
01175         vga.crtc.start_vertical_blanking = (400 + 8) & 0xFF; // FIXME
01176         vga.crtc.overflow |=  0x01;
01177         vga.crtc.overflow &= ~0x20;
01178     }
01179 
01180     /* 8-char wide mode. change to 25MHz clock to match. */
01181     vga.config.addr_shift = 0;
01182     seq(clocking_mode) |= 1; /* 8-bit wide char */
01183     vga.misc_output &= ~0x0C; /* bits[3:2] = 0 25MHz clock */
01184 
01185     /* PC-98 seems to favor a block cursor */
01186     vga.draw.cursor.enabled = true;
01187     crtc(cursor_start) = 0;
01188     vga.draw.cursor.sline = 0;
01189     crtc(cursor_end) = 15;
01190     vga.draw.cursor.eline = 15;
01191 
01192     /* now, switch to PC-98 video emulation */
01193     for (unsigned int i=0;i < 16;i++) VGA_ATTR_SetPalette(i,i);
01194     for (unsigned int i=0;i < 16;i++) vga.dac.combine[i] = i;
01195 
01196     vga.mode=M_PC98;
01197     assert(vga.mem.memsize >= 0x80000);
01198     memset(vga.mem.linear,0,0x80000);
01199 
01200     VGA_StartResize();
01201 }
01202 
01203 void MEM_ResetPageHandler_Unmapped(Bitu phys_page, Bitu pages);
01204 
01205 void updateGDCpartitions4(bool enable) {
01206     pc98_allow_4_display_partitions = enable;
01207     pc98_gdc[GDC_SLAVE].display_partition_mask = pc98_allow_4_display_partitions ? 3 : 1;
01208 }
01209 
01210 /* source: Neko Project II  GDC SYNC parameters for each mode */
01211 
01212 #if 0 // NOT YET USED
01213 static const UINT8 gdc_defsyncm15[8] = {0x10,0x4e,0x07,0x25,0x0d,0x0f,0xc8,0x94};
01214 static const UINT8 gdc_defsyncs15[8] = {0x06,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94};
01215 #endif
01216 
01217 static const UINT8 gdc_defsyncm24[8] = {0x10,0x4e,0x07,0x25,0x07,0x07,0x90,0x65};
01218 static const UINT8 gdc_defsyncs24[8] = {0x06,0x26,0x03,0x11,0x83,0x07,0x90,0x65};
01219 
01220 static const UINT8 gdc_defsyncm31[8] = {0x10,0x4e,0x47,0x0c,0x07,0x0d,0x90,0x89};
01221 static const UINT8 gdc_defsyncs31[8] = {0x06,0x26,0x41,0x0c,0x83,0x0d,0x90,0x89};
01222 
01223 static const UINT8 gdc_defsyncm31_480[8] = {0x10,0x4e,0x4b,0x0c,0x03,0x06,0xe0,0x95};
01224 static const UINT8 gdc_defsyncs31_480[8] = {0x06,0x4e,0x4b,0x0c,0x83,0x06,0xe0,0x95};
01225 
01226 void PC98_Set24KHz(void) {
01227     pc98_gdc[GDC_MASTER].write_fifo_command(0x0F/*sync DE=1*/);
01228     for (unsigned int i=0;i < 8;i++)
01229         pc98_gdc[GDC_MASTER].write_fifo_param(gdc_defsyncm24[i]);
01230     pc98_gdc[GDC_MASTER].force_fifo_complete();
01231 
01232     pc98_gdc[GDC_SLAVE].write_fifo_command(0x0F/*sync DE=1*/);
01233     for (unsigned int i=0;i < 8;i++)
01234         pc98_gdc[GDC_SLAVE].write_fifo_param(gdc_defsyncs24[i]);
01235     pc98_gdc[GDC_SLAVE].force_fifo_complete();
01236 }
01237 
01238 void PC98_Set31KHz(void) {
01239     pc98_gdc[GDC_MASTER].write_fifo_command(0x0F/*sync DE=1*/);
01240     for (unsigned int i=0;i < 8;i++)
01241         pc98_gdc[GDC_MASTER].write_fifo_param(gdc_defsyncm31[i]);
01242     pc98_gdc[GDC_MASTER].force_fifo_complete();
01243 
01244     pc98_gdc[GDC_SLAVE].write_fifo_command(0x0F/*sync DE=1*/);
01245     for (unsigned int i=0;i < 8;i++)
01246         pc98_gdc[GDC_SLAVE].write_fifo_param(gdc_defsyncs31[i]);
01247     pc98_gdc[GDC_SLAVE].force_fifo_complete();
01248 }
01249 
01250 void PC98_Set31KHz_480line(void) {
01251     pc98_gdc[GDC_MASTER].write_fifo_command(0x0F/*sync DE=1*/);
01252     for (unsigned int i=0;i < 8;i++)
01253         pc98_gdc[GDC_MASTER].write_fifo_param(gdc_defsyncm31_480[i]);
01254     pc98_gdc[GDC_MASTER].force_fifo_complete();
01255 
01256     pc98_gdc[GDC_SLAVE].write_fifo_command(0x0F/*sync DE=1*/);
01257     for (unsigned int i=0;i < 8;i++)
01258         pc98_gdc[GDC_SLAVE].write_fifo_param(gdc_defsyncs31_480[i]);
01259     pc98_gdc[GDC_SLAVE].force_fifo_complete();
01260 }
01261 
01262 void VGA_OnEnterPC98_phase2(Section *sec) {
01263     (void)sec;//UNUSED
01264     VGA_SetupHandlers();
01265 
01266     /* GDC 2.5/5.0MHz setting is also reflected in BIOS data area and DIP switch registers */
01267     gdc_5mhz_mode_update_vars();
01268 
01269     /* delay I/O port at 0x5F (0.6us) */
01270     IO_RegisterWriteHandler(0x5F,pc98_wait_write,IO_MB);
01271 
01272     /* master GDC at 0x60-0x6F (even)
01273      * slave GDC at 0xA0-0xAF (even) */
01274     for (unsigned int i=0x60;i <= 0xA0;i += 0x40) {
01275         for (unsigned int j=0;j < 0x10;j += 2) {
01276             IO_RegisterWriteHandler(i+j,pc98_gdc_write,IO_MB);
01277             IO_RegisterReadHandler(i+j,pc98_gdc_read,IO_MB);
01278         }
01279     }
01280 
01281     /* initial implementation of I/O ports 9A0h-9AEh even */
01282     IO_RegisterReadHandler(0x9A0,pc98_read_9a0,IO_MB);
01283     IO_RegisterWriteHandler(0x9A0,pc98_write_9a0,IO_MB);
01284 
01285     /* 9A8h which controls 24khz/31khz mode */
01286     IO_RegisterReadHandler(0x9A8,pc98_read_9a8,IO_MB);
01287     IO_RegisterWriteHandler(0x9A8,pc98_write_9a8,IO_MB);
01288 
01289     /* There are some font character RAM controls at 0xA1-0xA5 (odd)
01290      * combined with A4000-A4FFF. Found by unknown I/O tracing in DOSBox-X
01291      * and by tracing INT 18h AH=1Ah on an actual system using DEBUG.COM.
01292      *
01293      * If I find documentation on what exactly these ports are, I will
01294      * list them as such.
01295      *
01296      * Some games (Touhou Project) load font RAM directly through these
01297      * ports instead of using the BIOS. */
01298     for (unsigned int i=0xA1;i <= 0xA9;i += 2) {
01299         IO_RegisterWriteHandler(i,pc98_a1_write,IO_MB);
01300     }
01301     /* Touhou Project appears to read font RAM as well */
01302     IO_RegisterReadHandler(0xA9,pc98_a1_read,IO_MB);
01303 
01304     /* CRTC at 0x70-0x7F (even) */
01305     for (unsigned int j=0x70;j < 0x80;j += 2) {
01306         IO_RegisterWriteHandler(j,pc98_crtc_write,IO_MB);
01307         IO_RegisterReadHandler(j,pc98_crtc_read,IO_MB);
01308     }
01309 
01310     /* EGC at 0x4A0-0x4AF (even).
01311      * All I/O ports are 16-bit.
01312      * NTS: On real hardware, doing 8-bit I/O on these ports will often hang the system. */
01313     for (unsigned int i=0;i < 0x10;i += 2) {
01314         IO_RegisterWriteHandler(i+0x4A0,pc98_egc4a0_write_warning,IO_MB);
01315         IO_RegisterWriteHandler(i+0x4A0,pc98_egc4a0_write,        IO_MW);
01316         IO_RegisterWriteHandler(i+0x4A1,pc98_egc4a0_write_warning,IO_MB);
01317         IO_RegisterWriteHandler(i+0x4A1,pc98_egc4a0_write_warning,IO_MW);
01318 
01319         IO_RegisterReadHandler(i+0x4A0,pc98_egc4a0_read_warning,IO_MB);
01320         IO_RegisterReadHandler(i+0x4A0,pc98_egc4a0_read,        IO_MW);
01321         IO_RegisterReadHandler(i+0x4A1,pc98_egc4a0_read_warning,IO_MB);
01322         IO_RegisterReadHandler(i+0x4A1,pc98_egc4a0_read_warning,IO_MW);
01323     }
01324 
01325     pc98_gdc[GDC_MASTER].master_sync = true;
01326     pc98_gdc[GDC_MASTER].display_enable = true;
01327     pc98_gdc[GDC_MASTER].row_height = 16;
01328     pc98_gdc[GDC_MASTER].display_pitch = 80;
01329     pc98_gdc[GDC_MASTER].active_display_words_per_line = 80;
01330     pc98_gdc[GDC_MASTER].display_partition_mask = 3;
01331 
01332     pc98_gdc[GDC_SLAVE].master_sync = false;
01333     pc98_gdc[GDC_SLAVE].display_enable = false;//FIXME
01334     pc98_gdc[GDC_SLAVE].row_height = 1;
01335     pc98_gdc[GDC_SLAVE].display_pitch = gdc_5mhz_mode ? 80u : 40u;
01336     pc98_gdc[GDC_SLAVE].display_partition_mask = pc98_allow_4_display_partitions ? 3 : 1;
01337 
01338     const unsigned char *gdcsync_m;
01339     const unsigned char *gdcsync_s;
01340 
01341     if (!pc98_31khz_mode) {
01342         gdcsync_m = gdc_defsyncm24;
01343         gdcsync_s = gdc_defsyncs24;
01344     }
01345     else {
01346         gdcsync_m = gdc_defsyncm31;
01347         gdcsync_s = gdc_defsyncs31;
01348     }
01349 
01350     pc98_gdc[GDC_MASTER].write_fifo_command(0x0F/*sync DE=1*/);
01351     for (unsigned int i=0;i < 8;i++)
01352         pc98_gdc[GDC_MASTER].write_fifo_param(gdcsync_m[i]);
01353     pc98_gdc[GDC_MASTER].force_fifo_complete();
01354 
01355     pc98_gdc[GDC_SLAVE].write_fifo_command(0x0F/*sync DE=1*/);
01356     for (unsigned int i=0;i < 8;i++)
01357         pc98_gdc[GDC_SLAVE].write_fifo_param(gdcsync_s[i]);
01358     pc98_gdc[GDC_SLAVE].force_fifo_complete();
01359 
01360     VGA_StartResize();
01361 }
01362 
01363 void VGA_Destroy(Section*) {
01364     void PC98_FM_Destroy(Section *sec);
01365     PC98_FM_Destroy(NULL);
01366 }
01367 
01368 extern uint8_t                     pc98_pal_analog[256*3]; /* G R B    0x0..0xF */
01369 extern uint8_t                     pc98_pal_digital[8];    /* G R B    0x0..0x7 */
01370 
01371 void pc98_update_palette(void);
01372 void UpdateCGAFromSaveState(void);
01373 
01374 bool debugpollvga_pf_menu_callback(DOSBoxMenu * const xmenu, DOSBoxMenu::item * const menuitem) {
01375     (void)xmenu;//UNUSED
01376     (void)menuitem;//UNUSED
01377 
01378     enable_page_flip_debugging_marker = !enable_page_flip_debugging_marker;
01379     mainMenu.get_item("debug_pageflip").check(enable_page_flip_debugging_marker).refresh_item(mainMenu);
01380 
01381     return true;
01382 }
01383 
01384 bool debugpollvga_rtp_menu_callback(DOSBoxMenu * const xmenu, DOSBoxMenu::item * const menuitem) {
01385     (void)xmenu;//UNUSED
01386     (void)menuitem;//UNUSED
01387 
01388     enable_vretrace_poll_debugging_marker = !enable_vretrace_poll_debugging_marker;
01389     mainMenu.get_item("debug_retracepoll").check(enable_vretrace_poll_debugging_marker).refresh_item(mainMenu);
01390 
01391     return true;
01392 }
01393 
01394 void VGA_Init() {
01395     Bitu i,j;
01396 
01397     vga.mode=M_ERROR;           //For first init
01398     vga.other.mcga_mode_control = 0;
01399 
01400         vga.config.chained = false;
01401 
01402     vga.draw.render_step = 0;
01403     vga.draw.render_max = 1;
01404 
01405     vga.tandy.draw_base = NULL;
01406     vga.tandy.mem_base = NULL;
01407     LOG(LOG_MISC,LOG_DEBUG)("Initializing VGA");
01408     LOG(LOG_MISC,LOG_DEBUG)("Render scaler maximum resolution is %u x %u",SCALER_MAXWIDTH,SCALER_MAXHEIGHT);
01409 
01410     VGA_TweakUserVsyncOffset(0.0f);
01411 
01412     for (i=0;i<256;i++) {
01413         ExpandTable[i]=(Bitu)(i + (i << 8u) + (i << 16u) + (i << 24u));
01414     }
01415     for (i=0;i<16;i++) {
01416         TXT_FG_Table[i]=(Bitu)(i + (i << 8u) + (i << 16u) + (i << 24u));
01417         TXT_BG_Table[i]=(Bitu)(i + (i << 8u) + (i << 16u) + (i << 24u));
01418 #ifdef WORDS_BIGENDIAN
01419         FillTable[i]=
01420             ((i & 1u) ? 0xff000000u : 0u) |
01421             ((i & 2u) ? 0x00ff0000u : 0u) |
01422             ((i & 4u) ? 0x0000ff00u : 0u) |
01423             ((i & 8u) ? 0x000000ffu : 0u) ;
01424         TXT_Font_Table[i]=
01425             ((i & 1u) ? 0x000000ffu : 0u) |
01426             ((i & 2u) ? 0x0000ff00u : 0u) |
01427             ((i & 4u) ? 0x00ff0000u : 0u) |
01428             ((i & 8u) ? 0xff000000u : 0u) ;
01429 #else 
01430         FillTable[i]=
01431             ((i & 1u) ? 0x000000ffu : 0u) |
01432             ((i & 2u) ? 0x0000ff00u : 0u) |
01433             ((i & 4u) ? 0x00ff0000u : 0u) |
01434             ((i & 8u) ? 0xff000000u : 0u) ;
01435         TXT_Font_Table[i]=  
01436             ((i & 1u) ? 0xff000000u : 0u) |
01437             ((i & 2u) ? 0x00ff0000u : 0u) |
01438             ((i & 4u) ? 0x0000ff00u : 0u) |
01439             ((i & 8u) ? 0x000000ffu : 0u) ;
01440 #endif
01441     }
01442     for (j=0;j<4;j++) {
01443         for (i=0;i<16;i++) {
01444 #ifdef WORDS_BIGENDIAN
01445             Expand16Table[j][i] =
01446                 ((i & 1u) ? 1u <<        j  : 0u) |
01447                 ((i & 2u) ? 1u << (8u +  j) : 0u) |
01448                 ((i & 4u) ? 1u << (16u + j) : 0u) |
01449                 ((i & 8u) ? 1u << (24u + j) : 0u);
01450 #else
01451             Expand16Table[j][i] =
01452                 ((i & 1u) ? 1u << (24u + j) : 0u) |
01453                 ((i & 2u) ? 1u << (16u + j) : 0u) |
01454                 ((i & 4u) ? 1u << (8u  + j) : 0u) |
01455                 ((i & 8u) ? 1u <<        j  : 0u);
01456 #endif
01457         }
01458     }
01459 
01460     mainMenu.alloc_item(DOSBoxMenu::item_type_id,"debug_pageflip").set_text("Page flip debug line").set_callback_function(debugpollvga_pf_menu_callback);
01461     mainMenu.alloc_item(DOSBoxMenu::item_type_id,"debug_retracepoll").set_text("Retrace poll debug line").set_callback_function(debugpollvga_rtp_menu_callback);
01462 
01463     AddExitFunction(AddExitFunctionFuncPair(VGA_Destroy));
01464     AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(VGA_Reset));
01465 }
01466 
01467 void SVGA_Setup_Driver(void) {
01468     memset(&svga, 0, sizeof(SVGA_Driver));
01469 
01470     switch(svgaCard) {
01471     case SVGA_S3Trio:
01472         SVGA_Setup_S3Trio();
01473         break;
01474     case SVGA_TsengET4K:
01475         SVGA_Setup_TsengET4K();
01476         break;
01477     case SVGA_TsengET3K:
01478         SVGA_Setup_TsengET3K();
01479         break;
01480     case SVGA_ParadisePVGA1A:
01481         SVGA_Setup_ParadisePVGA1A();
01482         break;
01483     default:
01484         break;
01485     }
01486 }
01487 
01488 void VGA_CaptureStartNextFrame(void) {
01489     vga_capture_current_rect = vga_capture_rect;
01490     vga_capture_current_address = vga_capture_address;
01491     vga_capture_write_address = vga_capture_address;
01492 
01493     vga_capture_address = 0;
01494 
01495     VGA_UpdateCapturePending();
01496 }
01497 
01498 bool VGA_CaptureValidateCurrentFrame(void) {
01499     if (VGA_IsCaptureEnabled()) {
01500         if (vga_capture_current_rect.x >= 0 && vga_capture_current_rect.y >= 0 &&       // crop rect is within frame
01501             (unsigned int)vga_capture_current_rect.y < vga.draw.height &&
01502             (unsigned int)vga_capture_current_rect.x < vga.draw.width &&
01503             vga_capture_current_rect.w > 0 && vga_capture_current_rect.h > 0 &&         // crop rect size is within frame
01504             (unsigned int)vga_capture_current_rect.h <= vga.draw.height &&
01505             (unsigned int)vga_capture_current_rect.w <= vga.draw.width &&
01506             ((unsigned int)vga_capture_current_rect.x+vga_capture_current_rect.w) <= vga.draw.width && // crop rect pos+size within frame
01507             ((unsigned int)vga_capture_current_rect.y+vga_capture_current_rect.h) <= vga.draw.height) {
01508             return true;
01509         }
01510     }
01511 
01512     return false;
01513 }
01514 
01515 bool VGA_CaptureHasNextFrame(void) {
01516     return !!(vga_capture_address != (uint32_t)0);
01517 }
01518 
01519 void VGA_MarkCaptureAcquired(void) {
01520     if (vga_capture_state & ((uint32_t)(1ul << 1ul))) // if already acquired and guest has not cleared the bit
01521         vga_capture_state |= (uint32_t)(1ul << 6ul); // mark overrun
01522 
01523     vga_capture_state |= (uint32_t)(1ul << 1ul); // mark acquired
01524 }
01525 
01526 void VGA_MarkCaptureRetrace(void) {
01527     vga_capture_state |=   (uint32_t)(1ul << 5ul); // mark retrace
01528 }
01529 
01530 void VGA_MarkCaptureInProgress(bool en) {
01531     const uint32_t f = (uint32_t)(1ul << 3ul);
01532 
01533     if (en)
01534         vga_capture_state |= f;
01535     else
01536         vga_capture_state &= ~f;
01537 }
01538 
01539 bool VGA_IsCapturePending(void) {
01540     return !!(vga_capture_state & ((uint32_t)(1ul << 0ul)));
01541 }
01542 
01543 bool VGA_IsCaptureEnabled(void) {
01544     return !!(vga_capture_state & ((uint32_t)(1ul << 4ul)));
01545 }
01546 
01547 bool VGA_IsCaptureInProgress(void) {
01548     return !!(vga_capture_state & ((uint32_t)(1ul << 3ul)));
01549 }
01550 
01551 void VGA_CaptureMarkError(void) {
01552     vga_capture_state |=   (uint32_t)(1ul << 2ul);  // set error
01553     vga_capture_state &= ~((uint32_t)(1ul << 4ul)); // clear enable
01554 }
01555 
01556 void VGA_UpdateCapturePending(void) {
01557     bool en = false;
01558 
01559     if (VGA_IsCaptureEnabled()) {
01560         if (vga_capture_address != (uint32_t)0)
01561             en = true;
01562     }
01563 
01564     if (en)
01565         vga_capture_state |=   (uint32_t)(1ul << 0ul); // set bit 0 capture pending
01566     else
01567         vga_capture_state &= ~((uint32_t)(1ul << 0ul)); // clear bit 0 capture pending
01568 }
01569 
01570 uint32_t VGA_QueryCaptureState(void) {
01571     /* bits[0:0] = if set, capture pending
01572      * bits[1:1] = if set, capture acquired
01573      * bits[2:2] = if set, capture state error (such as crop rectangle out of bounds)
01574      * bits[3:3] = if set, capture in progress
01575      * bits[4:4] = if set, capture enabled
01576      * bits[5:5] = if set, vertical retrace occurred. capture must be enabled for this to occur
01577      * bits[6:6] = if set, capture was acquired and acquired bit was already set (overrun)
01578      *
01579      * both bits 0 and 1 can be set if one capture has finished and the "next" capture address has been loaded.
01580      */
01581     return vga_capture_state;
01582 }
01583 
01584 void VGA_SetCaptureState(uint32_t v) {
01585     /* bits[1:1] = if set, clear capture acquired bit
01586      * bits[2:2] = if set, clear capture state error
01587        bits[4:4] = if set, enable capture
01588        bits[5:5] = if set, clear vertical retrace occurrence flag
01589        bits[6:6] = if set, clear overrun (acquired) bit */
01590     vga_capture_state ^= (vga_capture_state & v & 0x66/*x110 0110*/);
01591 
01592     vga_capture_state &=    ~0x10u;
01593     vga_capture_state |= v & 0x10u;
01594 
01595     if (!VGA_IsCaptureEnabled())
01596         vga_capture_state = 0;
01597 
01598     VGA_UpdateCapturePending();
01599 }
01600 
01601 uint32_t VGA_QueryCaptureAddress(void) {
01602     return vga_capture_current_address;
01603 }
01604 
01605 void VGA_SetCaptureAddress(uint32_t v) {
01606     vga_capture_address = v;
01607     VGA_UpdateCapturePending();
01608 }
01609 
01610 void VGA_SetCaptureStride(uint32_t v) {
01611     vga_capture_stride = v;
01612     VGA_UpdateCapturePending();
01613 }
01614 
01615 extern void POD_Save_VGA_Draw( std::ostream & );
01616 extern void POD_Save_VGA_Seq( std::ostream & );
01617 extern void POD_Save_VGA_Attr( std::ostream & );
01618 extern void POD_Save_VGA_Crtc( std::ostream & );
01619 extern void POD_Save_VGA_Gfx( std::ostream & );
01620 extern void POD_Save_VGA_Dac( std::ostream & );
01621 extern void POD_Save_VGA_S3( std::ostream & );
01622 extern void POD_Save_VGA_Other( std::ostream & );
01623 extern void POD_Save_VGA_Memory( std::ostream & );
01624 extern void POD_Save_VGA_Paradise( std::ostream & );
01625 extern void POD_Save_VGA_Tseng( std::ostream & );
01626 extern void POD_Save_VGA_XGA( std::ostream & );
01627 extern void POD_Load_VGA_Draw( std::istream & );
01628 extern void POD_Load_VGA_Seq( std::istream & );
01629 extern void POD_Load_VGA_Attr( std::istream & );
01630 extern void POD_Load_VGA_Crtc( std::istream & );
01631 extern void POD_Load_VGA_Gfx( std::istream & );
01632 extern void POD_Load_VGA_Dac( std::istream & );
01633 extern void POD_Load_VGA_S3( std::istream & );
01634 extern void POD_Load_VGA_Other( std::istream & );
01635 extern void POD_Load_VGA_Memory( std::istream & );
01636 extern void POD_Load_VGA_Paradise( std::istream & );
01637 extern void POD_Load_VGA_Tseng( std::istream & );
01638 extern void POD_Load_VGA_XGA( std::istream & );
01639 
01640 //save state support
01641 void *VGA_SetupDrawing_PIC_Event = (void*)((uintptr_t)VGA_SetupDrawing);
01642 
01643 
01644 namespace {
01645 class SerializeVga : public SerializeGlobalPOD {
01646 public:
01647         SerializeVga() : SerializeGlobalPOD("Vga")
01648         {}
01649 
01650 private:
01651         virtual void getBytes(std::ostream& stream)
01652         {
01653                 Bit32u tandy_drawbase_idx, tandy_membase_idx;
01654 
01655 
01656 
01657 
01658                 if( vga.tandy.draw_base == vga.mem.linear ) tandy_drawbase_idx=0xffffffff;
01659                 else tandy_drawbase_idx = vga.tandy.draw_base - MemBase;
01660 
01661                 if( vga.tandy.mem_base == vga.mem.linear ) tandy_membase_idx=0xffffffff;
01662                 else tandy_membase_idx = vga.tandy.mem_base - MemBase;
01663 
01664                 //********************************
01665                 //********************************
01666 
01667                 SerializeGlobalPOD::getBytes(stream);
01668 
01669 
01670                 // - pure data
01671                 WRITE_POD( &vga.mode, vga.mode );
01672                 WRITE_POD( &vga.misc_output, vga.misc_output );
01673 
01674                 
01675                 // VGA_Draw.cpp
01676                 POD_Save_VGA_Draw(stream);
01677 
01678 
01679                 // - pure struct data
01680                 WRITE_POD( &vga.config, vga.config );
01681                 WRITE_POD( &vga.internal, vga.internal );
01682 
01683 
01684                 // VGA_Seq.cpp / VGA_Attr.cpp / (..)
01685                 POD_Save_VGA_Seq(stream);
01686                 POD_Save_VGA_Attr(stream);
01687                 POD_Save_VGA_Crtc(stream);
01688                 POD_Save_VGA_Gfx(stream);
01689                 POD_Save_VGA_Dac(stream);
01690 
01691 
01692                 // - pure data
01693                 WRITE_POD( &vga.latch, vga.latch );
01694 
01695 
01696                 // VGA_S3.cpp
01697                 POD_Save_VGA_S3(stream);
01698 
01699 
01700                 // - pure struct data
01701                 WRITE_POD( &vga.svga, vga.svga );
01702                 WRITE_POD( &vga.herc, vga.herc );
01703 
01704 
01705                 // - near-pure struct data
01706                 WRITE_POD( &vga.tandy, vga.tandy );
01707 
01708                 // - reloc data
01709                 WRITE_POD( &tandy_drawbase_idx, tandy_drawbase_idx );
01710                 WRITE_POD( &tandy_membase_idx, tandy_membase_idx );
01711 
01712 
01713                 // vga_other.cpp / vga_memory.cpp
01714                 POD_Save_VGA_Other(stream);
01715                 POD_Save_VGA_Memory(stream);
01716 
01717 
01718                 // - pure data
01719                 //WRITE_POD( &vga.vmemwrap, vga.vmemwrap );
01720 
01721 
01722                 // - static ptrs + 'new' data
01723                 //Bit8u* fastmem;
01724                 //Bit8u* fastmem_orgptr;
01725 
01726                 // - 'new' data
01727                 //WRITE_POD_SIZE( vga.fastmem_orgptr, sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16) );
01728 
01729 
01730                 // - pure data (variable on S3 card)
01731                 WRITE_POD( &vga.mem.memsize, vga.mem.memsize );
01732 
01733 
01734 #ifdef VGA_KEEP_CHANGES
01735                 // - static ptr
01736                 //Bit8u* map;
01737 
01738                 // - 'new' data
01739                 WRITE_POD_SIZE( vga.changes.map, sizeof(Bit8u) * (VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32 );
01740 
01741 
01742                 // - pure data
01743                 WRITE_POD( &vga.changes.checkMask, vga.changes.checkMask );
01744                 WRITE_POD( &vga.changes.frame, vga.changes.frame );
01745                 WRITE_POD( &vga.changes.writeMask, vga.changes.writeMask );
01746                 WRITE_POD( &vga.changes.active, vga.changes.active );
01747                 WRITE_POD( &vga.changes.clearMask, vga.changes.clearMask );
01748                 WRITE_POD( &vga.changes.start, vga.changes.start );
01749                 WRITE_POD( &vga.changes.last, vga.changes.last );
01750                 WRITE_POD( &vga.changes.lastAddress, vga.changes.lastAddress );
01751 #endif
01752 
01753 
01754                 // - pure data
01755                 WRITE_POD( &vga.lfb.page, vga.lfb.page );
01756                 WRITE_POD( &vga.lfb.addr, vga.lfb.addr );
01757                 WRITE_POD( &vga.lfb.mask, vga.lfb.mask );
01758 
01759                 // - static ptr
01760                 //PageHandler *handler;
01761 
01762 
01763                 // VGA_paradise.cpp / VGA_tseng.cpp / VGA_xga.cpp
01764                 POD_Save_VGA_Paradise(stream);
01765                 POD_Save_VGA_Tseng(stream);
01766                 POD_Save_VGA_XGA(stream);
01767         }
01768 
01769         virtual void setBytes(std::istream& stream)
01770         {
01771                 Bit32u tandy_drawbase_idx, tandy_membase_idx;
01772 
01773 
01774 
01775                 //********************************
01776                 //********************************
01777 
01778                 SerializeGlobalPOD::setBytes(stream);
01779 
01780 
01781                 // - pure data
01782                 READ_POD( &vga.mode, vga.mode );
01783                 READ_POD( &vga.misc_output, vga.misc_output );
01784 
01785                 
01786                 // VGA_Draw.cpp
01787                 POD_Load_VGA_Draw(stream);
01788 
01789 
01790                 // - pure struct data
01791                 READ_POD( &vga.config, vga.config );
01792                 READ_POD( &vga.internal, vga.internal );
01793 
01794 
01795                 // VGA_Seq.cpp / VGA_Attr.cpp / (..)
01796                 POD_Load_VGA_Seq(stream);
01797                 POD_Load_VGA_Attr(stream);
01798                 POD_Load_VGA_Crtc(stream);
01799                 POD_Load_VGA_Gfx(stream);
01800                 POD_Load_VGA_Dac(stream);
01801 
01802 
01803                 // - pure data
01804                 READ_POD( &vga.latch, vga.latch );
01805 
01806 
01807                 // VGA_S3.cpp
01808                 POD_Load_VGA_S3(stream);
01809 
01810 
01811                 // - pure struct data
01812                 READ_POD( &vga.svga, vga.svga );
01813                 READ_POD( &vga.herc, vga.herc );
01814 
01815 
01816                 // - near-pure struct data
01817                 READ_POD( &vga.tandy, vga.tandy );
01818 
01819                 // - reloc data
01820                 READ_POD( &tandy_drawbase_idx, tandy_drawbase_idx );
01821                 READ_POD( &tandy_membase_idx, tandy_membase_idx );
01822 
01823 
01824                 // vga_other.cpp / vga_memory.cpp
01825                 POD_Load_VGA_Other(stream);
01826                 POD_Load_VGA_Memory(stream);
01827 
01828 
01829                 // - pure data
01830                 //READ_POD( &vga.vmemwrap, vga.vmemwrap );
01831 
01832 
01833                 // - static ptrs + 'new' data
01834                 //Bit8u* fastmem;
01835                 //Bit8u* fastmem_orgptr;
01836 
01837                 // - 'new' data
01838                 //READ_POD_SIZE( vga.fastmem_orgptr, sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16) );
01839 
01840 
01841                 // - pure data (variable on S3 card)
01842                 READ_POD( &vga.mem.memsize, vga.mem.memsize );
01843 
01844 
01845 #ifdef VGA_KEEP_CHANGES
01846                 // - static ptr
01847                 //Bit8u* map;
01848 
01849                 // - 'new' data
01850                 READ_POD_SIZE( vga.changes.map, sizeof(Bit8u) * (VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32 );
01851 
01852 
01853                 // - pure data
01854                 READ_POD( &vga.changes.checkMask, vga.changes.checkMask );
01855                 READ_POD( &vga.changes.frame, vga.changes.frame );
01856                 READ_POD( &vga.changes.writeMask, vga.changes.writeMask );
01857                 READ_POD( &vga.changes.active, vga.changes.active );
01858                 READ_POD( &vga.changes.clearMask, vga.changes.clearMask );
01859                 READ_POD( &vga.changes.start, vga.changes.start );
01860                 READ_POD( &vga.changes.last, vga.changes.last );
01861                 READ_POD( &vga.changes.lastAddress, vga.changes.lastAddress );
01862 #endif
01863 
01864 
01865                 // - pure data
01866                 READ_POD( &vga.lfb.page, vga.lfb.page );
01867                 READ_POD( &vga.lfb.addr, vga.lfb.addr );
01868                 READ_POD( &vga.lfb.mask, vga.lfb.mask );
01869 
01870                 // - static ptr
01871                 //PageHandler *handler;
01872 
01873 
01874                 // VGA_paradise.cpp / VGA_tseng.cpp / VGA_xga.cpp
01875                 POD_Load_VGA_Paradise(stream);
01876                 POD_Load_VGA_Tseng(stream);
01877                 POD_Load_VGA_XGA(stream);
01878 
01879                 //********************************
01880                 //********************************
01881 
01882                 if( tandy_drawbase_idx == 0xffffffff ) vga.tandy.draw_base = vga.mem.linear;
01883                 else vga.tandy.draw_base = MemBase + tandy_drawbase_idx;
01884 
01885                 if( tandy_membase_idx == 0xffffffff ) vga.tandy.mem_base = vga.mem.linear;
01886                 else vga.tandy.mem_base = MemBase + tandy_membase_idx;
01887         }
01888 } dummy;
01889 }