sync with upstream svn

This commit is contained in:
dborth 2010-10-06 05:17:29 +00:00
parent 806dc853cc
commit ccd9bdbeac
15 changed files with 569 additions and 276 deletions

59
README
View File

@ -139,7 +139,7 @@ Type INTRO in DOSBox for a quick tour.
It is essential that you get familiar with the idea of mounting, DOSBox does not It is essential that you get familiar with the idea of mounting, DOSBox does not
automatically make any drive (or a part of it) accessible to the emulation. See automatically make any drive (or a part of it) accessible to the emulation. See
the FAQ entry "How to start?" as well as the description of the MOUNT command the FAQ entry "How to start?" as well as the description of the MOUNT command
(section 4: "Internal Programs"). If you have your game on a cdrom you may try (Section 4: "Internal Programs"). If you have your game on a cdrom you may try
this guide: http://vogons.zetafleet.com/viewtopic.php?t=8933 this guide: http://vogons.zetafleet.com/viewtopic.php?t=8933
@ -185,7 +185,7 @@ START: How to start?
AUTOMATION: Do I always have to type these commands? AUTOMATION: Do I always have to type these commands?
In the DOSBox configuration file is an [autoexec] section. The commands In the DOSBox configuration file is an [autoexec] section. The commands
present there are run when DOSBox starts, so you can use this section present there are run when DOSBox starts, so you can use this section
for the mounting. Look at Section 13: The configuration (options) file for the mounting. Look at Section 13: "The configuration (options) file".
FULLSCREEN: How do I change to fullscreen? FULLSCREEN: How do I change to fullscreen?
@ -313,11 +313,12 @@ SOUND: What sound hardware does DOSBox presently emulate?
SOUND: The sound stutters or sounds stretched/weird. SOUND: The sound stutters or sounds stretched/weird.
You may be using too much CPU power to keep DOSBox running at the current You may be using too much CPU power to keep DOSBox running at the current
speed. You can lower the cycles, skip frames, reduce the sampling rate of speed. You can lower the cycles, skip frames, reduce the sampling rate of
the respective sound device, increase the prebuffer. See section 13: "The the respective sound device, increase the prebuffer. See Section 13: "The
configuration (options) file" configuration (options) file".
If you are using cycles=max or =auto, then make sure that there is no If you are using 'cycles=max' or 'cycles=auto', then make sure that there is
background processes interfering! (especially if they access the harddisk) no background processes interfering! (especially if they access the harddisk)
Also look at Section 10. "How to speed up/slow down DOSBox" Also look at Section 10: "How to speed up/slow down DOSBox" as well as
Section 11: "Troubleshooting".
KEYBOARD: I can't type \ or : in DOSBox. KEYBOARD: I can't type \ or : in DOSBox.
@ -326,7 +327,7 @@ KEYBOARD: I can't type \ or : in DOSBox.
detected), or the key mapping is wrong. detected), or the key mapping is wrong.
Some possible fixes: Some possible fixes:
1. Use / instead, or ALT-58 for : and ALT-92 for \. 1. Use / instead, or ALT-58 for : and ALT-92 for \.
2. Change the DOS keyboard layout (see Section 8: Keyboard Layout). 2. Change the DOS keyboard layout (see Section 8: "Keyboard Layout").
3. Add the commands you want to execute to the [autoexec] section 3. Add the commands you want to execute to the [autoexec] section
of the DOSBox configuration file. of the DOSBox configuration file.
4. Open the DOSBox configuration file and change the usescancodes entry. 4. Open the DOSBox configuration file and change the usescancodes entry.
@ -367,16 +368,16 @@ CONTROL: The character/cursor/mouse pointer always moves into one direction!
SPEED: The game/application runs much too slow/too fast! SPEED: The game/application runs much too slow/too fast!
Look at the section 10: "How to speed up/slow down DOSBox" for more Look at Section 10: "How to speed up/slow down DOSBox" for more
information. information.
CRASH: The game/application does not run at all/crashes! CRASH: The game/application does not run at all/crashes!
Look at Section 11: Troubleshooting Look at Section 11: "Troubleshooting".
CRASH: DOSBox crashes on startup!. CRASH: DOSBox crashes on startup!.
Look at Section 11: Troubleshooting Look at Section 11: "Troubleshooting".
GAME: My Build game(Duke3D/Blood/Shadow Warrior) has problems. GAME: My Build game(Duke3D/Blood/Shadow Warrior) has problems.
@ -395,7 +396,7 @@ SAFETY: Can DOSBox harm my computer?
OPTIONS: I would like to change DOSBox's options. OPTIONS: I would like to change DOSBox's options.
Look at Section 13. "The configuration (options) file" Look at Section 13: "The configuration (options) file".
HELP: Great Manual, but I still don't get it. HELP: Great Manual, but I still don't get it.
@ -412,7 +413,7 @@ HELP: Great Manual, but I still don't get it.
An overview of the command line options you can give to DOSBox. Although An overview of the command line options you can give to DOSBox. Although
in most cases it is easier to use DOSBox's configuration file instead. in most cases it is easier to use DOSBox's configuration file instead.
See: Section 13. "The configuration (options) file" See Section 13: "The configuration (options) file".
To be able to use Command Line Parameters: To be able to use Command Line Parameters:
(Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe (Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe
@ -461,11 +462,11 @@ dosbox -erasemapper
-conf configfilelocation -conf configfilelocation
Start DOSBox with the options specified in "configfilelocation". Start DOSBox with the options specified in "configfilelocation".
Multiple -conf options may be present. Multiple -conf options may be present.
See Section 13 for more details. See Section 13: "The configuration (options) file" for more details.
-lang languagefilelocation -lang languagefilelocation
Start DOSBox using the language specified in "languagefilelocation". Start DOSBox using the language specified in "languagefilelocation".
See Section 14 for more details. See Section 14: "The Language File" for more details.
-machine machinetype -machine machinetype
Setup DOSBox to emulate a specific type of machine. Valid choices are: Setup DOSBox to emulate a specific type of machine. Valid choices are:
@ -763,8 +764,8 @@ CONFIG -get "section property"
config -writeconf c:\dosgames\dosbox.conf config -writeconf c:\dosgames\dosbox.conf
2. To set the cpu cycles to 10000: 2. To set the cpu cycles to 10000:
config -set "cpu cycles=10000" config -set "cpu cycles=10000"
3. To turn ems memory emulation off: 3. To turn EMS memory emulation off:
config -set "dos ems=off" config -set "dos ems=false"
4. To check which cpu core is being used. 4. To check which cpu core is being used.
config -get "cpu core" config -get "cpu core"
@ -1015,7 +1016,7 @@ IPX
KEYB [keyboardlayoutcode [codepage [codepagefile]]] KEYB [keyboardlayoutcode [codepage [codepagefile]]]
Change the keyboard layout. For detailed information about keyboard layouts Change the keyboard layout. For detailed information about keyboard layouts
please see Section 8: "Keyboard Layout" please see Section 8: "Keyboard Layout".
[keyboardlayoutcode] is a string consisting of five or less characters, [keyboardlayoutcode] is a string consisting of five or less characters,
examples are PL214 (Polish typists) or PL457 (Polish programmers). examples are PL214 (Polish typists) or PL457 (Polish programmers).
@ -1092,7 +1093,7 @@ F11 (machine=hercules) cycle through amber, green, white colouring***
a different machine type. So either reassign them or reset the mapper. a different machine type. So either reassign them or reset the mapper.
These are the default keybindings. They can be changed in the keymapper These are the default keybindings. They can be changed in the keymapper
(see Section 7: KeyMapper). (see Section 7: "KeyMapper").
In MAC OS you can try using cmd(applekey) together with Ctrl if the key doesn't In MAC OS you can try using cmd(applekey) together with Ctrl if the key doesn't
work eg. cmd-ctrl-F1, but some keys may still need remapping (in Linux too). work eg. cmd-ctrl-F1, but some keys may still need remapping (in Linux too).
@ -1146,8 +1147,8 @@ inside DOSBox, try different 'timed' setting in DOSBox's configuration file.
7. KeyMapper: 7. KeyMapper:
============= =============
You start the DOSBox mapper either with CTRL-F1 (see section 5. Special Keys) You start the DOSBox mapper either with CTRL-F1 (see Section 5: "Special Keys")
or -startmapper (see Section 3. Command Line Parameters). or -startmapper (see Section 3: "Command Line Parameters").
You are presented with a virtual keyboard and a virtual joystick. You are presented with a virtual keyboard and a virtual joystick.
These virtual devices correspond to the keys and events DOSBox will These virtual devices correspond to the keys and events DOSBox will
@ -1241,9 +1242,9 @@ your mapperfile, if it is present in the DOSBox configuration file.
To switch to a different keyboard layout, either the entry "keyboardlayout" To switch to a different keyboard layout, either the entry "keyboardlayout"
in the [dos] section of the DOSBox configuration file can be used, or the in the [dos] section of the DOSBox configuration file can be used, or the
internal DOSBox program keyb.com (Section 4: Internal Programs) internal DOSBox program keyb.com (Section 4: "Internal Programs"). Both accept
Both accept DOS conforming language codes (see below), DOS conforming language codes (see below), but only by using keyb.com a
but only by using keyb.com a custom codepage can be specified. custom codepage can be specified.
The default keyboardlayout=auto currently works under windows only. The language The default keyboardlayout=auto currently works under windows only. The language
is chosen according to the OS language, but the keyboard layout is not detected. is chosen according to the OS language, but the keyboard layout is not detected.
@ -1357,8 +1358,8 @@ CPU Cycles (speed up/slow down)
a different setting in the DOSBox's configuration file. a different setting in the DOSBox's configuration file.
You can force the slow or fast behavior by setting a fixed amount of cycles You can force the slow or fast behavior by setting a fixed amount of cycles
in the DOSBox's configuration file. If you for example set cycles=10000, then in the DOSBox's configuration file. If you set for example cycles=10000, the
DOSBox window will display a line "Cpu Speed: fixed 10000 cycles" at the top. DOSBox window will display a line "CPU speed: fixed 10000 cycles" at the top.
In this mode you can reduce the amount of cycles even more by hitting CTRL-F11 In this mode you can reduce the amount of cycles even more by hitting CTRL-F11
(you can go as low as you want) or raise it by hitting CTRL-F12 as much as you (you can go as low as you want) or raise it by hitting CTRL-F12 as much as you
want, but you will be limited by the power of one core of your computer's CPU. want, but you will be limited by the power of one core of your computer's CPU.
@ -1373,8 +1374,8 @@ CPU Cycles (speed up/slow down)
You can also force the fast behavior by setting cycles=max in the DOSBox You can also force the fast behavior by setting cycles=max in the DOSBox
configuration file. The DOSBox window will display a line configuration file. The DOSBox window will display a line
"Cpu Speed: max 100% cycles" at the top then. This time you won't have to care "CPU speed: max 100% cycles" at the top then. This time you won't have to care
how much free time your real CPU's cores have, because DOSBox will always use how much free time your real CPU cores have, because DOSBox will always use
100% of your real CPU's one core. In this mode you can reduce the amount 100% of your real CPU's one core. In this mode you can reduce the amount
of your real CPU's core usage by CTRL-F11 or raise it with CTRL-F12. of your real CPU's core usage by CTRL-F11 or raise it with CTRL-F12.
@ -1424,7 +1425,7 @@ Example:
==================== ====================
General tip: General tip:
Check messages in DOSBox Status Window. See section 12. "DOSBox Status Window" Check messages in DOSBox Status Window. See Section 12: "DOSBox Status Window".
DOSBox crashes right after starting it: DOSBox crashes right after starting it:
- use different values for the output= entry in your DOSBox - use different values for the output= entry in your DOSBox

View File

@ -114,6 +114,8 @@ DmaChannel * GetDMAChannel(Bit8u chan);
void CloseSecondDMAController(void); void CloseSecondDMAController(void);
bool SecondDMAControllerAvailable(void); bool SecondDMAControllerAvailable(void);
void DMA_SetWrapping(Bitu wrap);
static Bit32u dma_wrapping = 0xffff; static Bit32u dma_wrapping = 0xffff;
#endif #endif

View File

@ -338,7 +338,7 @@ void DOSBOX_Init(void) {
const char* machines[] = { const char* machines[] = {
"hercules", "cga", "tandy", "pcjr", "ega", "hercules", "cga", "tandy", "pcjr", "ega",
"vgaonly", "svga_s3", "svga_et3000", "svga_et4000", "vgaonly", "svga_s3", "svga_et3000", "svga_et4000",
"svga_paradise", "vesa_nolfb", "vesa_oldvbe", 0 }; "svga_paradise", "vesa_nolfb", "vesa_oldvbe", 0 };
secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit);
Pstring = secprop->Add_path("language",Property::Changeable::Always,""); Pstring = secprop->Add_path("language",Property::Changeable::Always,"");
Pstring->Set_help("Select another language file."); Pstring->Set_help("Select another language file.");
@ -681,8 +681,13 @@ void DOSBOX_Init(void) {
Pbool->Set_help("Enable XMS support."); Pbool->Set_help("Enable XMS support.");
secprop->AddInitFunction(&EMS_Init,true);//done secprop->AddInitFunction(&EMS_Init,true);//done
Pbool = secprop->Add_bool("ems",Property::Changeable::WhenIdle,true); const char* ems_settings[] = { "true", "emsboard", "emm386", "false", 0};
Pbool->Set_help("Enable EMS support."); Pstring = secprop->Add_string("ems",Property::Changeable::WhenIdle,"true");
Pstring->Set_values(ems_settings);
Pstring->Set_help("Enable EMS support. The default (=true) provides the best\n"
"compatibility but certain applications may run better with\n"
"other choices, or require EMS support to be disabled (=false)\n"
"to work at all.");
Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true); Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Enable UMB support."); Pbool->Set_help("Enable UMB support.");

View File

@ -239,9 +239,9 @@ void GFX_SetTitle(Bit32s cycles,Bits frameskip,bool paused){
if(cycles != -1) internal_cycles = cycles; if(cycles != -1) internal_cycles = cycles;
if(frameskip != -1) internal_frameskip = frameskip; if(frameskip != -1) internal_frameskip = frameskip;
if(CPU_CycleAutoAdjust) { if(CPU_CycleAutoAdjust) {
sprintf(title,"DOSBox %s, Cpu speed: max %3d%% cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); sprintf(title,"DOSBox %s, CPU speed: max %3d%% cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram);
} else { } else {
sprintf(title,"DOSBox %s, Cpu speed: %8d cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); sprintf(title,"DOSBox %s, CPU speed: %8d cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram);
} }
if(paused) strcat(title," PAUSED"); if(paused) strcat(title," PAUSED");

View File

@ -48,7 +48,9 @@ static void DMA_BlockRead(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8u
offset <<= dma16; offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping; Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
for ( ; size ; size--, offset++) { for ( ; size ; size--, offset++) {
if (offset>(dma_wrapping<<dma16)) E_Exit("DMA segbound wrapping (read)"); if (offset>(dma_wrapping<<dma16)) {
LOG_MSG("DMA segbound wrapping (read): %x:%x size %x [%x] wrap %x",spage,offset,size,dma16,dma_wrapping);
}
offset &= dma_wrap; offset &= dma_wrap;
Bitu page = highpart_addr_page+(offset >> 12); Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */ /* care for EMS pageframe etc. */
@ -67,7 +69,9 @@ static void DMA_BlockWrite(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8
offset <<= dma16; offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping; Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
for ( ; size ; size--, offset++) { for ( ; size ; size--, offset++) {
if (offset>(dma_wrapping<<dma16)) E_Exit("DMA segbound wrapping (write)"); if (offset>(dma_wrapping<<dma16)) {
LOG_MSG("DMA segbound wrapping (write): %x:%x size %x [%x] wrap %x",spage,offset,size,dma16,dma_wrapping);
}
offset &= dma_wrap; offset &= dma_wrap;
Bitu page = highpart_addr_page+(offset >> 12); Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */ /* care for EMS pageframe etc. */

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: hardware.cpp,v 1.23 2009-10-11 18:09:22 qbix79 Exp $ */ /* $Id: hardware.cpp,v 1.22 2009-04-26 18:24:36 qbix79 Exp $ */
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -161,13 +161,17 @@ static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit3
#endif #endif
#if (C_SSHOT) #if (C_SSHOT)
static void CAPTURE_VideoEvent(bool pressed) {
if (!pressed)
return;
if (CaptureState & CAPTURE_VIDEO) {
/* Close the video */
CaptureState &= ~CAPTURE_VIDEO;
LOG_MSG("Stopped capturing video.");
static void CAPTURE_VideoHeader() {
Bit8u avi_header[AVI_HEADER_SIZE]; Bit8u avi_header[AVI_HEADER_SIZE];
Bitu main_list; Bitu main_list;
Bitu header_pos=0; Bitu header_pos=0;
Bitu save_pos=ftell(capture.video.handle);
#define AVIOUT4(_S_) memcpy(&avi_header[header_pos],_S_,4);header_pos+=4; #define AVIOUT4(_S_) memcpy(&avi_header[header_pos],_S_,4);header_pos+=4;
#define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2; #define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2;
#define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4; #define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4;
@ -284,20 +288,6 @@ static void CAPTURE_VideoHeader() {
fwrite( capture.video.index, 1, capture.video.indexused, capture.video.handle); fwrite( capture.video.index, 1, capture.video.indexused, capture.video.handle);
fseek(capture.video.handle, 0, SEEK_SET); fseek(capture.video.handle, 0, SEEK_SET);
fwrite(&avi_header, 1, AVI_HEADER_SIZE, capture.video.handle); fwrite(&avi_header, 1, AVI_HEADER_SIZE, capture.video.handle);
fseek(capture.video.handle, save_pos, SEEK_SET);
}
static void CAPTURE_VideoEvent(bool pressed) {
if (!pressed)
return;
if (CaptureState & CAPTURE_VIDEO) {
/* Close the video */
CaptureState &= ~CAPTURE_VIDEO;
LOG_MSG("Stopped capturing video.");
/* Adds AVI header to the file */
CAPTURE_VideoHeader();
fclose( capture.video.handle ); fclose( capture.video.handle );
free( capture.video.index ); free( capture.video.index );
free( capture.video.buf ); free( capture.video.buf );
@ -557,9 +547,6 @@ skip_shot:
capture.video.audioused = 0; capture.video.audioused = 0;
} }
/* Adds AVI header to the file */
CAPTURE_VideoHeader();
/* Everything went okay, set flag again for next frame */ /* Everything went okay, set flag again for next frame */
CaptureState |= CAPTURE_VIDEO; CaptureState |= CAPTURE_VIDEO;
} }
@ -756,6 +743,9 @@ public:
#endif #endif
} }
~HARDWARE(){ ~HARDWARE(){
#if (C_SSHOT)
if (capture.video.handle) CAPTURE_VideoEvent(true);
#endif
if (capture.wave.handle) CAPTURE_WaveEvent(true); if (capture.wave.handle) CAPTURE_WaveEvent(true);
if (capture.midi.handle) CAPTURE_MidiEvent(true); if (capture.midi.handle) CAPTURE_MidiEvent(true);
} }

View File

@ -118,30 +118,30 @@ static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) {
static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) {
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
Bit32u * draw=(Bit32u *)TempLine; Bit8u* draw=TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) { Bitu end = vga.draw.blocks*2;
Bitu val1 = base[vidstart & vga.tandy.addr_mask]; while(end) {
++vidstart; Bit8u byte = base[vidstart & vga.tandy.addr_mask];
Bitu val2 = base[vidstart & vga.tandy.addr_mask]; *draw++=vga.attr.palette[byte >> 4];
++vidstart; *draw++=vga.attr.palette[byte & 0x0f];
*draw++=(val1 & 0x0f) << 8 | vidstart++;
(val1 & 0xf0) >> 4 | end--;
(val2 & 0x0f) << 24 |
(val2 & 0xf0) << 12;
} }
return TempLine; return TempLine;
} }
static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart, Bitu line) {
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
Bit32u * draw=(Bit32u *)TempLine; Bit8u* draw=TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) { Bitu end = vga.draw.blocks;
Bitu val = base[vidstart & vga.tandy.addr_mask]; while(end) {
++vidstart; Bit8u byte = base[vidstart & vga.tandy.addr_mask];
*draw++=(val & 0xf0) >> 4 | Bit8u data = vga.attr.palette[byte >> 4];
(val & 0xf0) << 4 | *draw++ = data; *draw++ = data;
(val & 0x0f) << 16 | data = vga.attr.palette[byte & 0x0f];
(val & 0x0f) << 24; *draw++ = data; *draw++ = data;
vidstart++;
end--;
} }
return TempLine; return TempLine;
} }
@ -175,12 +175,28 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) {
#endif #endif
static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu /*line*/) { static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu /*line*/) {
// There is guaranteed extra memory past the wrap boundary. So, instead of using temporary
// storage just copy appropriate chunk from the beginning to the wrap boundary when needed.
Bitu offset = vidstart & vga.draw.linear_mask; Bitu offset = vidstart & vga.draw.linear_mask;
if (vga.draw.linear_mask-offset < vga.draw.line_length) Bit8u* ret = &vga.draw.linear_base[offset];
memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length);
Bit8u *ret = &vga.draw.linear_base[ offset ]; // in case (vga.draw.line_length + offset) has bits set that
// are not set in the mask: ((x|y)!=y) equals (x&~y)
if (GCC_UNLIKELY((vga.draw.line_length + offset)& ~vga.draw.linear_mask)) {
// this happens, if at all, only once per frame (1 of 480 lines)
// in some obscure games
Bitu end = (offset + vga.draw.line_length) & vga.draw.linear_mask;
// assuming lines not longer than 4096 pixels
Bitu wrapped_len = end & 0xFFF;
Bitu unwrapped_len = vga.draw.line_length-wrapped_len;
// unwrapped chunk: to top of memory block
memcpy(TempLine, &vga.draw.linear_base[offset], unwrapped_len);
// wrapped chunk: from base of memory block
memcpy(&TempLine[unwrapped_len], vga.draw.linear_base, wrapped_len);
ret = TempLine;
}
#if !defined(C_UNALIGNED_MEMORY) #if !defined(C_UNALIGNED_MEMORY)
if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) {
memcpy( TempLine, ret, vga.draw.line_length ); memcpy( TempLine, ret, vga.draw.line_length );
@ -589,10 +605,60 @@ static void VGA_ProcessSplit() {
vga.draw.address_line=0; vga.draw.address_line=0;
} }
static Bit8u bg_color_index = 0; // screen-off black index
static void VGA_DrawSingleLine(Bitu /*blah*/) { static void VGA_DrawSingleLine(Bitu /*blah*/) {
if (GCC_UNLIKELY(vga.attr.disabled)) { if (GCC_UNLIKELY(vga.attr.disabled)) {
// draw blanked line (DoWhackaDo, Alien Carnage, TV sports Football) switch(machine) {
memset(TempLine, 0, sizeof(TempLine)); case MCH_PCJR:
// Displays the border color when screen is disabled
bg_color_index = vga.tandy.border_color;
break;
case MCH_TANDY:
// Either the PCJr way or the CGA way
if (vga.tandy.gfx_control& 0x4) {
bg_color_index = vga.tandy.border_color;
} else if (vga.mode==M_TANDY4)
bg_color_index = vga.attr.palette[0];
else bg_color_index = 0;
break;
case MCH_CGA:
// the background color
bg_color_index = vga.attr.overscan_color;
break;
case MCH_EGA:
case MCH_VGA:
// DoWhackaDo, Alien Carnage, TV sports Football
// when disabled by attribute index bit 5:
// ET3000, ET4000, Paradise display the border color
// S3 displays the content of the currently selected attribute register
// when disabled by sequencer the screen is black "257th color"
// the DAC table may not match the bits of the overscan register
// so use black for this case too...
//if (vga.attr.disabled& 2) {
if (vga.dac.xlat16[bg_color_index] != 0) {
for(Bitu i = 0; i < 256; i++)
if (vga.dac.xlat16[i] == 0) {
bg_color_index = i;
break;
}
}
//} else
// bg_color_index = vga.attr.overscan_color;
break;
default:
bg_color_index = 0;
break;
}
if (vga.draw.bpp==8) {
memset(TempLine, bg_color_index, sizeof(TempLine));
} else if (vga.draw.bpp==16) {
Bit16u* wptr = (Bit16u*) TempLine;
Bit16u value = vga.dac.xlat16[bg_color_index];
for (Bitu i = 0; i < sizeof(TempLine)/2; i++) {
wptr[i] = value;
}
}
RENDER_DrawLine(TempLine); RENDER_DrawLine(TempLine);
} else { } else {
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
@ -966,6 +1032,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
switch (machine) { switch (machine) {
case MCH_CGA: case MCH_CGA:
case MCH_PCJR: case MCH_PCJR:
case MCH_TANDY:
vga.draw.mode = LINE; vga.draw.mode = LINE;
break; break;
case MCH_EGA: case MCH_EGA:

View File

@ -153,6 +153,27 @@ static Bitu read_crtc_data_other(Bitu /*port*/,Bitu /*iolen*/) {
return (Bitu)(~0); return (Bitu)(~0);
} }
static void write_lightpen(Bitu port,Bitu val,Bitu) {
switch (port) {
case 0x3db: // Clear lightpen latch
vga.other.lightpen_triggered = false;
break;
case 0x3dc: // Preset lightpen latch
if (!vga.other.lightpen_triggered) {
vga.other.lightpen_triggered = true; // TODO: this shows at port 3ba/3da bit 1
double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
double timeInLine = fmod(timeInFrame,vga.draw.delay.htotal);
Bitu current_scanline = (Bitu)(timeInFrame / vga.draw.delay.htotal);
vga.other.lightpen = (Bit16u)((vga.draw.address_add/2) * (current_scanline/2));
vga.other.lightpen += (Bit16u)((timeInLine / vga.draw.delay.hdend) *
((float)(vga.draw.address_add/2)));
}
break;
}
}
static double hue_offset = 0.0; static double hue_offset = 0.0;
static Bit8u cga16_val = 0; static Bit8u cga16_val = 0;
static void update_cga16_color(void); static void update_cga16_color(void);
@ -235,56 +256,139 @@ static void DecreaseHue(bool pressed) {
LOG_MSG("Hue at %f",hue_offset); LOG_MSG("Hue at %f",hue_offset);
} }
static void write_color_select(Bit8u val) { static void write_cga_color_select(Bitu val) {
vga.tandy.color_select=val; vga.tandy.color_select=val;
switch (vga.mode) { switch(vga.mode) {
case M_TANDY4: {
Bit8u base = (val & 0x10) ? 0x08 : 0;
Bit8u bg = val & 0xf;
if (vga.tandy.mode_control & 0x4) // cyan red white
VGA_SetCGA4Table(bg, 3+base, 4+base, 7+base);
else if (val & 0x20) // cyan magenta white
VGA_SetCGA4Table(bg, 3+base, 5+base, 7+base);
else // green red brown
VGA_SetCGA4Table(bg, 2+base, 4+base, 6+base);
vga.tandy.border_color = bg;
vga.attr.overscan_color = bg;
break;
}
case M_TANDY2: case M_TANDY2:
VGA_SetCGA2Table(0,val & 0xf); VGA_SetCGA2Table(0,val & 0xf);
break; vga.attr.overscan_color = 0;
case M_TANDY4:
{
if ((machine==MCH_TANDY && (vga.tandy.gfx_control & 0x8)) ||
(machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) {
VGA_SetCGA4Table(0,1,2,3);
return;
}
Bit8u base=(val & 0x10) ? 0x08 : 0;
/* Check for BW Mode */
if (vga.tandy.mode_control & 0x4) {
VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base);
} else {
if (val & 0x20) VGA_SetCGA4Table(val & 0xf,3+base,5+base,7+base);
else VGA_SetCGA4Table(val & 0xf,2+base,4+base,6+base);
}
}
break; break;
case M_CGA16: case M_CGA16:
cga16_color_select(val); cga16_color_select(val);
break; break;
case M_TEXT: case M_TEXT:
case M_TANDY16: vga.tandy.border_color = val & 0xf;
vga.attr.overscan_color = 0;
break; break;
} }
} }
static void TANDY_FindMode(void) { static void write_cga(Bitu port,Bitu val,Bitu /*iolen*/) {
if (vga.tandy.mode_control & 0x2) { switch (port) {
if (vga.tandy.gfx_control & 0x10) case 0x3d8:
VGA_SetMode(M_TANDY16); vga.tandy.mode_control=(Bit8u)val;
else if (vga.tandy.gfx_control & 0x08) vga.attr.disabled = (val&0x8)? 0: 1;
VGA_SetMode(M_TANDY4); if (vga.tandy.mode_control & 0x2) { // graphics mode
else if (vga.tandy.mode_control & 0x10) if (vga.tandy.mode_control & 0x10) {// highres mode
VGA_SetMode(M_TANDY2); if (!(val & 0x4)) { // burst on
else VGA_SetMode(M_CGA16); // composite ntsc 160x200 16 color mode
VGA_SetMode(M_TANDY4); } else {
write_color_select(vga.tandy.color_select); VGA_SetMode(M_TANDY2);
}
} else VGA_SetMode(M_TANDY4); // lowres mode
write_cga_color_select(vga.tandy.color_select);
} else {
VGA_SetMode(M_TANDY_TEXT);
}
VGA_SetBlinking(val & 0x20);
break;
case 0x3d9: // color select
write_cga_color_select(val);
break;
}
}
static void tandy_update_palette() {
// TODO mask off bits if needed
if (machine == MCH_TANDY) {
switch (vga.mode) {
case M_TANDY2:
VGA_SetCGA2Table(vga.attr.palette[0],
//vga.attr.palette[vga.tandy.color_select&0xf]);
vga.attr.palette[0xf]);
//VGA_SetCGA2Table(vga.attr.palette[0xf],vga.attr.palette[0]);
break;
case M_TANDY4:
if (vga.tandy.gfx_control & 0x8) {
// 4-color high resolution - might be an idea to introduce M_TANDY4H
VGA_SetCGA4Table( // function sets both medium and highres 4color tables
vga.attr.palette[0], vga.attr.palette[1],
vga.attr.palette[2], vga.attr.palette[3]);
} else {
Bit8u color_set = 0;
Bit8u r_mask = 0xf;
if (vga.tandy.color_select & 0x10) color_set |= 8; // intensity
if (vga.tandy.color_select & 0x20) color_set |= 1; // Cyan Mag. White
if (vga.tandy.mode_control & 0x04) { // Cyan Red White
color_set |= 1;
r_mask &= ~1;
}
VGA_SetCGA4Table(
vga.attr.palette[0],
vga.attr.palette[(2|color_set)& vga.tandy.palette_mask],
vga.attr.palette[(4|(color_set& r_mask))& vga.tandy.palette_mask],
vga.attr.palette[(6|color_set)& vga.tandy.palette_mask]);
}
break;
default:
break;
}
} else { } else {
VGA_SetMode(M_TANDY_TEXT); // PCJr
switch (vga.mode) {
case M_TANDY2:
VGA_SetCGA2Table(vga.attr.palette[0],vga.attr.palette[1]);
break;
case M_TANDY4:
VGA_SetCGA4Table(
vga.attr.palette[0], vga.attr.palette[1],
vga.attr.palette[2], vga.attr.palette[3]);
break;
default:
break;
}
} }
} }
void VGA_SetModeNow(VGAModes mode); void VGA_SetModeNow(VGAModes mode);
static void TANDY_FindMode(void) {
if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.gfx_control & 0x10) {
if (vga.mode==M_TANDY4) {
VGA_SetModeNow(M_TANDY16);
} else VGA_SetMode(M_TANDY16);
}
else if (vga.tandy.gfx_control & 0x08) {
VGA_SetMode(M_TANDY4);
}
else if (vga.tandy.mode_control & 0x10)
VGA_SetMode(M_TANDY2);
else {
if (vga.mode==M_TANDY16) {
VGA_SetModeNow(M_TANDY4);
} else VGA_SetMode(M_TANDY4);
}
tandy_update_palette();
} else {
VGA_SetMode(M_TANDY_TEXT);
}
}
static void PCJr_FindMode(void) { static void PCJr_FindMode(void) {
if (vga.tandy.mode_control & 0x2) { if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.mode_control & 0x10) { if (vga.tandy.mode_control & 0x10) {
@ -299,7 +403,6 @@ static void PCJr_FindMode(void) {
if (vga.mode==M_TANDY16) VGA_SetModeNow(M_TANDY4); if (vga.mode==M_TANDY16) VGA_SetModeNow(M_TANDY4);
else VGA_SetMode(M_TANDY4); else VGA_SetMode(M_TANDY4);
} }
write_color_select(vga.tandy.color_select);
} else { } else {
VGA_SetMode(M_TANDY_TEXT); VGA_SetMode(M_TANDY_TEXT);
} }
@ -327,11 +430,16 @@ static void write_tandy_reg(Bit8u val) {
vga.tandy.mode_control=val; vga.tandy.mode_control=val;
VGA_SetBlinking(val & 0x20); VGA_SetBlinking(val & 0x20);
PCJr_FindMode(); PCJr_FindMode();
vga.attr.disabled = (val&0x8)? 0: 1; if (val&0x8) vga.attr.disabled &= ~1;
else vga.attr.disabled |= 1;
} else { } else {
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
} }
break; break;
case 0x1: /* Palette mask */
vga.tandy.palette_mask = val;
tandy_update_palette();
break;
case 0x2: /* Border color */ case 0x2: /* Border color */
vga.tandy.border_color=val; vga.tandy.border_color=val;
break; break;
@ -348,45 +456,12 @@ static void write_tandy_reg(Bit8u val) {
TandyCheckLineMask(); TandyCheckLineMask();
VGA_SetupHandlers(); VGA_SetupHandlers();
break; break;
case 0x8: /* Monitor mode seletion */ default:
//Bit 1 select mode e, for 640x200x16, some double clocking thing? if ((vga.tandy.reg_index & 0xf0) == 0x10) { // color palette
//Bit 4 select 350 line mode for hercules emulation vga.attr.palette[vga.tandy.reg_index-0x10] = val&0xf;
LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to tandy monitor mode",val ); tandy_update_palette();
break; } else
/* palette colors */ LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
VGA_ATTR_SetPalette(vga.tandy.reg_index-0x10,val & 0xf);
break;
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
}
}
static void write_cga(Bitu port,Bitu val,Bitu /*iolen*/) {
switch (port) {
case 0x3d8:
vga.tandy.mode_control=(Bit8u)val;
vga.attr.disabled = (val&0x8)? 0: 1;
if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.mode_control & 0x10) {
if (!(val & 0x4) && machine==MCH_CGA) {
VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode
} else {
VGA_SetMode(M_TANDY2);
}
} else VGA_SetMode(M_TANDY4);
write_color_select(vga.tandy.color_select);
} else {
VGA_SetMode(M_TANDY_TEXT);
}
VGA_SetBlinking(val & 0x20);
break;
case 0x3d9:
write_color_select((Bit8u)val);
break;
} }
} }
@ -394,40 +469,32 @@ static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
switch (port) { switch (port) {
case 0x3d8: case 0x3d8:
vga.tandy.mode_control=(Bit8u)val; vga.tandy.mode_control=(Bit8u)val;
if (val&0x8) vga.attr.disabled &= ~1;
else vga.attr.disabled |= 1;
TandyCheckLineMask(); TandyCheckLineMask();
VGA_SetBlinking(val & 0x20); VGA_SetBlinking(val & 0x20);
TANDY_FindMode(); TANDY_FindMode();
break; break;
case 0x3d9: case 0x3d9:
write_color_select((Bit8u)val); vga.tandy.color_select=val;
if (vga.mode==M_TANDY2) vga.attr.palette[0xf] = vga.tandy.color_select&0xf;
else vga.attr.palette[0] = vga.tandy.color_select&0xf; // Pirates!
tandy_update_palette();
break; break;
case 0x3da: case 0x3da:
vga.tandy.reg_index=(Bit8u)val; vga.tandy.reg_index=(Bit8u)val;
break; //if (val&0x10) vga.attr.disabled |= 2;
case 0x3db: // Clear lightpen latch //else vga.attr.disabled &= ~2;
vga.other.lightpen_triggered = false;
break;
case 0x3dc: // Preset lightpen latch
if (!vga.other.lightpen_triggered) {
vga.other.lightpen_triggered = true; // TODO: this shows at port 3ba/3da bit 1
double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
double timeInLine = fmod(timeInFrame,vga.draw.delay.htotal);
Bitu current_scanline = (Bitu)(timeInFrame / vga.draw.delay.htotal);
vga.other.lightpen = (Bit16u)((vga.draw.address_add/2) * (current_scanline/2));
vga.other.lightpen += (Bit16u)((timeInLine / vga.draw.delay.hdend) *
((float)(vga.draw.address_add/2)));
}
break; break;
// case 0x3dd: //Extended ram page address register: // case 0x3dd: //Extended ram page address register:
break; // break;
case 0x3de: case 0x3de:
write_tandy_reg((Bit8u)val); write_tandy_reg((Bit8u)val);
break; break;
case 0x3df: case 0x3df:
vga.tandy.line_mask = (Bit8u)(val >> 6); vga.tandy.line_mask = (Bit8u)(val >> 6);
vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
if(vga.tandy.line_mask==3) vga.tandy.draw_bank &= ~1; // LSB unused in 32k modes
vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
TandyCheckLineMask(); TandyCheckLineMask();
VGA_SetupHandlers(); VGA_SetupHandlers();
@ -437,12 +504,14 @@ static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
static void write_pcjr(Bitu port,Bitu val,Bitu /*iolen*/) { static void write_pcjr(Bitu port,Bitu val,Bitu /*iolen*/) {
switch (port) { switch (port) {
case 0x3d9:
write_color_select((Bit8u)val);
break;
case 0x3da: case 0x3da:
if (vga.tandy.pcjr_flipflop) write_tandy_reg((Bit8u)val); if (vga.tandy.pcjr_flipflop) write_tandy_reg((Bit8u)val);
else vga.tandy.reg_index=(Bit8u)val; else {
vga.tandy.reg_index=(Bit8u)val;
if (vga.tandy.reg_index & 0x10)
vga.attr.disabled |= 2;
else vga.attr.disabled &= ~2;
}
vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop; vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop;
break; break;
case 0x3df: case 0x3df:
@ -577,6 +646,10 @@ void VGA_SetupOther(void) {
for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8); for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8);
vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font; vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font;
} }
if (machine==MCH_CGA || IS_TANDY_ARCH || machine==MCH_HERC) {
IO_RegisterWriteHandler(0x3db,write_lightpen,IO_MB);
IO_RegisterWriteHandler(0x3dc,write_lightpen,IO_MB);
}
if (machine==MCH_HERC) { if (machine==MCH_HERC) {
extern Bit8u int10_font_14[256 * 14]; extern Bit8u int10_font_14[256 * 14];
for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_14[i*14],14); for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_14[i*14],14);
@ -586,8 +659,6 @@ void VGA_SetupOther(void) {
if (machine==MCH_CGA) { if (machine==MCH_CGA) {
IO_RegisterWriteHandler(0x3d8,write_cga,IO_MB); IO_RegisterWriteHandler(0x3d8,write_cga,IO_MB);
IO_RegisterWriteHandler(0x3d9,write_cga,IO_MB); IO_RegisterWriteHandler(0x3d9,write_cga,IO_MB);
IO_RegisterWriteHandler(0x3db,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3dc,write_tandy,IO_MB);
MAPPER_AddHandler(IncreaseHue,MK_f11,MMOD2,"inchue","Inc Hue"); MAPPER_AddHandler(IncreaseHue,MK_f11,MMOD2,"inchue","Inc Hue");
MAPPER_AddHandler(DecreaseHue,MK_f11,0,"dechue","Dec Hue"); MAPPER_AddHandler(DecreaseHue,MK_f11,0,"dechue","Dec Hue");
} }
@ -595,14 +666,13 @@ void VGA_SetupOther(void) {
write_tandy( 0x3df, 0x0, 0 ); write_tandy( 0x3df, 0x0, 0 );
IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3d9,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3d9,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3de,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3de,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3df,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3df,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB);
} }
if (machine==MCH_PCJR) { if (machine==MCH_PCJR) {
//write_pcjr will setup base address //write_pcjr will setup base address
write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 ); write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 );
IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB);
IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB);
IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB);
} }

