MFX Melvindale needed scanline y adjust for LFB, now Contract Out of Control needs x adjust for LFB

This commit is contained in:
Jonathan Campbell 2024-08-10 09:54:45 -07:00
parent 3aecdb4c1f
commit 3770369da3
4 changed files with 24 additions and 1 deletions

View File

@ -1,4 +1,9 @@
NEXT
- VESA BIOS: Add new option to adjust reported linear framebuffer
address by a specific number of pixels. This is needed by
"Out of Control" by Contract which for whatever reason,
will always draw to the LFB base minus 128 bytes. This option
makes it possible to correct the demo graphics. (joncampbell123).
- Gravis Ultrasound: Officially, registers 0x0-0xF, the voice
control registers, are documented to have a 0x0-0xF write and
0x80-0x8F read alias. Unofficially, according to the behavior

View File

@ -2703,6 +2703,12 @@ void DOSBOX_SetupConfigSections(void) {
"location reported by the VESA BIOS. Set to nonzero for DOS games with sloppy VESA graphics pointer management.\n"
" MFX \"Melvindale\" (1996): Set this option to 2 to center the picture properly.");
Pint = secprop->Add_int("vesa lfb pel scanline adjust",Property::Changeable::WhenIdle,0);
Pint->Set_help("If non-zero, the VESA BIOS will report the linear framebuffer offset by this many pixels.\n"
"This does not affect the linear framebuffer's location. It only affects the linear framebuffer\n"
"location reported by the VESA BIOS. Set to nonzero for DOS games with sloppy VESA graphics pointer management.\n"
" Contract \"Out of Control\" (1997): Set this option to 128 to fix the display.");
/* If set, all VESA BIOS modes map 128KB of video RAM at A0000-BFFFF even though VESA BIOS emulation
* reports a 64KB window. Some demos like the 1996 Wired report
* (ftp.scene.org/pub/parties/1995/wired95/misc/e-w95rep.zip) assume they can write past the window

View File

@ -688,6 +688,7 @@ static inline unsigned int int_log2(unsigned int val) {
extern bool pcibus_enable;
extern int hack_lfb_yadjust;
extern int hack_lfb_xadjust;
extern uint8_t GDC_display_plane_wait_for_vsync;
void VGA_VsyncUpdateMode(VGA_Vsync vsyncmode);
@ -935,6 +936,7 @@ void VGA_Reset(Section*) {
vga_ignore_extended_memory_bit = section->Get_bool("ignore extended memory bit");
enable_vretrace_poll_debugging_marker = section->Get_bool("vertical retrace poll debug line");
vga_double_buffered_line_compare = section->Get_bool("double-buffered line compare");
hack_lfb_xadjust = section->Get_int("vesa lfb pel scanline adjust");
hack_lfb_yadjust = section->Get_int("vesa lfb base scanline adjust");
allow_vesa_lowres_modes = section->Get_bool("allow low resolution vesa modes");
allow_vesa_4bpp_packed = section->Get_bool("allow 4bpp packed vesa modes");

View File

@ -32,6 +32,7 @@
#include "bitop.h"
int hack_lfb_yadjust = 0;
int hack_lfb_xadjust = 0;
int vesa_set_display_vsync_wait = -1;
bool vesa_bank_switch_window_range_check = true;
@ -252,6 +253,7 @@ uint8_t VESA_GetSVGAModeInformation(uint16_t mode,uint16_t seg,uint16_t off) {
PhysPt buf=PhysMake(seg,off);
Bitu pageSize;
uint8_t modeAttributes;
unsigned int adj = 0;
Bitu i=0;
mode&=0x3fff; // vbe2 compatible, ignore lfb and keep screen content bits
@ -298,6 +300,7 @@ foundit:
case M_PACKED4:
if (!allow_vesa_4bpp_packed && !(ModeList_VGA[i].mode >= 0x202 && ModeList_VGA[i].mode <= 0x208)) return VESA_FAIL;//TODO: New option to disable
pageSize = mblock->sheight * cwidth/2;
adj = hack_lfb_xadjust / 2;
var_write(&minfo.BytesPerScanLine,(uint16_t)((((cwidth+15U)/8U)&(~1U))*4)); /* NTS: 4bpp requires even value due to VGA registers, round up */
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -310,6 +313,7 @@ foundit:
case M_LIN4:
if (!allow_vesa_4bpp) return VESA_FAIL;
pageSize = mblock->sheight * (uint16_t)(((cwidth+15U)/8U)&(~1U));
adj = hack_lfb_xadjust / 8;
var_write(&minfo.BytesPerScanLine,(uint16_t)(((cwidth+15U)/8U)&(~1U))); /* NTS: 4bpp requires even value due to VGA registers, round up */
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x4);
@ -321,6 +325,7 @@ foundit:
case M_LIN8:
if (!allow_vesa_8bpp || !allow_res) return VESA_FAIL;
pageSize = mblock->sheight * cwidth;
adj = hack_lfb_xadjust;
var_write(&minfo.BytesPerScanLine,(uint16_t)cwidth);
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -333,6 +338,7 @@ foundit:
case M_LIN15:
if (!allow_vesa_15bpp || !allow_res) return VESA_FAIL;
pageSize = mblock->sheight * cwidth*2;
adj = hack_lfb_xadjust * 2;
var_write(&minfo.BytesPerScanLine,(uint16_t)(cwidth*2));
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -353,6 +359,7 @@ foundit:
case M_LIN16:
if (!allow_vesa_16bpp || !allow_res) return VESA_FAIL;
pageSize = mblock->sheight * cwidth*2;
adj = hack_lfb_xadjust * 2;
var_write(&minfo.BytesPerScanLine,(uint16_t)(cwidth*2));
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -372,6 +379,7 @@ foundit:
if (!allow_vesa_24bpp || !allow_res) return VESA_FAIL;
if (mode >= 0x120 && !allow_explicit_vesa_24bpp) return VESA_FAIL;
pageSize = mblock->sheight * cwidth*3;
adj = hack_lfb_xadjust * 3;
var_write(&minfo.BytesPerScanLine,(uint16_t)(cwidth*3));
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -390,6 +398,7 @@ foundit:
case M_LIN32:
if (!allow_vesa_32bpp || !allow_res) return VESA_FAIL;
pageSize = mblock->sheight * cwidth*4;
adj = hack_lfb_xadjust * 4;
var_write(&minfo.BytesPerScanLine,(uint16_t)(cwidth*4));
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
var_write(&minfo.NumberOfPlanes,0x1);
@ -409,6 +418,7 @@ foundit:
break;
case M_TEXT:
if (!allow_vesa_tty) return VESA_FAIL;
adj = hack_lfb_xadjust / 8;
pageSize = 0;
var_write(&minfo.BytesPerScanLine, (uint16_t)(mblock->twidth * 2));
if (!int10.vesa_oldvbe10) { /* optional in VBE 1.0 */
@ -494,7 +504,7 @@ foundit:
}
}
if (!int10.vesa_nolfb && !int10.vesa_oldvbe) var_write(&minfo.PhysBasePtr,S3_LFB_BASE + (hack_lfb_yadjust*(long)host_readw((HostPt)(&minfo.BytesPerScanLine))));
if (!int10.vesa_nolfb && !int10.vesa_oldvbe) var_write(&minfo.PhysBasePtr,S3_LFB_BASE + adj + (hack_lfb_yadjust*(long)host_readw((HostPt)(&minfo.BytesPerScanLine))));
MEM_BlockWrite(buf,&minfo,sizeof(MODE_INFO));
return VESA_SUCCESS;