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
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
(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
@ -185,7 +185,7 @@ START: How to start?
AUTOMATION: Do I always have to type these 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
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?
@ -313,11 +313,12 @@ SOUND: What sound hardware does DOSBox presently emulate?
SOUND: The sound stutters or sounds stretched/weird.
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
the respective sound device, increase the prebuffer. See section 13: "The
configuration (options) file"
If you are using cycles=max or =auto, then make sure that there is no
background processes interfering! (especially if they access the harddisk)
Also look at Section 10. "How to speed up/slow down DOSBox"
the respective sound device, increase the prebuffer. See Section 13: "The
configuration (options) file".
If you are using 'cycles=max' or 'cycles=auto', then make sure that there is
no background processes interfering! (especially if they access the harddisk)
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.
@ -326,7 +327,7 @@ KEYBOARD: I can't type \ or : in DOSBox.
detected), or the key mapping is wrong.
Some possible fixes:
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
of the DOSBox configuration file.
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!
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.
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!.
Look at Section 11: Troubleshooting
Look at Section 11: "Troubleshooting".
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.
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.
@ -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
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:
(Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe
@ -461,11 +462,11 @@ dosbox -erasemapper
-conf configfilelocation
Start DOSBox with the options specified in "configfilelocation".
Multiple -conf options may be present.
See Section 13 for more details.
See Section 13: "The configuration (options) file" for more details.
-lang 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
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
2. To set the cpu cycles to 10000:
config -set "cpu cycles=10000"
3. To turn ems memory emulation off:
config -set "dos ems=off"
3. To turn EMS memory emulation off:
config -set "dos ems=false"
4. To check which cpu core is being used.
config -get "cpu core"
@ -1015,7 +1016,7 @@ IPX
KEYB [keyboardlayoutcode [codepage [codepagefile]]]
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,
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.
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
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:
=============
You start the DOSBox mapper either with CTRL-F1 (see section 5. Special Keys)
or -startmapper (see Section 3. Command Line Parameters).
You start the DOSBox mapper either with CTRL-F1 (see Section 5: "Special Keys")
or -startmapper (see Section 3: "Command Line Parameters").
You are presented with a virtual keyboard and a virtual joystick.
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"
in the [dos] section of the DOSBox configuration file can be used, or the
internal DOSBox program keyb.com (Section 4: Internal Programs)
Both accept DOS conforming language codes (see below),
but only by using keyb.com a custom codepage can be specified.
internal DOSBox program keyb.com (Section 4: "Internal Programs"). Both accept
DOS conforming language codes (see below), but only by using keyb.com a
custom codepage can be specified.
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.
@ -1357,8 +1358,8 @@ CPU Cycles (speed up/slow down)
a different setting in the DOSBox's configuration file.
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
DOSBox window will display a line "Cpu Speed: fixed 10000 cycles" at the top.
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.
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
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
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
how much free time your real CPU's cores have, because DOSBox will always use
"CPU speed: max 100% cycles" at the top then. This time you won't have to care
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
of your real CPU's core usage by CTRL-F11 or raise it with CTRL-F12.
@ -1424,7 +1425,7 @@ Example:
====================
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:
- use different values for the output= entry in your DOSBox

View File

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

View File

@ -681,8 +681,13 @@ void DOSBOX_Init(void) {
Pbool->Set_help("Enable XMS support.");
secprop->AddInitFunction(&EMS_Init,true);//done
Pbool = secprop->Add_bool("ems",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Enable EMS support.");
const char* ems_settings[] = { "true", "emsboard", "emm386", "false", 0};
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->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(frameskip != -1) internal_frameskip = frameskip;
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 {
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");

View File

@ -48,7 +48,9 @@ static void DMA_BlockRead(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8u
offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
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;
Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */
@ -67,7 +69,9 @@ static void DMA_BlockWrite(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8
offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
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;
Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */

View File

@ -16,7 +16,7 @@
* 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 <stdlib.h>
@ -161,13 +161,17 @@ static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit3
#endif
#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];
Bitu main_list;
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 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;
@ -284,20 +288,6 @@ static void CAPTURE_VideoHeader() {
fwrite( capture.video.index, 1, capture.video.indexused, capture.video.handle);
fseek(capture.video.handle, 0, SEEK_SET);
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 );
free( capture.video.index );
free( capture.video.buf );
@ -557,9 +547,6 @@ skip_shot:
capture.video.audioused = 0;
}
/* Adds AVI header to the file */
CAPTURE_VideoHeader();
/* Everything went okay, set flag again for next frame */
CaptureState |= CAPTURE_VIDEO;
}
@ -756,6 +743,9 @@ public:
#endif
}
~HARDWARE(){
#if (C_SSHOT)
if (capture.video.handle) CAPTURE_VideoEvent(true);
#endif
if (capture.wave.handle) CAPTURE_WaveEvent(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) {
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
Bit32u * draw=(Bit32u *)TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val1 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
Bitu val2 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
*draw++=(val1 & 0x0f) << 8 |
(val1 & 0xf0) >> 4 |
(val2 & 0x0f) << 24 |
(val2 & 0xf0) << 12;
Bit8u* draw=TempLine;
Bitu end = vga.draw.blocks*2;
while(end) {
Bit8u byte = base[vidstart & vga.tandy.addr_mask];
*draw++=vga.attr.palette[byte >> 4];
*draw++=vga.attr.palette[byte & 0x0f];
vidstart++;
end--;
}
return TempLine;
}
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);
Bit32u * draw=(Bit32u *)TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val = base[vidstart & vga.tandy.addr_mask];
++vidstart;
*draw++=(val & 0xf0) >> 4 |
(val & 0xf0) << 4 |
(val & 0x0f) << 16 |
(val & 0x0f) << 24;
Bit8u* draw=TempLine;
Bitu end = vga.draw.blocks;
while(end) {
Bit8u byte = base[vidstart & vga.tandy.addr_mask];
Bit8u data = vga.attr.palette[byte >> 4];
*draw++ = data; *draw++ = data;
data = vga.attr.palette[byte & 0x0f];
*draw++ = data; *draw++ = data;
vidstart++;
end--;
}
return TempLine;
}
@ -175,12 +175,28 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) {
#endif
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;
if (vga.draw.linear_mask-offset < vga.draw.line_length)
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 ];
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 (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) {
memcpy( TempLine, ret, vga.draw.line_length );
@ -589,10 +605,60 @@ static void VGA_ProcessSplit() {
vga.draw.address_line=0;
}
static Bit8u bg_color_index = 0; // screen-off black index
static void VGA_DrawSingleLine(Bitu /*blah*/) {
if (GCC_UNLIKELY(vga.attr.disabled)) {
// draw blanked line (DoWhackaDo, Alien Carnage, TV sports Football)
memset(TempLine, 0, sizeof(TempLine));
switch(machine) {
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);
} else {
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
@ -966,6 +1032,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
switch (machine) {
case MCH_CGA:
case MCH_PCJR:
case MCH_TANDY:
vga.draw.mode = LINE;
break;
case MCH_EGA:

View File

@ -153,6 +153,27 @@ static Bitu read_crtc_data_other(Bitu /*port*/,Bitu /*iolen*/) {
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 Bit8u cga16_val = 0;
static void update_cga16_color(void);
@ -235,56 +256,139 @@ static void DecreaseHue(bool pressed) {
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;
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:
VGA_SetCGA2Table(0,val & 0xf);
break;
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);
}
}
vga.attr.overscan_color = 0;
break;
case M_CGA16:
cga16_color_select(val);
break;
case M_TEXT:
case M_TANDY16:
vga.tandy.border_color = val & 0xf;
vga.attr.overscan_color = 0;
break;
}
}
static void TANDY_FindMode(void) {
if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.gfx_control & 0x10)
VGA_SetMode(M_TANDY16);
else if (vga.tandy.gfx_control & 0x08)
VGA_SetMode(M_TANDY4);
else if (vga.tandy.mode_control & 0x10)
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) { // graphics mode
if (vga.tandy.mode_control & 0x10) {// highres mode
if (!(val & 0x4)) { // burst on
VGA_SetMode(M_CGA16); // composite ntsc 160x200 16 color mode
} else {
VGA_SetMode(M_TANDY2);
else
VGA_SetMode(M_TANDY4);
write_color_select(vga.tandy.color_select);
}
} 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 {
// 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);
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) {
if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.mode_control & 0x10) {
@ -299,7 +403,6 @@ static void PCJr_FindMode(void) {
if (vga.mode==M_TANDY16) VGA_SetModeNow(M_TANDY4);
else VGA_SetMode(M_TANDY4);
}
write_color_select(vga.tandy.color_select);
} else {
VGA_SetMode(M_TANDY_TEXT);
}
@ -327,11 +430,16 @@ static void write_tandy_reg(Bit8u val) {
vga.tandy.mode_control=val;
VGA_SetBlinking(val & 0x20);
PCJr_FindMode();
vga.attr.disabled = (val&0x8)? 0: 1;
if (val&0x8) vga.attr.disabled &= ~1;
else vga.attr.disabled |= 1;
} else {
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
}
break;
case 0x1: /* Palette mask */
vga.tandy.palette_mask = val;
tandy_update_palette();
break;
case 0x2: /* Border color */
vga.tandy.border_color=val;
break;
@ -348,86 +456,45 @@ static void write_tandy_reg(Bit8u val) {
TandyCheckLineMask();
VGA_SetupHandlers();
break;
case 0x8: /* Monitor mode seletion */
//Bit 1 select mode e, for 640x200x16, some double clocking thing?
//Bit 4 select 350 line mode for hercules emulation
LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to tandy monitor mode",val );
break;
/* palette colors */
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:
if ((vga.tandy.reg_index & 0xf0) == 0x10) { // color palette
vga.attr.palette[vga.tandy.reg_index-0x10] = val&0xf;
tandy_update_palette();
} else
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;
}
}
static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
switch (port) {
case 0x3d8:
vga.tandy.mode_control=(Bit8u)val;
if (val&0x8) vga.attr.disabled &= ~1;
else vga.attr.disabled |= 1;
TandyCheckLineMask();
VGA_SetBlinking(val & 0x20);
TANDY_FindMode();
break;
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;
case 0x3da:
vga.tandy.reg_index=(Bit8u)val;
break;
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)));
}
//if (val&0x10) vga.attr.disabled |= 2;
//else vga.attr.disabled &= ~2;
break;
// case 0x3dd: //Extended ram page address register:
break;
// break;
case 0x3de:
write_tandy_reg((Bit8u)val);
break;
case 0x3df:
vga.tandy.line_mask = (Bit8u)(val >> 6);
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);
TandyCheckLineMask();
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*/) {
switch (port) {
case 0x3d9:
write_color_select((Bit8u)val);
break;
case 0x3da:
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;
break;
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);
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) {
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);
@ -586,8 +659,6 @@ void VGA_SetupOther(void) {
if (machine==MCH_CGA) {
IO_RegisterWriteHandler(0x3d8,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(DecreaseHue,MK_f11,0,"dechue","Dec Hue");
}
@ -595,14 +666,13 @@ void VGA_SetupOther(void) {
write_tandy( 0x3df, 0x0, 0 );
IO_RegisterWriteHandler(0x3d8,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(0x3df,write_tandy,IO_MB);
IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB);
}
if (machine==MCH_PCJR) {
//write_pcjr will setup base address
write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 );
IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB);
IO_RegisterWriteHandler(0x3da,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;
}
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 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)) {
retval |= 0x80;
break;
return false;
}
CALLBACK_Idle();
}
return retval;
return true;
}
static Bitu INT14_Handler(void) {
@ -500,7 +498,7 @@ static Bitu INT14_Handler(void) {
CALLBACK_SCF(false);
break;
}
case 0x01: { // Transmit character
case 0x01: // Transmit character
// Parameters: Return:
// AL: character AL: unchanged
// 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
IO_WriteB(port+4,0x3);
// wait for DSR & CTS
reg_ah = INT14_Wait(port+6, 0x30, timeout);
if (!(reg_ah & 0x80)) {
if (INT14_Wait(port+6, 0x30, timeout, &reg_ah)) {
// wait for TX buffer empty
reg_ah = INT14_Wait(port+5, 0x20, timeout);
if (!(reg_ah & 0x80)) {
if (INT14_Wait(port+5, 0x20, timeout, &reg_ah)) {
// fianlly send the character
IO_WriteB(port,reg_al);
}
} // else timed out
} else
reg_ah |= 0x80;
} else // timed out
reg_ah |= 0x80;
CALLBACK_SCF(false);
break;
}
case 0x02: // Read character
// Parameters: Return:
// AH: 0x02 AL: received character
@ -537,15 +534,16 @@ static Bitu INT14_Handler(void) {
IO_WriteB(port+4,0x1);
// wait for DSR
reg_ah = INT14_Wait(port+6, 0x20, timeout);
if (!(reg_ah & 0x80)) {
if (INT14_Wait(port+6, 0x20, timeout, &reg_ah)) {
// wait for character to arrive
reg_ah = INT14_Wait(port+5, 0x01, timeout);
if (!(reg_ah & 0x80)) {
if (INT14_Wait(port+5, 0x01, timeout, &reg_ah)) {
reg_ah &= 0x1E;
reg_al = IO_ReadB(port);
}
}
} else
reg_ah |= 0x80;
} else
reg_ah |= 0x80;
CALLBACK_SCF(false);
break;
case 0x03: // get status

View File

@ -32,6 +32,7 @@
#include "setup.h"
#include "support.h"
#include "cpu.h"
#include "dma.h"
#define EMM_PAGEFRAME 0xE000
#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096)
@ -88,6 +89,8 @@ struct EMM_Handle {
EMM_Mapping page_map[EMM_MAX_PHYS];
};
static Bitu ems_type;
static EMM_Handle emm_handles[EMM_MAX_HANDLES];
static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
static EMM_Mapping emm_segmentmappings[0x40];
@ -97,7 +100,8 @@ static Bit16u GEMMIS_seg;
class device_EMM : public DOS_Device {
public:
device_EMM() {
device_EMM(bool is_emm386_avail) {
is_emm386=is_emm386_avail;
SetName("EMMXXXX0");
GEMMIS_seg=0;
}
@ -108,11 +112,12 @@ public:
}
bool Seek(Bit32u * /*pos*/,Bit32u /*type*/){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 WriteToControlChannel(PhysPt /*bufptr*/,Bit16u /*size*/,Bit16u * /*retcode*/){return true;}
private:
Bit8u cache;
bool is_emm386;
};
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;
return true;
case 0x01: {
if (!is_emm386) return false;
if (size!=6) return false;
if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20);
PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0);
@ -181,12 +187,14 @@ bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retco
return true;
}
case 0x02:
if (!is_emm386) return false;
if (size!=2) return false;
mem_writeb(bufptr+0x00,EMM_VERSION>>4); // version 4
mem_writeb(bufptr+0x01,EMM_MINOR_VERSION);
*retcode=2;
return true;
case 0x03:
if (!is_emm386) return false;
if (EMM_MINOR_VERSION < 0x2d) return false;
if (size!=4) return false;
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) {
// 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);
/* unmapping doesn't need valid handle (as handle isn't used) */
@ -1262,9 +1286,25 @@ static Bitu INT4B_Handler() {
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 {
private:
DOS_Device * emm_device;
/* location in protected unfreeable memory where the ems name and callback are
* stored 32 bytes.*/
static Bit16u ems_baseseg;
@ -1273,7 +1313,9 @@ private:
Bitu call_int67;
public:
EMS(Section* configuration):Module_base(configuration){
EMS(Section* configuration):Module_base(configuration) {
emm_device=NULL;
ems_type=0;
/* Virtual DMA interrupt callback */
call_vdma.Install(&INT4B_Handler,CB_IRET,"Int 4b vdma");
@ -1283,8 +1325,11 @@ public:
GEMMIS_seg=0;
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) {
ems_type=0;
LOG_MSG("EMS disabled for PCJr machine");
return;
}
@ -1302,8 +1347,8 @@ public:
/* Register the ems device */
//TODO MAYBE put it in the class.
DOS_Device * newdev = new device_EMM();
DOS_AddDevice(newdev);
emm_device = new device_EMM(ems_type!=2);
DOS_AddDevice(emm_device);
/* Clear handle and page tables */
Bitu i;
@ -1323,9 +1368,13 @@ public:
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 (ems_type!=2) {
/* Install a callback that handles VCPI-requests in protected mode requests */
call_vcpi.Install(&VCPI_PM_Handler,CB_IRETD,"VCPI PM");
vcpi.pm_interface=(call_vcpi.Get_callback())*CB_SIZE;
@ -1367,17 +1416,19 @@ public:
CPU_IRET(true,0);
}
}
}
~EMS() {
Section_prop * section=static_cast<Section_prop *>(m_configuration);
if (!section->Get_bool("ems")) return;
if (ems_type<=0) return;
/* Undo Biosclearing */
BIOS_ZeroExtendedSize(false);
/* Remove ems device */
device_EMM newdev;
DOS_DelDevice(&newdev);
if (emm_device!=NULL) {
DOS_DelDevice(emm_device);
emm_device=NULL;
}
GEMMIS_seg=0;
/* Remove the emsname and callback hack */

View File

@ -107,7 +107,9 @@ static Bitu INT10_Handler(void) {
INT10_ReadCharAttr(&reg_ax,reg_bh);
break;
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;
case 0x0A: /* Write Character at cursor CX times */
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);
break;
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) {
case 0x00: /* SET SINGLE PALETTE REGISTER */
INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
@ -162,7 +165,7 @@ static Bitu INT10_Handler(void) {
INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx);
break;
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;
case 0x12: /* SET BLOCK OF DAC REGISTERS */
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);
break;
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;
case 0x17: /* GET BLOCK OF DAC REGISTER */
INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
@ -208,11 +211,11 @@ static Bitu INT10_Handler(void) {
break;
case 0x01: /* Load 8x14 font */
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;
case 0x02: /* Load 8x8 font */
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;
case 0x03: /* Set Block Specifier */
IO_Write(0x3c4,0x3);IO_Write(0x3c5,reg_bl);
@ -220,7 +223,7 @@ static Bitu INT10_Handler(void) {
case 0x04: /* Load 8x16 font */
case 0x14:
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;
/* Graphics mode calls */
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_GetOverscanBorderColor(Bit8u * val);
void INT10_GetAllPaletteRegisters(PhysPt data);
void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue);
void INT10_GetSingleDacRegister(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_SetDACBlock(Bit16u index,Bit16u count,PhysPt data);
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data);
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 },
{ 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 },
//{ 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 },
};
@ -547,6 +548,11 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
default:
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
IO_WriteB(0x3da,0x5);
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;
else color_select=0x30;
IO_WriteB(0x3d9,color_select);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
INT10_SetColorSelect(1);
INT10_SetBackgroundBorder(0);
break;
}