View File

@ -434,18 +434,16 @@ static Bitu INT17_Handler(void) {
return CBRET_NONE; return CBRET_NONE;
} }
static Bit8u INT14_Wait(Bit16u port, Bit8u mask, Bit8u timeout) { static bool INT14_Wait(Bit16u port, Bit8u mask, Bit8u timeout, Bit8u* retval) {
double starttime = PIC_FullIndex(); double starttime = PIC_FullIndex();
double timeout_f = timeout * 1000.0; double timeout_f = timeout * 1000.0;
Bit8u retval; while (((*retval = IO_ReadB(port)) & mask) != mask) {
while (((retval = IO_ReadB(port)) & mask) != mask) {
if (starttime < (PIC_FullIndex() - timeout_f)) { if (starttime < (PIC_FullIndex() - timeout_f)) {
retval |= 0x80; return false;
break;
} }
CALLBACK_Idle(); CALLBACK_Idle();
} }
return retval; return true;
} }
static Bitu INT14_Handler(void) { static Bitu INT14_Handler(void) {
@ -500,7 +498,7 @@ static Bitu INT14_Handler(void) {
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
} }
case 0x01: { // Transmit character case 0x01: // Transmit character
// Parameters: Return: // Parameters: Return:
// AL: character AL: unchanged // AL: character AL: unchanged
// AH: 0x01 AH: line status from just before the char was sent // AH: 0x01 AH: line status from just before the char was sent
@ -510,20 +508,19 @@ static Bitu INT14_Handler(void) {
// set DTR & RTS on // set DTR & RTS on
IO_WriteB(port+4,0x3); IO_WriteB(port+4,0x3);
// wait for DSR & CTS // wait for DSR & CTS
reg_ah = INT14_Wait(port+6, 0x30, timeout); if (INT14_Wait(port+6, 0x30, timeout, &reg_ah)) {
if (!(reg_ah & 0x80)) {
// wait for TX buffer empty // wait for TX buffer empty
reg_ah = INT14_Wait(port+5, 0x20, timeout); if (INT14_Wait(port+5, 0x20, timeout, &reg_ah)) {
if (!(reg_ah & 0x80)) {
// fianlly send the character // fianlly send the character
IO_WriteB(port,reg_al); IO_WriteB(port,reg_al);
} } else
} // else timed out reg_ah |= 0x80;
} else // timed out
reg_ah |= 0x80;
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
}
case 0x02: // Read character case 0x02: // Read character
// Parameters: Return: // Parameters: Return:
// AH: 0x02 AL: received character // AH: 0x02 AL: received character
@ -537,15 +534,16 @@ static Bitu INT14_Handler(void) {
IO_WriteB(port+4,0x1); IO_WriteB(port+4,0x1);
// wait for DSR // wait for DSR
reg_ah = INT14_Wait(port+6, 0x20, timeout); if (INT14_Wait(port+6, 0x20, timeout, &reg_ah)) {
if (!(reg_ah & 0x80)) {
// wait for character to arrive // wait for character to arrive
reg_ah = INT14_Wait(port+5, 0x01, timeout); if (INT14_Wait(port+5, 0x01, timeout, &reg_ah)) {
if (!(reg_ah & 0x80)) {
reg_ah &= 0x1E; reg_ah &= 0x1E;
reg_al = IO_ReadB(port); reg_al = IO_ReadB(port);
} } else
} reg_ah |= 0x80;
} else
reg_ah |= 0x80;
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
case 0x03: // get status case 0x03: // get status

View File

@ -32,6 +32,7 @@
#include "setup.h" #include "setup.h"
#include "support.h" #include "support.h"
#include "cpu.h" #include "cpu.h"
#include "dma.h"
#define EMM_PAGEFRAME 0xE000 #define EMM_PAGEFRAME 0xE000
#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096) #define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096)
@ -88,6 +89,8 @@ struct EMM_Handle {
EMM_Mapping page_map[EMM_MAX_PHYS]; EMM_Mapping page_map[EMM_MAX_PHYS];
}; };
static Bitu ems_type;
static EMM_Handle emm_handles[EMM_MAX_HANDLES]; static EMM_Handle emm_handles[EMM_MAX_HANDLES];
static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
static EMM_Mapping emm_segmentmappings[0x40]; static EMM_Mapping emm_segmentmappings[0x40];
@ -97,7 +100,8 @@ static Bit16u GEMMIS_seg;
class device_EMM : public DOS_Device { class device_EMM : public DOS_Device {
public: public:
device_EMM() { device_EMM(bool is_emm386_avail) {
is_emm386=is_emm386_avail;
SetName("EMMXXXX0"); SetName("EMMXXXX0");
GEMMIS_seg=0; GEMMIS_seg=0;
} }
@ -108,11 +112,12 @@ public:
} }
bool Seek(Bit32u * /*pos*/,Bit32u /*type*/){return false;} bool Seek(Bit32u * /*pos*/,Bit32u /*type*/){return false;}
bool Close(){return false;} bool Close(){return false;}
Bit16u GetInformation(void){return 0xc080;} Bit16u GetInformation(void){return 0xc0c0;}
bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode);
bool WriteToControlChannel(PhysPt /*bufptr*/,Bit16u /*size*/,Bit16u * /*retcode*/){return true;} bool WriteToControlChannel(PhysPt /*bufptr*/,Bit16u /*size*/,Bit16u * /*retcode*/){return true;}
private: private:
Bit8u cache; Bit8u cache;
bool is_emm386;
}; };
bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) {
@ -125,6 +130,7 @@ bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retco
*retcode=6; *retcode=6;
return true; return true;
case 0x01: { case 0x01: {
if (!is_emm386) return false;
if (size!=6) return false; if (size!=6) return false;
if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20); if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20);
PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0); PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0);
@ -181,12 +187,14 @@ bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retco
return true; return true;
} }
case 0x02: case 0x02:
if (!is_emm386) return false;
if (size!=2) return false; if (size!=2) return false;
mem_writeb(bufptr+0x00,EMM_VERSION>>4); // version 4 mem_writeb(bufptr+0x00,EMM_VERSION>>4); // version 4
mem_writeb(bufptr+0x01,EMM_MINOR_VERSION); mem_writeb(bufptr+0x01,EMM_MINOR_VERSION);
*retcode=2; *retcode=2;
return true; return true;
case 0x03: case 0x03:
if (!is_emm386) return false;
if (EMM_MINOR_VERSION < 0x2d) return false; if (EMM_MINOR_VERSION < 0x2d) return false;
if (size!=4) return false; if (size!=4) return false;
mem_writew(bufptr+0x00,(Bit16u)(MEM_TotalPages()*4)); // max size (kb) mem_writew(bufptr+0x00,(Bit16u)(MEM_TotalPages()*4)); // max size (kb)
@ -323,7 +331,23 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
static Bit8u EMM_MapSegment(Bitu segment,Bit16u handle,Bit16u log_page) { static Bit8u EMM_MapSegment(Bitu segment,Bit16u handle,Bit16u log_page) {
// LOG_MSG("EMS MapSegment handle %d segment %d log %d",handle,segment,log_page); // LOG_MSG("EMS MapSegment handle %d segment %d log %d",handle,segment,log_page);
if (((segment>=0xa000) && (segment<0xb000)) || ((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME+0x1000))) { bool valid_segment=false;
if ((ems_type==1) || (ems_type==3)) {
if (segment<0xf000+0x1000) valid_segment=true;
} else {
if ((segment>=0xa000) && (segment<0xb000)) {
valid_segment=true; // allow mapping of graphics memory
}
if ((segment>=EMM_PAGEFRAME) && (segment<EMM_PAGEFRAME+0x1000)) {
valid_segment=true; // allow mapping of EMS page frame
}
/* if ((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME)) {
valid_segment=true;
} */
}
if (valid_segment) {
Bit32s tphysPage = ((Bit32s)segment-EMM_PAGEFRAME)/(0x1000/EMM_MAX_PHYS); Bit32s tphysPage = ((Bit32s)segment-EMM_PAGEFRAME)/(0x1000/EMM_MAX_PHYS);
/* unmapping doesn't need valid handle (as handle isn't used) */ /* unmapping doesn't need valid handle (as handle isn't used) */
@ -1262,9 +1286,25 @@ static Bitu INT4B_Handler() {
return CBRET_NONE; return CBRET_NONE;
} }
Bitu GetEMSType(Section_prop * section) {
Bitu rtype = 0;
std::string emstypestr(section->Get_string("ems"));
if (emstypestr=="true") {
rtype = 1; // mixed mode
} else if (emstypestr=="emsboard") {
rtype = 2;
} else if (emstypestr=="emm386") {
rtype = 3;
} else {
rtype = 0;
}
return rtype;
}
class EMS: public Module_base { class EMS: public Module_base {
private: private:
DOS_Device * emm_device;
/* location in protected unfreeable memory where the ems name and callback are /* location in protected unfreeable memory where the ems name and callback are
* stored 32 bytes.*/ * stored 32 bytes.*/
static Bit16u ems_baseseg; static Bit16u ems_baseseg;
@ -1273,7 +1313,9 @@ private:
Bitu call_int67; Bitu call_int67;
public: public:
EMS(Section* configuration):Module_base(configuration){ EMS(Section* configuration):Module_base(configuration) {
emm_device=NULL;
ems_type=0;
/* Virtual DMA interrupt callback */ /* Virtual DMA interrupt callback */
call_vdma.Install(&INT4B_Handler,CB_IRET,"Int 4b vdma"); call_vdma.Install(&INT4B_Handler,CB_IRET,"Int 4b vdma");
@ -1283,8 +1325,11 @@ public:
GEMMIS_seg=0; GEMMIS_seg=0;
Section_prop * section=static_cast<Section_prop *>(configuration); Section_prop * section=static_cast<Section_prop *>(configuration);
if (!section->Get_bool("ems")) return; ems_type=GetEMSType(section);
if (ems_type<=0) return;
if (machine==MCH_PCJR) { if (machine==MCH_PCJR) {
ems_type=0;
LOG_MSG("EMS disabled for PCJr machine"); LOG_MSG("EMS disabled for PCJr machine");
return; return;
} }
@ -1302,8 +1347,8 @@ public:
/* Register the ems device */ /* Register the ems device */
//TODO MAYBE put it in the class. //TODO MAYBE put it in the class.
DOS_Device * newdev = new device_EMM(); emm_device = new device_EMM(ems_type!=2);
DOS_AddDevice(newdev); DOS_AddDevice(emm_device);
/* Clear handle and page tables */ /* Clear handle and page tables */
Bitu i; Bitu i;
@ -1323,61 +1368,67 @@ public:
EMM_AllocateSystemHandle(8); // allocate OS-dedicated handle (ems handle zero, 128kb) EMM_AllocateSystemHandle(8); // allocate OS-dedicated handle (ems handle zero, 128kb)
if (ems_type==3) {
DMA_SetWrapping(0xffffffff); // emm386-bug that disables dma wrapping
}
if (!ENABLE_VCPI) return; if (!ENABLE_VCPI) return;
/* Install a callback that handles VCPI-requests in protected mode requests */ if (ems_type!=2) {
call_vcpi.Install(&VCPI_PM_Handler,CB_IRETD,"VCPI PM"); /* Install a callback that handles VCPI-requests in protected mode requests */
vcpi.pm_interface=(call_vcpi.Get_callback())*CB_SIZE; call_vcpi.Install(&VCPI_PM_Handler,CB_IRETD,"VCPI PM");
vcpi.pm_interface=(call_vcpi.Get_callback())*CB_SIZE;
/* Initialize private data area and set up descriptor tables */ /* Initialize private data area and set up descriptor tables */
SetupVCPI(); SetupVCPI();
if (!vcpi.enabled) return; if (!vcpi.enabled) return;
/* Install v86-callback that handles interrupts occuring /* Install v86-callback that handles interrupts occuring
in v86 mode, including protection fault exceptions */ in v86 mode, including protection fault exceptions */
call_v86mon.Install(&V86_Monitor,CB_IRET,"V86 Monitor"); call_v86mon.Install(&V86_Monitor,CB_IRET,"V86 Monitor");
mem_writeb(vcpi.private_area+0x2e00,(Bit8u)0xFE); //GRP 4 mem_writeb(vcpi.private_area+0x2e00,(Bit8u)0xFE); //GRP 4
mem_writeb(vcpi.private_area+0x2e01,(Bit8u)0x38); //Extra Callback instruction mem_writeb(vcpi.private_area+0x2e01,(Bit8u)0x38); //Extra Callback instruction
mem_writew(vcpi.private_area+0x2e02,call_v86mon.Get_callback()); //The immediate word mem_writew(vcpi.private_area+0x2e02,call_v86mon.Get_callback()); //The immediate word
mem_writeb(vcpi.private_area+0x2e04,(Bit8u)0x66); mem_writeb(vcpi.private_area+0x2e04,(Bit8u)0x66);
mem_writeb(vcpi.private_area+0x2e05,(Bit8u)0xCF); //A IRETD Instruction mem_writeb(vcpi.private_area+0x2e05,(Bit8u)0xCF); //A IRETD Instruction
/* Testcode only, starts up dosbox in v86-mode */ /* Testcode only, starts up dosbox in v86-mode */
if (ENABLE_V86_STARTUP) { if (ENABLE_V86_STARTUP) {
/* Prepare V86-task */ /* Prepare V86-task */
CPU_SET_CRX(0, 1); CPU_SET_CRX(0, 1);
CPU_LGDT(0xff, vcpi.private_area+0x0000); CPU_LGDT(0xff, vcpi.private_area+0x0000);
CPU_LIDT(0x7ff, vcpi.private_area+0x2000); CPU_LIDT(0x7ff, vcpi.private_area+0x2000);
if (CPU_LLDT(0x08)) LOG_MSG("VCPI:Could not load LDT"); if (CPU_LLDT(0x08)) LOG_MSG("VCPI:Could not load LDT");
if (CPU_LTR(0x10)) LOG_MSG("VCPI:Could not load TR"); if (CPU_LTR(0x10)) LOG_MSG("VCPI:Could not load TR");
CPU_Push32(SegValue(gs)); CPU_Push32(SegValue(gs));
CPU_Push32(SegValue(fs)); CPU_Push32(SegValue(fs));
CPU_Push32(SegValue(ds)); CPU_Push32(SegValue(ds));
CPU_Push32(SegValue(es)); CPU_Push32(SegValue(es));
CPU_Push32(SegValue(ss)); CPU_Push32(SegValue(ss));
CPU_Push32(0x23002); CPU_Push32(0x23002);
CPU_Push32(SegValue(cs)); CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip&0xffff); CPU_Push32(reg_eip&0xffff);
/* Switch to V86-mode */ /* Switch to V86-mode */
cpu.cpl=0; cpu.cpl=0;
CPU_IRET(true,0); CPU_IRET(true,0);
}
} }
} }
~EMS() { ~EMS() {
Section_prop * section=static_cast<Section_prop *>(m_configuration); if (ems_type<=0) return;
if (!section->Get_bool("ems")) return;
/* Undo Biosclearing */ /* Undo Biosclearing */
BIOS_ZeroExtendedSize(false); BIOS_ZeroExtendedSize(false);
/* Remove ems device */ /* Remove ems device */
device_EMM newdev; if (emm_device!=NULL) {
DOS_DelDevice(&newdev); DOS_DelDevice(emm_device);
emm_device=NULL;
}
GEMMIS_seg=0; GEMMIS_seg=0;
/* Remove the emsname and callback hack */ /* Remove the emsname and callback hack */

View File

@ -107,7 +107,9 @@ static Bitu INT10_Handler(void) {
INT10_ReadCharAttr(&reg_ax,reg_bh); INT10_ReadCharAttr(&reg_ax,reg_bh);
break; break;
case 0x09: /* Write Character & Attribute at cursor CX times */ case 0x09: /* Write Character & Attribute at cursor CX times */
INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,true); if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)==0x11)
INT10_WriteChar(reg_al,(reg_bl&0x80)|0x3f,reg_bh,reg_cx,true);
else INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,true);
break; break;
case 0x0A: /* Write Character at cursor CX times */ case 0x0A: /* Write Character at cursor CX times */
INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false); INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false);
@ -138,7 +140,8 @@ static Bitu INT10_Handler(void) {
reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
break; break;
case 0x10: /* Palette functions */ case 0x10: /* Palette functions */
if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x03))) break; if (!IS_EGAVGA_ARCH && (reg_al>0x02)) break;
else if (!IS_VGA_ARCH && (reg_al>0x03)) break;
switch (reg_al) { switch (reg_al) {
case 0x00: /* SET SINGLE PALETTE REGISTER */ case 0x00: /* SET SINGLE PALETTE REGISTER */
INT10_SetSinglePaletteRegister(reg_bl,reg_bh); INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
@ -162,7 +165,7 @@ static Bitu INT10_Handler(void) {
INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx); INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx);
break; break;
case 0x10: /* SET INDIVIDUAL DAC REGISTER */ case 0x10: /* SET INDIVIDUAL DAC REGISTER */
INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl); INT10_SetSingleDACRegister(reg_bl,reg_dh,reg_ch,reg_cl);
break; break;
case 0x12: /* SET BLOCK OF DAC REGISTERS */ case 0x12: /* SET BLOCK OF DAC REGISTERS */
INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
@ -171,7 +174,7 @@ static Bitu INT10_Handler(void) {
INT10_SelectDACPage(reg_bl,reg_bh); INT10_SelectDACPage(reg_bl,reg_bh);
break; break;
case 0x15: /* GET INDIVIDUAL DAC REGISTER */ case 0x15: /* GET INDIVIDUAL DAC REGISTER */
INT10_GetSingleDacRegister(reg_bl,&reg_dh,&reg_ch,&reg_cl); INT10_GetSingleDACRegister(reg_bl,&reg_dh,&reg_ch,&reg_cl);
break; break;
case 0x17: /* GET BLOCK OF DAC REGISTER */ case 0x17: /* GET BLOCK OF DAC REGISTER */
INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
@ -208,11 +211,11 @@ static Bitu INT10_Handler(void) {
break; break;
case 0x01: /* Load 8x14 font */ case 0x01: /* Load 8x14 font */
case 0x11: case 0x11:
INT10_LoadFont(Real2Phys(int10.rom.font_14),reg_al==0x11,256,0,0,14); INT10_LoadFont(Real2Phys(int10.rom.font_14),reg_al==0x11,256,0,reg_bl,14);
break; break;
case 0x02: /* Load 8x8 font */ case 0x02: /* Load 8x8 font */
case 0x12: case 0x12:
INT10_LoadFont(Real2Phys(int10.rom.font_8_first),reg_al==0x12,256,0,0,8); INT10_LoadFont(Real2Phys(int10.rom.font_8_first),reg_al==0x12,256,0,reg_bl,8);
break; break;
case 0x03: /* Set Block Specifier */ case 0x03: /* Set Block Specifier */
IO_Write(0x3c4,0x3);IO_Write(0x3c5,reg_bl); IO_Write(0x3c4,0x3);IO_Write(0x3c5,reg_bl);
@ -220,7 +223,7 @@ static Bitu INT10_Handler(void) {
case 0x04: /* Load 8x16 font */ case 0x04: /* Load 8x16 font */
case 0x14: case 0x14:
if (!IS_VGA_ARCH) break; if (!IS_VGA_ARCH) break;
INT10_LoadFont(Real2Phys(int10.rom.font_16),reg_al==0x14,256,0,0,16); INT10_LoadFont(Real2Phys(int10.rom.font_16),reg_al==0x14,256,0,reg_bl,16);
break; break;
/* Graphics mode calls */ /* Graphics mode calls */
case 0x20: /* Set User 8x8 Graphics characters */ case 0x20: /* Set User 8x8 Graphics characters */

View File

@ -187,8 +187,8 @@ void INT10_ToggleBlinkingBit(Bit8u state);
void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val); void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val);
void INT10_GetOverscanBorderColor(Bit8u * val); void INT10_GetOverscanBorderColor(Bit8u * val);
void INT10_GetAllPaletteRegisters(PhysPt data); void INT10_GetAllPaletteRegisters(PhysPt data);
void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue); void INT10_SetSingleDACRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue);
void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue); void INT10_GetSingleDACRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue);
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data); void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data);
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data); void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data);
void INT10_SelectDACPage(Bit8u function,Bit8u mode); void INT10_SelectDACPage(Bit8u function,Bit8u mode);

