- Fix EGA panning to behave as on real hardware (fixes Beverly Hills Cop, Faery Tale Adv., Secret Agent 1)
- EGA splitscreen updates (Megademo, Secret Agent 1) - Change display address latch timing (Beverly Hills Cop) - Code style adoptions Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3621
This commit is contained in:
parent
db66fef419
commit
ef95dc160e
3 changed files with 61 additions and 20 deletions
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
typedef enum {
|
||||
PART,
|
||||
LINE,
|
||||
//EGALINE
|
||||
EGALINE
|
||||
} Drawmode;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -157,6 +157,9 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
|
|||
default:
|
||||
vga.config.pel_panning=(val & 0x7);
|
||||
}
|
||||
if (machine==MCH_EGA)
|
||||
// On the EGA panning can be programmed for every scanline:
|
||||
vga.draw.panning = vga.config.pel_panning;
|
||||
/*
|
||||
0-3 Indicates number of pixels to shift the display left
|
||||
Value 9bit textmode 256color mode Other modes
|
||||
|
|
|
@ -155,7 +155,7 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) {
|
|||
for (; start <= end;start++) {
|
||||
if ( map[start] & checkMask ) {
|
||||
Bitu offset = vidstart & vga.draw.linear_mask;
|
||||
if(vga.draw.linear_mask-offset < vga.draw.line_length)
|
||||
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 ];
|
||||
#if !defined(C_UNALIGNED_MEMORY)
|
||||
|
@ -574,8 +574,7 @@ static INLINE void VGA_ChangesEnd(void ) {
|
|||
|
||||
|
||||
static void VGA_ProcessSplit() {
|
||||
// On the EGA the address is always reset to 0.
|
||||
if ((vga.attr.mode_control&0x20) || (machine==MCH_EGA)) {
|
||||
if (vga.attr.mode_control&0x20) {
|
||||
vga.draw.address=0;
|
||||
// reset panning to 0 here so we don't have to check for
|
||||
// it in the character draw functions. It will be set back
|
||||
|
@ -585,7 +584,7 @@ static void VGA_ProcessSplit() {
|
|||
// In text mode only the characters are shifted by panning, not the address;
|
||||
// this is done in the text line draw function.
|
||||
vga.draw.address = vga.draw.byte_panning_shift*vga.draw.bytes_skip;
|
||||
if (!(vga.mode==M_TEXT)) vga.draw.address += vga.draw.panning;
|
||||
if ((vga.mode!=M_TEXT)&&(machine!=MCH_EGA)) vga.draw.address += vga.draw.panning;
|
||||
}
|
||||
vga.draw.address_line=0;
|
||||
}
|
||||
|
@ -612,6 +611,29 @@ static void VGA_DrawSingleLine(Bitu /*blah*/) {
|
|||
} else RENDER_EndUpdate(false);
|
||||
}
|
||||
|
||||
static void VGA_DrawEGASingleLine(Bitu /*blah*/) {
|
||||
if (GCC_UNLIKELY(vga.attr.disabled)) {
|
||||
memset(TempLine, 0, sizeof(TempLine));
|
||||
RENDER_DrawLine(TempLine);
|
||||
} else {
|
||||
Bitu address = vga.draw.address;
|
||||
if (vga.mode!=M_TEXT) address += vga.draw.panning;
|
||||
Bit8u * data=VGA_DrawLine(address, vga.draw.address_line );
|
||||
RENDER_DrawLine(data);
|
||||
}
|
||||
|
||||
vga.draw.address_line++;
|
||||
if (vga.draw.address_line>=vga.draw.address_line_total) {
|
||||
vga.draw.address_line=0;
|
||||
vga.draw.address+=vga.draw.address_add;
|
||||
}
|
||||
vga.draw.lines_done++;
|
||||
if (vga.draw.split_line==vga.draw.lines_done) VGA_ProcessSplit();
|
||||
if (vga.draw.lines_done < vga.draw.lines_total) {
|
||||
PIC_AddEvent(VGA_DrawEGASingleLine,(float)vga.draw.delay.htotal);
|
||||
} else RENDER_EndUpdate(false);
|
||||
}
|
||||
|
||||
static void VGA_DrawPart(Bitu lines) {
|
||||
while (lines--) {
|
||||
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
|
||||
|
@ -721,7 +743,6 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
|
|||
VGA_DisplayStartLatch(0);
|
||||
break;
|
||||
case MCH_VGA:
|
||||
case MCH_EGA:
|
||||
PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrstart);
|
||||
PIC_AddEvent(VGA_PanningLatch, (float)vga.draw.delay.vrend);
|
||||
// EGA: 82c435 datasheet: interrupt happens at display end
|
||||
|
@ -729,6 +750,10 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
|
|||
// add a little amount of time to make sure the last drawpart has already fired
|
||||
PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005));
|
||||
break;
|
||||
case MCH_EGA:
|
||||
PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrend);
|
||||
PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005));
|
||||
break;
|
||||
default:
|
||||
E_Exit("This new machine needs implementation in VGA_VerticalTimer too.");
|
||||
break;
|
||||
|
@ -748,7 +773,11 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
|
|||
vga.draw.address = vga.config.real_start;
|
||||
vga.draw.byte_panning_shift = 0;
|
||||
// go figure...
|
||||
if (machine==MCH_EGA) vga.draw.split_line*=2;
|
||||
if (machine==MCH_EGA) {
|
||||
if (vga.draw.doubleheight) // Spacepigs EGA Megademo
|
||||
vga.draw.split_line*=2;
|
||||
vga.draw.split_line++; // EGA adds one buggy scanline
|
||||
}
|
||||
// if (machine==MCH_EGA) vga.draw.split_line = ((((vga.config.line_compare&0x5ff)+1)*2-1)/vga.draw.lines_scaled);
|
||||
#ifdef VGA_KEEP_CHANGES
|
||||
bool startaddr_changed=false;
|
||||
|
@ -761,13 +790,13 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
|
|||
vga.draw.byte_panning_shift = 8;
|
||||
vga.draw.address += vga.draw.bytes_skip;
|
||||
vga.draw.address *= vga.draw.byte_panning_shift;
|
||||
vga.draw.address += vga.draw.panning;
|
||||
if (machine!=MCH_EGA) vga.draw.address += vga.draw.panning;
|
||||
#ifdef VGA_KEEP_CHANGES
|
||||
startaddr_changed=true;
|
||||
#endif
|
||||
break;
|
||||
case M_VGA:
|
||||
if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) {
|
||||
if (vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) {
|
||||
vga.draw.linear_base = vga.fastmem;
|
||||
vga.draw.linear_mask = 0xffff;
|
||||
} else {
|
||||
|
@ -843,16 +872,19 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
|
|||
PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts + draw_skip,vga.draw.parts_lines);
|
||||
break;
|
||||
case LINE:
|
||||
case EGALINE:
|
||||
if (GCC_UNLIKELY(vga.draw.lines_done < vga.draw.lines_total)) {
|
||||
LOG(LOG_VGAMISC,LOG_NORMAL)( "Lines left: %d",
|
||||
vga.draw.lines_total-vga.draw.lines_done);
|
||||
PIC_RemoveEvents(VGA_DrawSingleLine);
|
||||
if (vga.draw.mode==EGALINE) PIC_RemoveEvents(VGA_DrawEGASingleLine);
|
||||
else PIC_RemoveEvents(VGA_DrawSingleLine);
|
||||
RENDER_EndUpdate(true);
|
||||
}
|
||||
vga.draw.lines_done = 0;
|
||||
PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
|
||||
if (vga.draw.mode==EGALINE)
|
||||
PIC_AddEvent(VGA_DrawEGASingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
|
||||
else PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip));
|
||||
break;
|
||||
//case EGALINE:
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,6 +968,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
case MCH_PCJR:
|
||||
vga.draw.mode = LINE;
|
||||
break;
|
||||
case MCH_EGA:
|
||||
// Note: The Paradise SVGA uses the same panning mechanism as EGA
|
||||
vga.draw.mode = EGALINE;
|
||||
break;
|
||||
case MCH_VGA:
|
||||
if (svgaCard==SVGA_None) {
|
||||
vga.draw.mode = LINE;
|
||||
|
@ -1031,13 +1067,13 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
htotal*=2;
|
||||
}
|
||||
vga.draw.address_line_total=(vga.crtc.maximum_scan_line&0x1f)+1;
|
||||
if(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) {
|
||||
if (IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) {
|
||||
// vgaonly; can't use with CGA because these use address_line for their
|
||||
// own purposes.
|
||||
// Set the low resolution modes to have as many lines as are scanned -
|
||||
// Quite a few demos change the max_scanline register at display time
|
||||
// to get SFX: Majic12 show, Magic circle, Copper, GBU, Party91
|
||||
if( vga.crtc.maximum_scan_line&0x80) vga.draw.address_line_total*=2;
|
||||
if ( vga.crtc.maximum_scan_line&0x80) vga.draw.address_line_total*=2;
|
||||
vga.draw.double_scan=false;
|
||||
}
|
||||
else if (IS_VGA_ARCH) vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0;
|
||||
|
@ -1109,10 +1145,10 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
|
||||
// on blanking wrap to 0, the first line is not blanked
|
||||
// this is used by the S3 BIOS and other S3 drivers in some SVGA modes
|
||||
if((vbend&0x7f)==1) vblank_skip = 0;
|
||||
if ((vbend&0x7f)==1) vblank_skip = 0;
|
||||
|
||||
// it might also cut some lines off the bottom
|
||||
if(vbstart < vdend) {
|
||||
if (vbstart < vdend) {
|
||||
vdend = vbstart;
|
||||
}
|
||||
LOG(LOG_VGA,LOG_WARN)("Blanking wrap to line %d", vblank_skip);
|
||||
|
@ -1121,7 +1157,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
vblank_skip = vbend;
|
||||
LOG(LOG_VGA,LOG_WARN)("Upper %d lines of the screen blanked", vblank_skip);
|
||||
} else if (vbstart < vdend) {
|
||||
if(vbend < vdend) {
|
||||
if (vbend < vdend) {
|
||||
// the game wants a black bar somewhere on the screen
|
||||
LOG(LOG_VGA,LOG_WARN)("Unsupported blanking: line %d-%d",vbstart,vbend);
|
||||
} else {
|
||||
|
@ -1220,7 +1256,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
case M_LIN8:
|
||||
if (vga.crtc.mode_control & 0x8)
|
||||
width >>=1;
|
||||
else if(svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) {
|
||||
else if (svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) {
|
||||
doublewidth=true;
|
||||
width >>=1;
|
||||
}
|
||||
|
@ -1254,6 +1290,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
vga.draw.blocks = width;
|
||||
width<<=3;
|
||||
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
|
||||
// This would also be required for EGA in Spacepigs Megademo
|
||||
bpp=16;
|
||||
VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line;
|
||||
} else VGA_DrawLine=VGA_Draw_Linear_Line;
|
||||
|
@ -1285,7 +1322,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
doublewidth=(vga.seq.clocking_mode & 0x8) > 0;
|
||||
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) {
|
||||
// vgaonly: allow 9-pixel wide fonts
|
||||
if(vga.seq.clocking_mode&0x01) {
|
||||
if (vga.seq.clocking_mode&0x01) {
|
||||
vga.draw.char9dot = false;
|
||||
width*=8;
|
||||
} else {
|
||||
|
@ -1376,7 +1413,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
}
|
||||
vga.draw.vblank_skip = vblank_skip;
|
||||
|
||||
if(!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) {
|
||||
if (!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) {
|
||||
//Only check for extra double height in vga modes
|
||||
//(line multiplying by address_line_total)
|
||||
if (!doubleheight && (vga.mode<M_TEXT) && !(vga.draw.address_line_total & 1)) {
|
||||
|
@ -1453,6 +1490,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
void VGA_KillDrawing(void) {
|
||||
PIC_RemoveEvents(VGA_DrawPart);
|
||||
PIC_RemoveEvents(VGA_DrawSingleLine);
|
||||
PIC_RemoveEvents(VGA_DrawEGASingleLine);
|
||||
vga.draw.parts_left = 0;
|
||||
vga.draw.lines_done = ~0;
|
||||
RENDER_EndUpdate(true);
|
||||
|
|
Loading…
Add table
Reference in a new issue