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 /* 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 }