View File

@ -246,6 +246,7 @@ VideoModeBlock ModeList_OTHER[]={
{ 0x008 ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,56 ,127 ,40 ,100 ,0 }, { 0x008 ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,56 ,127 ,40 ,100 ,0 },
{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 }, { 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
{ 0x00A ,M_CGA4 ,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 }, { 0x00A ,M_CGA4 ,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
//{ 0x00E ,M_TANDY16,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xA0000 ,0x10000 ,113 ,256 ,80 ,200 ,0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
}; };
@ -547,6 +548,11 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
default: default:
IO_WriteB(0x3de,0x0);break; IO_WriteB(0x3de,0x0);break;
} }
// write palette
for(Bitu i = 0; i < 16; i++) {
IO_WriteB(0x3da,i+0x10);
IO_WriteB(0x3de,i);
}
//Clear extended mapping //Clear extended mapping
IO_WriteB(0x3da,0x5); IO_WriteB(0x3da,0x5);
IO_WriteB(0x3de,0x0); IO_WriteB(0x3de,0x0);
@ -587,8 +593,9 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f; if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
else color_select=0x30; else color_select=0x30;
IO_WriteB(0x3d9,color_select);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
INT10_SetColorSelect(1);
INT10_SetBackgroundBorder(0);
break; break;
} }

