INT 10h: If machine=ega, check EGA switches to detect games that alter the EGA switches to force 200-line mode

This commit is contained in:
Jonathan Campbell 2024-12-04 20:49:32 -08:00
parent 22328353be
commit b0c5c68cc6
3 changed files with 26 additions and 3 deletions

View File

@ -4,6 +4,10 @@ Next
to divide line by 2 in rendering to match double scanned scanlines,
so that the "graphical" text of "After the War" can render properly
for machine=vgaonly. (joncampbell123).
- INT 10: If machine=ega, check the EGA switches on INT 10h modeset.
Some games force the EGA BIOS to use CGA 200-line text modes by
modifying those bits and then setting the mode ("After the War").
(joncampbell123).
2024.12.04
- Arrange memory device allocation so that it is possible to allocate

View File

@ -1240,7 +1240,10 @@ static void INT10_Seg40Init(void) {
// in Tandy emulation, this byte must be zero.
if (IS_EGAVGA_ARCH) {
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,0x60);
if (IS_VGA_ARCH)
real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
else
real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,ega200 ? 8 : 14);
// NTS: This is direclty from the configuration switches. The bits are inverted,
// 1=OFF 0=ON.
//
@ -1262,7 +1265,7 @@ static void INT10_Seg40Init(void) {
// [http://hackipedia.org/browse.cgi/Computer/Platform/PC%2c%20IBM%20compatible/Video/EGA/IBM/IBM%20Enhanced%20Graphics%20Adapter%20%281984%2d08%2d02%29%2epdf]
//
// Anything else is not valid.
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xFF^((!IS_VGA_ARCH && ega200)?0x8:0x6));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xFF^((!IS_VGA_ARCH && ega200)?0x7:0x9));
// Set the pointer to video save pointer table
real_writed(BIOSMEM_SEG, BIOSMEM_VS_POINTER, int10.rom.video_save_pointers);
}

View File

@ -887,7 +887,6 @@ static void FinishSetMode(bool clearmem) {
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(uint8_t)(CurMode->theight-1));
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(uint16_t)CurMode->cheight);
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80)));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,(!IS_VGA_ARCH && ega200)?0x08:0x09);
// this is an index into the dcc table:
#if C_DEBUG
if(IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,DISP2_Active()?0x0c:0x0b);
@ -1259,6 +1258,23 @@ static bool ShouldUseVPT(void) {
bool unmask_irq0_on_int10_setmode = true;
bool INT10_SetVideoMode(uint16_t mode) {
if (IS_EGA_ARCH) {
/* "After The War" forces EGA into 200-line CGA 8x8 text mode by
* modifying the 16-bits at 0x487-0x488 to alter the EGA switches
* and other info. For this trick to work here, we have to check
* those bits every modeset. */
uint8_t egasw = (real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES)^0xFF)&0xF;
bool newega200 = (egasw == 0 || egasw == 1 || egasw == 2 || egasw == 6 || egasw == 7 || egasw == 8);
if (ega200 != newega200) {
LOG(LOG_MISC,LOG_DEBUG)(
"EGA: Guest application changed BIOS DATA AREA EGA switches, %s 200-line EGA modes (sw=0x%x)",
newega200?"enabled":"disabled",egasw);
ega200 = newega200;
}
}
if (CurMode&&CurMode->mode==7&&!IS_PC98_ARCH) {
VideoModeBlock *modelist;