View File

@ -35,9 +35,44 @@ static INLINE void WriteTandyACTL(Bit8u creg,Bit8u val) {
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) {
switch (machine) {
case TANDY_ARCH_CASE:
case MCH_PCJR:
reg&=0xf;
IO_Read(VGAREG_TDY_RESET);
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;
case EGAVGA_ARCH_CASE:
if (!IS_VGA_ARCH) reg&=0x1f;
@ -168,14 +203,23 @@ void INT10_GetAllPaletteRegisters(PhysPt data) {
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);
if ((real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x06)==0) {
IO_Write(VGAREG_DAC_DATA,red);
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);
*red=IO_Read(VGAREG_DAC_DATA);
*green=IO_Read(VGAREG_DAC_DATA);
@ -184,11 +228,26 @@ void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * bl
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
if ((real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x06)==0) {
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++));
}
} 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);
}
}
}
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
@ -245,11 +304,21 @@ void INT10_GetPelMask(Bit8u & mask) {
}
void INT10_SetBackgroundBorder(Bit8u val) {
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
temp=(temp & 0xe0) | (val & 0x1f);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp);
if (machine == MCH_CGA || IS_TANDY_ARCH)
IO_Write(0x3d9,temp);
Bit8u color_select=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
color_select=(color_select & 0xe0) | (val & 0x1f);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
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) {
val = ((val << 1) & 0x10) | (val & 0x7);
/* Aways set the overscan color */
@ -258,7 +327,7 @@ void INT10_SetBackgroundBorder(Bit8u val) {
if (CurMode->mode <= 3)
return;
INT10_SetSinglePaletteRegister( 0, val );
val = (temp & 0x10) | 2 | ((temp & 0x20) >> 5);
val = (color_select & 0x10) | 2 | ((color_select & 0x20) >> 5);
INT10_SetSinglePaletteRegister( 1, val );
val+=2;
INT10_SetSinglePaletteRegister( 2, val );
@ -271,8 +340,31 @@ void INT10_SetColorSelect(Bit8u val) {
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0);
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);
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) {
if (CurMode->mode <= 3) //Maybe even skip the total function!
return;
@ -296,6 +388,6 @@ void INT10_PerformGrayScaleSumming(Bit16u start_reg,Bit16u count) {
/* calculate clamped intensity, taken from VGABIOS */
Bit32u i=(( 77*red + 151*green + 28*blue ) + 0x80) >> 8;
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;
}
Bitu GetEMSType(Section_prop * section);
class XMS: public Module_base {
private:
CALLBACK_HandlerObject callbackhandler;
@ -445,7 +447,8 @@ public:
/* Set up UMB chain */
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(){