View File

@ -35,9 +35,44 @@ static INLINE void WriteTandyACTL(Bit8u creg,Bit8u val) {
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) { void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) {
switch (machine) { switch (machine) {
case TANDY_ARCH_CASE: case MCH_PCJR:
reg&=0xf;
IO_Read(VGAREG_TDY_RESET); IO_Read(VGAREG_TDY_RESET);
WriteTandyACTL(reg+0x10,val); WriteTandyACTL(reg+0x10,val);
IO_Write(0x3da,0x0); // palette back on
break;
case MCH_TANDY:
// TODO waits for vertical retrace
switch(vga.mode) {
case M_TANDY2:
if (reg >= 0x10) break;
else if (reg==1) reg = 0x1f;
else reg |= 0x10;
WriteTandyACTL(reg+0x10,val);
break;
case M_TANDY4: {
if (CurMode->mode!=0x0a) {
// Palette values are kept constand by the BIOS.
// The four colors are mapped to special palette values by hardware.
// 3D8/3D9 registers influence this mapping. We need to figure out
// which entry is used for the requested color.
if (reg > 3) break;
if (reg != 0) { // 0 is assumed to be at 0
Bit8u color_select=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
reg = reg*2+8; // Green Red Brown
if (color_select& 0x20) reg++; // Cyan Magenta White
}
WriteTandyACTL(reg+0x10,val);
}
// 4-color high resolution mode 0x0a isn't handled specially
else WriteTandyACTL(reg+0x10,val);
break;
}
default:
WriteTandyACTL(reg+0x10,val);
break;
}
IO_Write(0x3da,0x0); // palette back on
break; break;
case EGAVGA_ARCH_CASE: case EGAVGA_ARCH_CASE:
if (!IS_VGA_ARCH) reg&=0x1f; if (!IS_VGA_ARCH) reg&=0x1f;
@ -168,14 +203,23 @@ void INT10_GetAllPaletteRegisters(PhysPt data) {
ResetACTL(); ResetACTL();
} }
void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue) { void INT10_SetSingleDACRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue) {
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
IO_Write(VGAREG_DAC_DATA,red); if ((real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x06)==0) {
IO_Write(VGAREG_DAC_DATA,green); IO_Write(VGAREG_DAC_DATA,red);
IO_Write(VGAREG_DAC_DATA,blue); IO_Write(VGAREG_DAC_DATA,green);
IO_Write(VGAREG_DAC_DATA,blue);
} else {
/* calculate clamped intensity, taken from VGABIOS */
Bit32u i=(( 77*red + 151*green + 28*blue ) + 0x80) >> 8;
Bit8u ic=(i>0x3f) ? 0x3f : ((Bit8u)(i & 0xff));
IO_Write(VGAREG_DAC_DATA,ic);
IO_Write(VGAREG_DAC_DATA,ic);
IO_Write(VGAREG_DAC_DATA,ic);
}
} }
void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue) { void INT10_GetSingleDACRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue) {
IO_Write(VGAREG_DAC_READ_ADDRESS,index); IO_Write(VGAREG_DAC_READ_ADDRESS,index);
*red=IO_Read(VGAREG_DAC_DATA); *red=IO_Read(VGAREG_DAC_DATA);
*green=IO_Read(VGAREG_DAC_DATA); *green=IO_Read(VGAREG_DAC_DATA);
@ -184,10 +228,25 @@ void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * bl
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) { void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
for (;count>0;count--) { if ((real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x06)==0) {
IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); for (;count>0;count--) {
IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); IO_Write(VGAREG_DAC_DATA,mem_readb(data++));
IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); IO_Write(VGAREG_DAC_DATA,mem_readb(data++));
IO_Write(VGAREG_DAC_DATA,mem_readb(data++));
}
} else {
for (;count>0;count--) {
Bit8u red=mem_readb(data++);
Bit8u green=mem_readb(data++);
Bit8u blue=mem_readb(data++);
/* calculate clamped intensity, taken from VGABIOS */
Bit32u i=(( 77*red + 151*green + 28*blue ) + 0x80) >> 8;
Bit8u ic=(i>0x3f) ? 0x3f : ((Bit8u)(i & 0xff));
IO_Write(VGAREG_DAC_DATA,ic);
IO_Write(VGAREG_DAC_DATA,ic);
IO_Write(VGAREG_DAC_DATA,ic);
}
} }
} }
@ -242,14 +301,24 @@ void INT10_SetPelMask(Bit8u mask) {
void INT10_GetPelMask(Bit8u & mask) { void INT10_GetPelMask(Bit8u & mask) {
mask=IO_Read(VGAREG_PEL_MASK); mask=IO_Read(VGAREG_PEL_MASK);
} }
void INT10_SetBackgroundBorder(Bit8u val) { void INT10_SetBackgroundBorder(Bit8u val) {
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); Bit8u color_select=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
temp=(temp & 0xe0) | (val & 0x1f); color_select=(color_select & 0xe0) | (val & 0x1f);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
if (machine == MCH_CGA || IS_TANDY_ARCH)
IO_Write(0x3d9,temp); if (machine == MCH_CGA || machine == MCH_TANDY)
IO_Write(0x3d9,color_select);
else if (machine == MCH_PCJR) {
IO_Read(VGAREG_TDY_RESET); // reset the flipflop
if (vga.mode!=M_TANDY_TEXT) {
IO_Write(VGAREG_TDY_ADDRESS, 0x10);
IO_Write(VGAREG_PCJR_DATA, color_select&0xf);
}
IO_Write(VGAREG_TDY_ADDRESS, 0x2); // border color
IO_Write(VGAREG_PCJR_DATA, color_select&0xf);
}
else if (IS_EGAVGA_ARCH) { else if (IS_EGAVGA_ARCH) {
val = ((val << 1) & 0x10) | (val & 0x7); val = ((val << 1) & 0x10) | (val & 0x7);
/* Aways set the overscan color */ /* Aways set the overscan color */
@ -258,7 +327,7 @@ void INT10_SetBackgroundBorder(Bit8u val) {
if (CurMode->mode <= 3) if (CurMode->mode <= 3)
return; return;
INT10_SetSinglePaletteRegister( 0, val ); INT10_SetSinglePaletteRegister( 0, val );
val = (temp & 0x10) | 2 | ((temp & 0x20) >> 5); val = (color_select & 0x10) | 2 | ((color_select & 0x20) >> 5);
INT10_SetSinglePaletteRegister( 1, val ); INT10_SetSinglePaletteRegister( 1, val );
val+=2; val+=2;
INT10_SetSinglePaletteRegister( 2, val ); INT10_SetSinglePaletteRegister( 2, val );
@ -271,8 +340,31 @@ void INT10_SetColorSelect(Bit8u val) {
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0); temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp);
if (machine == MCH_CGA || IS_TANDY_ARCH) if (machine == MCH_CGA || machine==MCH_TANDY)
IO_Write(0x3d9,temp); IO_Write(0x3d9,temp);
else if (machine == MCH_PCJR) {
switch(vga.mode) {
case M_TANDY2:
IO_Write(VGAREG_TDY_ADDRESS, 0x11);
IO_Write(VGAREG_PCJR_DATA, val&1? 0xf:0);
break;
case M_TANDY4:
for(Bit8u i = 0x11; i < 0x14; i++) {
const Bit8u t4_table[] = {0,2,4,6, 0,3,5,0xf};
IO_Write(VGAREG_TDY_ADDRESS, i);
IO_Write(VGAREG_PCJR_DATA, t4_table[(i-0x10)+(val&1? 4:0)]);
}
break;
default:
// 16-color modes: always write the same palette
for(Bit8u i = 0x11; i < 0x20; i++) {
IO_Write(VGAREG_TDY_ADDRESS, i);
IO_Write(VGAREG_PCJR_DATA, i-0x10);
}
break;
}
IO_Write(VGAREG_TDY_ADDRESS, 0); // enable palette
}
else if (IS_EGAVGA_ARCH) { else if (IS_EGAVGA_ARCH) {
if (CurMode->mode <= 3) //Maybe even skip the total function! if (CurMode->mode <= 3) //Maybe even skip the total function!
return; return;
@ -296,6 +388,6 @@ void INT10_PerformGrayScaleSumming(Bit16u start_reg,Bit16u count) {
/* calculate clamped intensity, taken from VGABIOS */ /* calculate clamped intensity, taken from VGABIOS */
Bit32u i=(( 77*red + 151*green + 28*blue ) + 0x80) >> 8; Bit32u i=(( 77*red + 151*green + 28*blue ) + 0x80) >> 8;
Bit8u ic=(i>0x3f) ? 0x3f : ((Bit8u)(i & 0xff)); Bit8u ic=(i>0x3f) ? 0x3f : ((Bit8u)(i & 0xff));
INT10_SetSingleDacRegister(start_reg+ct,ic,ic,ic); INT10_SetSingleDACRegister(start_reg+ct,ic,ic,ic);
} }
} }

View File

@ -412,6 +412,8 @@ Bitu XMS_Handler(void) {
return CBRET_NONE; return CBRET_NONE;
} }
Bitu GetEMSType(Section_prop * section);
class XMS: public Module_base { class XMS: public Module_base {
private: private:
CALLBACK_HandlerObject callbackhandler; CALLBACK_HandlerObject callbackhandler;
@ -445,7 +447,8 @@ public:
/* Set up UMB chain */ /* Set up UMB chain */
umb_available=section->Get_bool("umb"); umb_available=section->Get_bool("umb");
DOS_BuildUMBChain(section->Get_bool("umb"),section->Get_bool("ems")); bool ems_available = GetEMSType(section)>0;
DOS_BuildUMBChain(section->Get_bool("umb"),ems_available);
} }
~XMS(){ ~XMS(){