mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-08 02:53:03 +08:00
Merge pull request #831 from alexat/sdlmain_refactor
Generalize aspect correction (fit and extend) functions, removing duplicated code from outputs, minor warnings fix in sdlmain.cpp
This commit is contained in:
commit
59b1f08837
146
NOTES-TESTING-LOG/2018-07-02/TEST RESULTS AND FINDINGS.TXT
Normal file
146
NOTES-TESTING-LOG/2018-07-02/TEST RESULTS AND FINDINGS.TXT
Normal file
@ -0,0 +1,146 @@
|
||||
2018/07/02 test results and findings.
|
||||
|
||||
Test units:
|
||||
|
||||
COMP-Compro1997 An old Pentium ? from 1997, with ATI AGP VGA
|
||||
COMP-IBMPS2-30 An old IBM PS/2 Model 30 (286) with VGA
|
||||
COMP-P2ISA1997 An old Pentium II from 1997, with S3 VGA
|
||||
COMP-IBM5150 An old IBM 5150, 8088, with CGA
|
||||
COMP-Old486y91 An old 486SX 33MHz, with Tseng ET4000
|
||||
DOSBox-X-1e6bb8dc469761d46217d44615c06a7ff95f2e49 DOSBox-X, by indicated commit
|
||||
DOSLIB-848166fcacb6292773253273ef192ddae7942064 DOSLIB, by indicated commit
|
||||
|
||||
Equipment:
|
||||
|
||||
- Composite video capture (PEXHDCAP 1080p60). None of my Happauge USB capture
|
||||
sticks were willing to capture the CGA composite video output for some reason,
|
||||
nor would the Happauge WinTV in one of my machines. The PEXHDCAP was able to
|
||||
but had curious brightness problems as screen contents changed.
|
||||
|
||||
- HDMI video capture (PEXHDCAP 1080p30)
|
||||
|
||||
- VGA to HDMI adapter (one that matches the mode and converts as-is)
|
||||
|
||||
- A mobile phone, pointed at the LCD TV set (second try, IBM 5150 test)
|
||||
|
||||
Software:
|
||||
|
||||
- DOSBox-X build:
|
||||
git commit 1e6bb8dc469761d46217d44615c06a7ff95f2e49
|
||||
|
||||
- DOSLIB build:
|
||||
git commit 848166fcacb6292773253273ef192ddae7942064
|
||||
|
||||
Findings:
|
||||
|
||||
- On the IBM 5150, The IBM BIOS (I think it dates from 1982) is indeed missing
|
||||
the "number of rows - 1" value in the BIOS data area. This confirms comments
|
||||
in TEST-FW\VIDEO\PC\TEST.C about how it may not exist according to the
|
||||
definitions listed in IBM ROM BIOS source code from 1984, while the 1986
|
||||
listing does list it.
|
||||
|
||||
- On the IBM 5150, INT 10h appears to have a bug where all CGA modes work, but
|
||||
setting mode 7 produces a video mode with horizontal and vertical timing that
|
||||
is incompatible with NTSC. During that part, neither my capture card nor the
|
||||
LCD TV set would display anything.
|
||||
|
||||
Perhaps the bug, theoretically, is the application of MDA monitor timing for
|
||||
INT 10h mode 7 even on CGA.
|
||||
|
||||
- The EGA palette assumed in 16-color modes didn't always match the TEST-FW
|
||||
video's assumptions, but the differences are not jarring. They're understandable.
|
||||
|
||||
- In the 256-color mode test, three different attribute controller to DAC to
|
||||
DAC mask behaviors were seen.
|
||||
|
||||
|
||||
The most common, seen on all but two, is that the attribute controller appears
|
||||
to affect both the low nibble and upper bits (high nibble?) of the 8-bit
|
||||
color palette index.
|
||||
|
||||
When the test program flashes the attribute controller palette #1 for example,
|
||||
it appears to affect not only every 16th color starting from #1, but also
|
||||
colors #16-#31.
|
||||
|
||||
Generally, flashing attribute controller palette N affects:
|
||||
Every 16th color starting at N
|
||||
Colors (N * 16) to (N * 16 + 15)
|
||||
|
||||
This remapping needs more investigation on how exactly it works. This should
|
||||
be done as a separate palette test program targeting only the VGA.
|
||||
|
||||
Results so far suggest that both the low nibble and high nibble are translated
|
||||
through the attribute controller palette registers.
|
||||
|
||||
|
||||
On the Tseng ET4000, the attribute controller only affects the low 4 bits.
|
||||
It does not affect any of the higher bits.
|
||||
|
||||
Flashing attribute color palette N affects only every 16th color starting at N.
|
||||
|
||||
|
||||
Finally, perhaps the most erroneous is DOSBox-X (and DOSBox SVN).
|
||||
|
||||
Due to optimizations around lazily updating only part of the color palette,
|
||||
DOSBox-X only updates ONE color palette entry when the attribute controller
|
||||
palette is flashing.
|
||||
|
||||
Flashing attribute controller palette N affects:
|
||||
One color at DAC palette entry N
|
||||
|
||||
Questions to answer in further development:
|
||||
|
||||
For a separate program in TEST-FW\VIDEO\PC, focused on the VGA:
|
||||
|
||||
- How exactly does the attribute controller affect all 8 bits of 256-color pixels?
|
||||
|
||||
The TEST-FW\VIDEO\PC\TEST.C program only shows what happens when flashing the
|
||||
attribute controller palette entry between it's initial value and 0x3F (if the
|
||||
initial value is dimmer than neutral gray) or 0x00 (if brigher than gray).
|
||||
|
||||
- How do Attribute Controller registers 0x10 and 0x14 affect this mapping?
|
||||
|
||||
See http://www.osdever.net/FreeVGA/vga/attrreg.htm
|
||||
|
||||
These registers are documented to affect the color palette entry coming from
|
||||
the attribute controller, bits 4-5 in one case, and bits 6-7 in non-256-color
|
||||
modes.
|
||||
|
||||
Interesting to check: What happens if register 0x10 bit 6 (8-bit color enable)
|
||||
is switched off in 256-color mode?
|
||||
|
||||
- How does the DAC mask (3C6h) affect the attribute controller, VGA palette,
|
||||
various AC bits?
|
||||
|
||||
It's not clear where the DAC mask is applied, though as "Pel mask" it may be
|
||||
at the final stage before conversion through the VGA palette. Test program
|
||||
should confirm this.
|
||||
|
||||
Test routine ideas:
|
||||
|
||||
- Interactive mode to fiddle with attribute controller, color palette, and
|
||||
attribute controller bits, with 256-color palette on screen to show effects.
|
||||
|
||||
- Non-interactive mode to run through combinations of these bits, for capture
|
||||
and logging purposes.
|
||||
|
||||
Related demoscene capture ideas:
|
||||
|
||||
"Copper" (ftp.scene.org/pub/parties/1992/theparty92/demo/copper.zip)
|
||||
|
||||
- This demo uses VGA palette tricks that only seem to work in DOSBox-X and
|
||||
are said only to work on Tseng ET4000AX cards.
|
||||
|
||||
Test on ET4000 card vs S3 and ATI to note where it works exactly.
|
||||
|
||||
Noted in the past is that on S3 and Paradise chipsets, the "line fading"
|
||||
effects (explicitly said and during scrolling credits) show absolutely
|
||||
nothing on-screen.
|
||||
|
||||
- This demo abuses the horizontal sync pulse in some parts to make the
|
||||
picture "wobble", which causes modern VGA monitors and LCDS to switch off
|
||||
instead. Pull out an old VGA CRT or two and see if the effect can be
|
||||
recorded off the screen. Noted in past test runs, is that the effect
|
||||
makes an audible though quiet "ringing" sound in the back of the picture
|
||||
tube as the CRT tries to follow this "wobble" effect.
|
||||
|
@ -1,3 +1,3 @@
|
||||
/*auto-generated*/
|
||||
#define UPDATED_STR "Jun 30, 2018 9:48:45pm"
|
||||
#define UPDATED_STR "Jul 1, 2018 9:48:00am"
|
||||
#define COPYRIGHT_END_YEAR "2018"
|
||||
|
@ -168,4 +168,4 @@ void UpdateWindowDimensions(Bitu width, Bitu height);
|
||||
SDL_Window* GFX_SetSDLWindowMode(Bit16u width, Bit16u height, SCREEN_TYPES screenType);
|
||||
#endif
|
||||
|
||||
#endif /*DOSBOX_SDLMAIN_H*/
|
||||
#endif /*DOSBOX_SDLMAIN_H*/
|
||||
|
@ -87,8 +87,14 @@ void MAPPER_UpdateJoysticks(void);
|
||||
#endif
|
||||
|
||||
/* Mouse related */
|
||||
//! \brief Toggles mouse capture.
|
||||
void GFX_CaptureMouse(void);
|
||||
//! \brief Sets mouse capture state manually.
|
||||
void GFX_CaptureMouse(bool capture);
|
||||
//! \brief Notifies mouse capture according current state.
|
||||
void CaptureMouseNotify();
|
||||
//! \brief Notifies mouse capture according specific state.
|
||||
void CaptureMouseNotify(bool capture);
|
||||
extern bool mouselocked; //true if mouse is confined to window
|
||||
|
||||
#endif
|
||||
|
@ -3987,6 +3987,7 @@ static void MORE_ProgramStart(Program * * make) {
|
||||
void REDOS_ProgramStart(Program * * make);
|
||||
void A20GATE_ProgramStart(Program * * make);
|
||||
void PC98UTIL_ProgramStart(Program * * make);
|
||||
void VESAMOED_ProgramStart(Program * * make);
|
||||
|
||||
class NMITEST : public Program {
|
||||
public:
|
||||
@ -4003,14 +4004,43 @@ class CAPMOUSE : public Program
|
||||
{
|
||||
public:
|
||||
void Run() override
|
||||
{
|
||||
CaptureMouseNotify();
|
||||
GFX_CaptureMouse();
|
||||
std::string msg;
|
||||
msg.append("Mouse ");
|
||||
msg.append(Mouse_IsLocked() ? "captured" : "released");
|
||||
WriteOut(msg.c_str());
|
||||
}
|
||||
{
|
||||
auto val = 0;
|
||||
auto tmp = std::string("");
|
||||
|
||||
if(cmd->GetCount() == 0 || cmd->FindExist("/?", true))
|
||||
val = 0;
|
||||
else if(cmd->FindExist("/C", false))
|
||||
val = 1;
|
||||
else if(cmd->FindExist("/R", false))
|
||||
val = 2;
|
||||
|
||||
auto cap = false;
|
||||
switch(val)
|
||||
{
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
cap = true;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
WriteOut("Mouse capture/release.\n\n");
|
||||
WriteOut("CAPMOUSE /[?|C|R]\n");
|
||||
WriteOut(" /? help\n");
|
||||
WriteOut(" /C capture mouse\n");
|
||||
WriteOut(" /R release mouse\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CaptureMouseNotify(!cap);
|
||||
GFX_CaptureMouse(cap);
|
||||
std::string msg;
|
||||
msg.append("Mouse ");
|
||||
msg.append(Mouse_IsLocked() ? "captured" : "released");
|
||||
msg.append("\n");
|
||||
WriteOut(msg.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void CAPMOUSE_ProgramStart(Program** make)
|
||||
@ -4478,6 +4508,9 @@ void DOS_SetupPrograms(void) {
|
||||
PROGRAMS_MakeFile("NMITEST.COM",NMITEST_ProgramStart);
|
||||
PROGRAMS_MakeFile("RE-DOS.COM",REDOS_ProgramStart);
|
||||
|
||||
if (IS_VGA_ARCH && svgaCard != SVGA_None)
|
||||
PROGRAMS_MakeFile("VESAMOED.COM",VESAMOED_ProgramStart);
|
||||
|
||||
if (IS_PC98_ARCH)
|
||||
PROGRAMS_MakeFile("PC98UTIL.COM",PC98UTIL_ProgramStart);
|
||||
|
||||
|
@ -123,6 +123,11 @@ static void RENDER_EmptyLineHandler(const void * src) {
|
||||
/*HACK*/
|
||||
#if defined(__SSE__) && defined(_M_AMD64)
|
||||
# define sse2_available (1) /* SSE2 is always available on x86_64 */
|
||||
#else
|
||||
# ifdef __SSE__
|
||||
extern bool sse1_available;
|
||||
extern bool sse2_available;
|
||||
# endif
|
||||
#endif
|
||||
/*END HACK*/
|
||||
|
||||
@ -133,10 +138,8 @@ static void RENDER_StartLineHandler(const void * s) {
|
||||
Bits count = (Bits)render.src.start;
|
||||
#if defined(__SSE__)
|
||||
if (sse2_available) {
|
||||
#if defined (_MSC_VER)
|
||||
#define SIZEOF_INT_P sizeof(*src)
|
||||
#endif
|
||||
static const Bitu simd_inc = 16/SIZEOF_INT_P;
|
||||
#define MY_SIZEOF_INT_P sizeof(*src)
|
||||
static const Bitu simd_inc = 16/MY_SIZEOF_INT_P;
|
||||
while (count >= (Bits)simd_inc) {
|
||||
__m128i v = _mm_loadu_si128((const __m128i*)src);
|
||||
__m128i c = _mm_loadu_si128((const __m128i*)cache);
|
||||
@ -145,6 +148,7 @@ static void RENDER_StartLineHandler(const void * s) {
|
||||
goto cacheMiss;
|
||||
count-=(Bits)simd_inc; src+=simd_inc; cache+=simd_inc;
|
||||
}
|
||||
#undef MY_SIZEOF_INT_P
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1780,7 +1780,11 @@ void GFX_ReleaseMouse(void) {
|
||||
}
|
||||
|
||||
void GFX_CaptureMouse(void) {
|
||||
sdl.mouse.locked=!sdl.mouse.locked;
|
||||
GFX_CaptureMouse(!sdl.mouse.locked);
|
||||
}
|
||||
|
||||
void GFX_CaptureMouse(bool capture) {
|
||||
sdl.mouse.locked=capture;
|
||||
if (sdl.mouse.locked) {
|
||||
#if defined(C_SDL2)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
@ -1838,9 +1842,8 @@ void GFX_UpdateSDLCaptureState(void) {
|
||||
}
|
||||
|
||||
#if WIN32
|
||||
void CaptureMouseNotifyWin32()
|
||||
void CaptureMouseNotifyWin32(bool lck)
|
||||
{
|
||||
const auto lck = sdl.mouse.locked;
|
||||
switch (sdl.mouse.autolock_feedback)
|
||||
{
|
||||
case AUTOLOCK_FEEDBACK_NONE: break;
|
||||
@ -1882,9 +1885,14 @@ void CaptureMouseNotifyWin32()
|
||||
#endif
|
||||
|
||||
void CaptureMouseNotify()
|
||||
{
|
||||
CaptureMouseNotify(sdl.mouse.locked);
|
||||
}
|
||||
|
||||
void CaptureMouseNotify(bool capture)
|
||||
{
|
||||
#if WIN32
|
||||
CaptureMouseNotifyWin32();
|
||||
CaptureMouseNotifyWin32(capture);
|
||||
#else
|
||||
// TODO
|
||||
#endif
|
||||
@ -4334,8 +4342,8 @@ void GFX_EventsMouseProcess(const long x, const long y, const long rx, const lon
|
||||
evt.motion.which = 0;
|
||||
evt.motion.x = x3;
|
||||
evt.motion.y = y3;
|
||||
evt.motion.xrel = rx;
|
||||
evt.motion.yrel = ry;
|
||||
evt.motion.xrel = (Sint16)((rx >= 0) ? min(rx, 32767) : max(rx, -32768));
|
||||
evt.motion.yrel = (Sint16)((ry >= 0) ? min(ry, 32767) : max(ry, -32768));
|
||||
SDL_PushEvent(&evt);
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,8 @@ void VGA_DAC_UpdateColor( Bitu index ) {
|
||||
/* Remember the lookup table is there to handle the color palette AND the DAC mask AND the attribute controller palette */
|
||||
/* FIXME: Is it: index -> attribute controller -> dac mask, or
|
||||
* index -> dac mask -> attribute controller? */
|
||||
/* According to FreeVGA:
|
||||
* index -> attribute controller -> dac mask */
|
||||
maskIndex = vga.dac.combine[index&0xF] & vga.dac.pel_mask;
|
||||
VGA_DAC_SendColor( index, maskIndex );
|
||||
break;
|
||||
|
@ -178,7 +178,7 @@ static inline Bitu VGA_Generic_Read_Handler(PhysPt planeaddr,PhysPt rawaddr,unsi
|
||||
* Then when addressing VRAM A0 is replaced by a "higher order bit", which is
|
||||
* probably A14 or A16 depending on Extended Memory bit 1 in Sequencer register 04h memory mode */
|
||||
if ((vga.gfx.miscellaneous&2) && !non_cga_ignore_oddeven_engage) {/* Odd/Even enable */
|
||||
const PhysPt mask = (1u << hobit_n) - 2u;
|
||||
const PhysPt mask = (vga.config.compatible_chain4 ? 0u : ~0xFFFFu) + (1u << hobit_n) - 2u;
|
||||
const PhysPt hobit = (planeaddr >> hobit_n) & 1u;
|
||||
/* 1 << 14 = 0x4000
|
||||
* 1 << 14 - 1 = 0x3FFF
|
||||
@ -187,7 +187,7 @@ static inline Bitu VGA_Generic_Read_Handler(PhysPt planeaddr,PhysPt rawaddr,unsi
|
||||
planeaddr = (planeaddr & mask & (vga.mem.memmask >> 2u)) + hobit;
|
||||
}
|
||||
else {
|
||||
const PhysPt mask = (1u << hobit_n) - 1u;
|
||||
const PhysPt mask = (vga.config.compatible_chain4 ? 0u : ~0xFFFFu) + (1u << hobit_n) - 1u;
|
||||
planeaddr &= mask & (vga.mem.memmask >> 2u);
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ template <const bool chained> static inline void VGA_Generic_Write_Handler(PhysP
|
||||
* Then when addressing VRAM A0 is replaced by a "higher order bit", which is
|
||||
* probably A14 or A16 depending on Extended Memory bit 1 in Sequencer register 04h memory mode */
|
||||
if ((vga.gfx.miscellaneous&2) && !non_cga_ignore_oddeven_engage) {/* Odd/Even enable */
|
||||
const PhysPt mask = (1u << hobit_n) - 2u;
|
||||
const PhysPt mask = (vga.config.compatible_chain4 ? 0u : ~0xFFFFu) + (1u << hobit_n) - 2u;
|
||||
const PhysPt hobit = (planeaddr >> hobit_n) & 1u;
|
||||
/* 1 << 14 = 0x4000
|
||||
* 1 << 14 - 1 = 0x3FFF
|
||||
@ -245,7 +245,7 @@ template <const bool chained> static inline void VGA_Generic_Write_Handler(PhysP
|
||||
planeaddr = (planeaddr & mask & (vga.mem.memmask >> 2u)) + hobit;
|
||||
}
|
||||
else {
|
||||
const PhysPt mask = (1u << hobit_n) - 1u;
|
||||
const PhysPt mask = (vga.config.compatible_chain4 ? 0u : ~0xFFFFu) + (1u << hobit_n) - 1u;
|
||||
planeaddr &= mask & (vga.mem.memmask >> 2u);
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,7 @@ void FinishSetMode_PVGA1A(Bitu /*crtc_base*/, VGA_ModeExtraData* modeData) {
|
||||
// vga.vmemwrap = 256*1024;
|
||||
}
|
||||
|
||||
// FIXME: What? Is this needed?
|
||||
vga.config.compatible_chain4 = false;
|
||||
|
||||
VGA_SetupHandlers();
|
||||
|
@ -138,6 +138,7 @@ typedef struct {
|
||||
Bit16u pmode_interface_start;
|
||||
Bit16u pmode_interface_window;
|
||||
Bit16u pmode_interface_palette;
|
||||
Bit16u vesa_alloc_modes;
|
||||
Bit16u used;
|
||||
} rom;
|
||||
Bit16u vesa_setmode;
|
||||
@ -151,6 +152,8 @@ typedef struct {
|
||||
#define _S3_PIXEL_DOUBLE 0x0008
|
||||
#define _REPEAT1 0x0010 /* VGA doublescan (bit 0 of max scanline) */
|
||||
#define _CGA_SYNCDOUBLE 0x0020
|
||||
#define _USER_DISABLED 0x4000 /* disabled (cannot set mode) but still listed in modelist */
|
||||
#define _USER_MODIFIED 0x8000 /* user modified (through VESAMOED) */
|
||||
|
||||
extern Int10Data int10;
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "mouse.h"
|
||||
#include "vga.h"
|
||||
#include "bios.h"
|
||||
#include "programs.h"
|
||||
|
||||
#define SEQ_REGS 0x05
|
||||
#define GFX_REGS 0x09
|
||||
@ -142,11 +143,19 @@ VideoModeBlock ModeList_VGA[]={
|
||||
// if you select VGA 320x200 with S3 acceleration.
|
||||
{ 0x153 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _REPEAT1 },
|
||||
|
||||
{ 0x15C ,M_LIN8, 512 ,384 ,64 ,48 ,8, 8 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
|
||||
{ 0x159 ,M_LIN8, 400 ,300 ,50 ,37 ,8 ,8 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
|
||||
{ 0x15D ,M_LIN16, 512 ,384 ,64 ,48 ,8, 16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
|
||||
{ 0x15A ,M_LIN16, 400 ,300 ,50 ,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
|
||||
|
||||
{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
|
||||
{ 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
|
||||
{ 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
|
||||
{ 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
|
||||
|
||||
// hack: 320x200x16bpp for "Process" demo (1997) with apparently hard-coded VBE mode
|
||||
{ 0x136 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
|
||||
|
||||
// hack: 320x480x256-color alias for Habitual demo. doing this removes the need to run S3VBE20.EXE before running the demo.
|
||||
// the reason it has to be this particular video mode is because HABITUAL.EXE does not query modes, it simply assumes
|
||||
// that mode 0x166 is this particular mode and errors out if it can't set it.
|
||||
@ -510,13 +519,24 @@ static bool SetCurMode(VideoModeBlock modeblock[],Bit16u mode) {
|
||||
while (modeblock[i].mode!=0xffff) {
|
||||
if (modeblock[i].mode!=mode)
|
||||
i++;
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity UNLESS the user changed the mode */
|
||||
else if (modeblock[i].mode >= 0x100 && modeblock[i].mode <= 0x11F &&
|
||||
!(modeblock[i].special & _USER_MODIFIED) &&
|
||||
((modeblock[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
|
||||
(modeblock[i].type == M_LIN24 && vesa12_modes_32bpp))) {
|
||||
/* ignore */
|
||||
i++;
|
||||
}
|
||||
/* ignore deleted modes */
|
||||
else if (modeblock[i].type == M_ERROR) {
|
||||
/* ignore */
|
||||
i++;
|
||||
}
|
||||
/* ignore disabled modes */
|
||||
else if (modeblock[i].special & _USER_DISABLED) {
|
||||
/* ignore */
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
|
||||
CurMode=&modeblock[i];
|
||||
@ -1764,6 +1784,7 @@ Bitu VideoModeMemSize(Bitu mode) {
|
||||
if (modelist[i].mode==mode) {
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
|
||||
if (modelist[i].mode >= 0x100 && modelist[i].mode <= 0x11F &&
|
||||
!(modelist[i].special & _USER_MODIFIED) &&
|
||||
((modelist[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
|
||||
(modelist[i].type == M_LIN24 && vesa12_modes_32bpp))) {
|
||||
/* ignore */
|
||||
@ -1807,3 +1828,302 @@ Bitu VideoModeMemSize(Bitu mode) {
|
||||
// Return 0 for all other types, those always fit in memory
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bitu INT10_WriteVESAModeList(Bitu max_modes);
|
||||
|
||||
/* ====================== VESAMOED.COM ====================== */
|
||||
class VESAMOED : public Program {
|
||||
public:
|
||||
void Run(void) {
|
||||
size_t array_i = 0;
|
||||
std::string arg,tmp;
|
||||
bool got_opt=false;
|
||||
int mode = -1;
|
||||
int fmt = -1;
|
||||
int w = -1,h = -1;
|
||||
int ch = -1;
|
||||
int newmode = -1;
|
||||
signed char enable = -1;
|
||||
bool doDelete = false;
|
||||
bool modefind = false;
|
||||
|
||||
cmd->BeginOpt();
|
||||
while (cmd->GetOpt(/*&*/arg)) {
|
||||
got_opt=true;
|
||||
if (arg == "?" || arg == "help") {
|
||||
doHelp();
|
||||
break;
|
||||
}
|
||||
else if (arg == "mode") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
|
||||
if (tmp == "find") {
|
||||
modefind = true;
|
||||
}
|
||||
else if (isdigit(tmp[0])) {
|
||||
mode = strtoul(tmp.c_str(),NULL,0);
|
||||
}
|
||||
else {
|
||||
WriteOut("Unknown mode '%s'\n",tmp.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (arg == "fmt") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
|
||||
if (tmp == "LIN4")
|
||||
fmt = M_LIN4;
|
||||
else if (tmp == "LIN8")
|
||||
fmt = M_LIN8;
|
||||
else if (tmp == "LIN15")
|
||||
fmt = M_LIN15;
|
||||
else if (tmp == "LIN16")
|
||||
fmt = M_LIN16;
|
||||
else if (tmp == "LIN24")
|
||||
fmt = M_LIN24;
|
||||
else if (tmp == "LIN32")
|
||||
fmt = M_LIN32;
|
||||
else if (tmp == "TEXT")
|
||||
fmt = M_TEXT;
|
||||
else {
|
||||
WriteOut("Unknown format '%s'\n",tmp.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (arg == "w") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
w = strtoul(tmp.c_str(),NULL,0);
|
||||
}
|
||||
else if (arg == "h") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
h = strtoul(tmp.c_str(),NULL,0);
|
||||
}
|
||||
else if (arg == "ch") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
ch = strtoul(tmp.c_str(),NULL,0);
|
||||
}
|
||||
else if (arg == "newmode") {
|
||||
cmd->NextOptArgv(/*&*/tmp);
|
||||
|
||||
if (isdigit(tmp[0])) {
|
||||
newmode = strtoul(tmp.c_str(),NULL,0);
|
||||
}
|
||||
else {
|
||||
WriteOut("Unknown newmode '%s'\n",tmp.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (arg == "delete") {
|
||||
doDelete = true;
|
||||
}
|
||||
// NTS: If you're wondering why we support disabled modes (modes listed but cannot be set),
|
||||
// there are plenty of scenarios on actual hardware where this occurs. Laptops, for
|
||||
// example, have SVGA chipsets that can go up to 1600x1200, but the BIOS will disable
|
||||
// anything above the native resolution of the laptop's LCD display unless an
|
||||
// external monitor is attached at boot-up.
|
||||
else if (arg == "disable") {
|
||||
enable = 0;
|
||||
}
|
||||
else if (arg == "enable") {
|
||||
enable = 1;
|
||||
}
|
||||
else {
|
||||
WriteOut("Unknown switch %s",arg.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
cmd->EndOpt();
|
||||
if(!got_opt) {
|
||||
doHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (modefind) {
|
||||
if (w < 0 && h < 0 && fmt < 0)
|
||||
return;
|
||||
|
||||
while (ModeList_VGA[array_i].mode != 0xFFFF) {
|
||||
bool match = true;
|
||||
|
||||
if (w > 0 && (Bitu)w != ModeList_VGA[array_i].swidth)
|
||||
match = false;
|
||||
else if (h > 0 && (Bitu)h != ModeList_VGA[array_i].sheight)
|
||||
match = false;
|
||||
else if (fmt >= 0 && (Bitu)fmt != ModeList_VGA[array_i].type)
|
||||
match = false;
|
||||
else if (ModeList_VGA[array_i].type == M_ERROR)
|
||||
match = false;
|
||||
else if (ModeList_VGA[array_i].mode <= 0x13)
|
||||
match = false;
|
||||
|
||||
if (!match)
|
||||
array_i++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (ModeList_VGA[array_i].mode != 0xFFFF) {
|
||||
if (ModeList_VGA[array_i].mode == (Bitu)mode)
|
||||
break;
|
||||
|
||||
array_i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ModeList_VGA[array_i].mode == 0xFFFF) {
|
||||
WriteOut("Mode not found\n");
|
||||
return;
|
||||
}
|
||||
else if (ModeList_VGA[array_i].mode <= 0x13) {
|
||||
WriteOut("Editing base VGA modes is not allowed\n");
|
||||
return;
|
||||
}
|
||||
else if (modefind) {
|
||||
WriteOut("Found mode 0x%x\n",(unsigned int)ModeList_VGA[array_i].mode);
|
||||
}
|
||||
|
||||
if (enable == 0)
|
||||
ModeList_VGA[array_i].special |= _USER_DISABLED;
|
||||
else if (enable == 1)
|
||||
ModeList_VGA[array_i].special &= ~_USER_DISABLED;
|
||||
|
||||
if (doDelete) {
|
||||
if (ModeList_VGA[array_i].type != M_ERROR)
|
||||
WriteOut("Mode 0x%x deleted\n",ModeList_VGA[array_i].mode);
|
||||
else
|
||||
WriteOut("Mode 0x%x already deleted\n",ModeList_VGA[array_i].mode);
|
||||
|
||||
ModeList_VGA[array_i].type = M_ERROR;
|
||||
INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fmt < 0 && ModeList_VGA[array_i].type == M_ERROR) {
|
||||
WriteOut("Mode 0x%x is still deleted. Set a format with -fmt to un-delete\n",ModeList_VGA[array_i].mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!modefind && (w > 0 || h > 0 || fmt >= 0 || ch > 0)) {
|
||||
WriteOut("Changing mode 0x%x parameters\n",(unsigned int)ModeList_VGA[array_i].mode);
|
||||
|
||||
ModeList_VGA[array_i].special |= _USER_MODIFIED;
|
||||
|
||||
if (fmt >= 0) {
|
||||
ModeList_VGA[array_i].type = (VGAModes)fmt;
|
||||
/* will require reprogramming width in some cases! */
|
||||
if (w < 0) w = ModeList_VGA[array_i].swidth;
|
||||
}
|
||||
if (w > 0) {
|
||||
/* enforce alignment to avoid problems with modesetting code */
|
||||
{
|
||||
unsigned int aln = 8;
|
||||
|
||||
if (ModeList_VGA[array_i].type == M_LIN4)
|
||||
aln = 16;
|
||||
|
||||
w += aln / 2;
|
||||
w -= w % aln;
|
||||
if (w == 0) w = aln;
|
||||
}
|
||||
|
||||
ModeList_VGA[array_i].swidth = (Bitu)w;
|
||||
if (ModeList_VGA[array_i].type == M_LIN15 || ModeList_VGA[array_i].type == M_LIN16) {
|
||||
ModeList_VGA[array_i].hdispend = (Bitu)w / 4;
|
||||
ModeList_VGA[array_i].htotal = ModeList_VGA[array_i].hdispend + 40;
|
||||
}
|
||||
else {
|
||||
ModeList_VGA[array_i].hdispend = (Bitu)w / 8;
|
||||
ModeList_VGA[array_i].htotal = ModeList_VGA[array_i].hdispend + 20;
|
||||
}
|
||||
}
|
||||
if (h > 0) {
|
||||
ModeList_VGA[array_i].sheight = (Bitu)h;
|
||||
|
||||
if (h >= 340)
|
||||
ModeList_VGA[array_i].special &= ~_REPEAT1;
|
||||
else
|
||||
ModeList_VGA[array_i].special |= _REPEAT1;
|
||||
|
||||
if (ModeList_VGA[array_i].special & _REPEAT1)
|
||||
ModeList_VGA[array_i].vdispend = (Bitu)h * 2;
|
||||
else
|
||||
ModeList_VGA[array_i].vdispend = (Bitu)h;
|
||||
|
||||
ModeList_VGA[array_i].vtotal = ModeList_VGA[array_i].vdispend + 49;
|
||||
}
|
||||
if (ch == 8 || ch == 14 || ch == 16)
|
||||
ModeList_VGA[array_i].cheight = (Bitu)ch;
|
||||
|
||||
ModeList_VGA[array_i].twidth = ModeList_VGA[array_i].swidth / ModeList_VGA[array_i].cwidth;
|
||||
ModeList_VGA[array_i].theight = ModeList_VGA[array_i].sheight / ModeList_VGA[array_i].cheight;
|
||||
INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
|
||||
}
|
||||
|
||||
if (newmode >= 0x40) {
|
||||
WriteOut("Mode 0x%x moved to mode 0x%x\n",(unsigned int)ModeList_VGA[array_i].mode,(unsigned int)newmode);
|
||||
ModeList_VGA[array_i].mode = (Bitu)newmode;
|
||||
INT10_WriteVESAModeList(int10.rom.vesa_alloc_modes);
|
||||
}
|
||||
|
||||
/* if the new mode cannot fit in available memory, then mark as disabled */
|
||||
{
|
||||
unsigned int pitch = 0;
|
||||
|
||||
switch (ModeList_VGA[array_i].type) {
|
||||
case M_LIN4:
|
||||
pitch = (ModeList_VGA[array_i].swidth / 8) * 4; /* not totally accurate but close enough */
|
||||
break;
|
||||
case M_LIN8:
|
||||
pitch = ModeList_VGA[array_i].swidth;
|
||||
break;
|
||||
case M_LIN15:
|
||||
case M_LIN16:
|
||||
pitch = ModeList_VGA[array_i].swidth * 2;
|
||||
break;
|
||||
case M_LIN24:
|
||||
pitch = ModeList_VGA[array_i].swidth * 3;
|
||||
break;
|
||||
case M_LIN32:
|
||||
pitch = ModeList_VGA[array_i].swidth * 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pitch * ModeList_VGA[array_i].sheight) > vga.mem.memsize) {
|
||||
/* NTS: Actually we don't mark as disabled, the VESA mode query function will
|
||||
* report as disabled automatically for the same check we do. This just
|
||||
* lets the user know. */
|
||||
WriteOut("WARNING: Mode %u x %u as specified exceeds video memory, will be disabled\n",
|
||||
ModeList_VGA[array_i].swidth,
|
||||
ModeList_VGA[array_i].sheight);
|
||||
}
|
||||
}
|
||||
}
|
||||
void doHelp(void) {
|
||||
WriteOut("VESAMOED VESA BIOS mode editor utility\n");
|
||||
WriteOut("\n");
|
||||
WriteOut("NOTE: Due to architectual limitations of VBE emulation,\n");
|
||||
WriteOut(" Adding new modes is not allowed.\n");
|
||||
WriteOut("\n");
|
||||
WriteOut(" -mode <x> VBE video mode to edit.\n");
|
||||
WriteOut(" Specify video mode in decimal or hexadecimal,\n");
|
||||
WriteOut(" or specify 'find' to match by fmt, width, height.\n");
|
||||
WriteOut(" -fmt <x> Change pixel format, or mode to find.\n");
|
||||
WriteOut(" LIN4, LIN8, LIN15, LIN16,\n");
|
||||
WriteOut(" LIN24, LIN32, TEXT\n");
|
||||
WriteOut(" -w <x> Change width (in pixels), or mode to find.\n");
|
||||
WriteOut(" -h <x> Change height (in pixels), or mode to find.\n");
|
||||
WriteOut(" -ch <x> Change char height (in pixels), or mode to find.\n");
|
||||
WriteOut(" -newmode <x> Change video mode number\n");
|
||||
WriteOut(" -delete Delete video mode\n");
|
||||
WriteOut(" -disable Disable video mode (list but do not allow setting)\n");
|
||||
WriteOut(" -enable Enable video mode\n");
|
||||
}
|
||||
};
|
||||
|
||||
void VESAMOED_ProgramStart(Program * * make) {
|
||||
*make=new VESAMOED;
|
||||
}
|
||||
|
||||
|
@ -169,17 +169,20 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) {
|
||||
|
||||
mode&=0x3fff; // vbe2 compatible, ignore lfb and keep screen content bits
|
||||
if (mode<0x100) return 0x01;
|
||||
if (svga.accepts_mode) {
|
||||
if (!svga.accepts_mode(mode)) return 0x01;
|
||||
}
|
||||
while (ModeList_VGA[i].mode!=0xffff) {
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
|
||||
if (ModeList_VGA[i].mode >= 0x100 && ModeList_VGA[i].mode <= 0x11F &&
|
||||
!(ModeList_VGA[i].special & _USER_MODIFIED) &&
|
||||
((ModeList_VGA[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
|
||||
(ModeList_VGA[i].type == M_LIN24 && vesa12_modes_32bpp))) {
|
||||
/* ignore */
|
||||
i++;
|
||||
}
|
||||
/* ignore deleted modes */
|
||||
else if (ModeList_VGA[i].type == M_ERROR) {
|
||||
/* ignore */
|
||||
i++;
|
||||
}
|
||||
else if (mode==ModeList_VGA[i].mode)
|
||||
goto foundit;
|
||||
else
|
||||
@ -190,6 +193,15 @@ foundit:
|
||||
if ((int10.vesa_oldvbe) && (ModeList_VGA[i].mode>=0x120)) return 0x01;
|
||||
VideoModeBlock * mblock=&ModeList_VGA[i];
|
||||
|
||||
/* Don't allow querying modes the SVGA card does not accept,
|
||||
* unless the user modified the mode. */
|
||||
if (svga.accepts_mode && !(mblock->special & _USER_MODIFIED)) {
|
||||
if (!svga.accepts_mode(mode)) return 0x01;
|
||||
}
|
||||
|
||||
/* do not return information on deleted modes */
|
||||
if (mblock->type == M_ERROR) return 0x01;
|
||||
|
||||
bool allow_res = allow_vesa_lowres_modes ||
|
||||
(ModeList_VGA[i].swidth >= 640 && ModeList_VGA[i].sheight >= 400);
|
||||
|
||||
@ -300,7 +312,7 @@ foundit:
|
||||
pageSize &= ~0xFFFFu;
|
||||
}
|
||||
Bitu pages = 0;
|
||||
if (pageSize > vga.mem.memsize) {
|
||||
if (pageSize > vga.mem.memsize || (mblock->special & _USER_DISABLED)) {
|
||||
// mode not supported by current hardware configuration
|
||||
modeAttributes &= ~0x1;
|
||||
} else if (pageSize) {
|
||||
@ -608,72 +620,104 @@ static Bitu VESA_PMSetStart(void) {
|
||||
|
||||
extern int vesa_modelist_cap;
|
||||
|
||||
Bitu INT10_WriteVESAModeList(Bitu max_modes) {
|
||||
Bitu mode_wptr = int10.rom.vesa_modes;
|
||||
Bitu i=0,modecount=0;
|
||||
|
||||
//TODO Maybe add normal vga modes too, but only seems to complicate things
|
||||
while (ModeList_VGA[i].mode!=0xffff) {
|
||||
bool canuse_mode=false;
|
||||
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
|
||||
if (ModeList_VGA[i].mode >= 0x100 && ModeList_VGA[i].mode <= 0x11F &&
|
||||
((ModeList_VGA[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
|
||||
(ModeList_VGA[i].type == M_LIN24 && vesa12_modes_32bpp))) {
|
||||
/* ignore */
|
||||
}
|
||||
/* ignore deleted modes */
|
||||
else if (ModeList_VGA[i].type == M_ERROR) {
|
||||
/* ignore */
|
||||
}
|
||||
else {
|
||||
/* If there is no "accepts mode" then accept.
|
||||
*
|
||||
* If the user modified the mode, then accept.
|
||||
* If the mode exceeds video memory, then the mode will be reported as not supported by VESA BIOS functions.
|
||||
*
|
||||
* If the SVGA card would accept the mode (generally it's a memsize check), then accept. */
|
||||
if (!svga.accepts_mode)
|
||||
canuse_mode=true;
|
||||
else if (ModeList_VGA[i].special & _USER_MODIFIED)
|
||||
canuse_mode=true;
|
||||
else if (svga.accepts_mode(ModeList_VGA[i].mode))
|
||||
canuse_mode=true;
|
||||
|
||||
if (canuse_mode) {
|
||||
if (ModeList_VGA[i].mode >= 0x100) {
|
||||
bool allow_res = allow_vesa_lowres_modes ||
|
||||
(ModeList_VGA[i].swidth >= 640 && ModeList_VGA[i].sheight >= 400);
|
||||
|
||||
switch (ModeList_VGA[i].type) {
|
||||
case M_LIN32: canuse_mode=allow_vesa_32bpp && allow_res; break;
|
||||
case M_LIN24: canuse_mode=allow_vesa_24bpp && allow_res; break;
|
||||
case M_LIN16: canuse_mode=allow_vesa_16bpp && allow_res; break;
|
||||
case M_LIN15: canuse_mode=allow_vesa_15bpp && allow_res; break;
|
||||
case M_LIN8: canuse_mode=allow_vesa_8bpp && allow_res; break;
|
||||
case M_LIN4: canuse_mode=allow_vesa_4bpp; break;
|
||||
case M_TEXT: canuse_mode=allow_vesa_tty; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canuse_mode && vesa_modelist_cap > 0 && (unsigned int)modecount >= (unsigned int)vesa_modelist_cap)
|
||||
canuse_mode = false;
|
||||
if (canuse_mode && (unsigned int)modecount >= (unsigned int)max_modes)
|
||||
canuse_mode = false;
|
||||
|
||||
if (ModeList_VGA[i].type != M_TEXT) {
|
||||
if (canuse_mode && vesa_mode_width_cap > 0 && (unsigned int)ModeList_VGA[i].swidth > (unsigned int)vesa_mode_width_cap)
|
||||
canuse_mode = false;
|
||||
|
||||
if (canuse_mode && vesa_mode_height_cap > 0 && (unsigned int)ModeList_VGA[i].sheight > (unsigned int)vesa_mode_height_cap)
|
||||
canuse_mode = false;
|
||||
}
|
||||
|
||||
if (ModeList_VGA[i].mode>=0x100 && canuse_mode) {
|
||||
if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
|
||||
phys_writew(PhysMake(0xc000,mode_wptr),ModeList_VGA[i].mode);
|
||||
mode_wptr+=2;
|
||||
modecount++;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(modecount <= int10.rom.vesa_alloc_modes); /* do not overrun the buffer */
|
||||
|
||||
/* after the buffer, is 0xFFFF */
|
||||
phys_writew(PhysMake(0xc000,mode_wptr),0xFFFF);
|
||||
mode_wptr+=2;
|
||||
|
||||
return modecount;
|
||||
}
|
||||
|
||||
void INT10_SetupVESA(void) {
|
||||
Bitu i,modecount=0;
|
||||
|
||||
/* BUGFIX: Generating VESA BIOS data when machine=ega or machine=vgaonly is dumb.
|
||||
* Stop wasting ROM space! --J.C. */
|
||||
if (machine != MCH_VGA) return;
|
||||
if (svgaCard == SVGA_None) return;
|
||||
|
||||
/* Put the mode list somewhere in memory */
|
||||
Bitu i,modecount=0;
|
||||
i=0;
|
||||
int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used);
|
||||
//TODO Maybe add normal vga modes too, but only seems to complicate things
|
||||
while (ModeList_VGA[i].mode!=0xffff) {
|
||||
bool canuse_mode=false;
|
||||
|
||||
/* Hack for VBE 1.2 modes and 24/32bpp ambiguity */
|
||||
if (ModeList_VGA[i].mode >= 0x100 && ModeList_VGA[i].mode <= 0x11F &&
|
||||
((ModeList_VGA[i].type == M_LIN32 && !vesa12_modes_32bpp) ||
|
||||
(ModeList_VGA[i].type == M_LIN24 && vesa12_modes_32bpp))) {
|
||||
/* ignore */
|
||||
}
|
||||
else {
|
||||
if (!svga.accepts_mode)
|
||||
canuse_mode=true;
|
||||
else if (svga.accepts_mode(ModeList_VGA[i].mode))
|
||||
canuse_mode=true;
|
||||
|
||||
if (canuse_mode) {
|
||||
if (ModeList_VGA[i].mode >= 0x100) {
|
||||
bool allow_res = allow_vesa_lowres_modes ||
|
||||
(ModeList_VGA[i].swidth >= 640 && ModeList_VGA[i].sheight >= 400);
|
||||
|
||||
switch (ModeList_VGA[i].type) {
|
||||
case M_LIN32: canuse_mode=allow_vesa_32bpp && allow_res; break;
|
||||
case M_LIN24: canuse_mode=allow_vesa_24bpp && allow_res; break;
|
||||
case M_LIN16: canuse_mode=allow_vesa_16bpp && allow_res; break;
|
||||
case M_LIN15: canuse_mode=allow_vesa_15bpp && allow_res; break;
|
||||
case M_LIN8: canuse_mode=allow_vesa_8bpp && allow_res; break;
|
||||
case M_LIN4: canuse_mode=allow_vesa_4bpp; break;
|
||||
case M_TEXT: canuse_mode=allow_vesa_tty; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canuse_mode && vesa_modelist_cap > 0 && (unsigned int)modecount >= (unsigned int)vesa_modelist_cap)
|
||||
canuse_mode = false;
|
||||
|
||||
if (ModeList_VGA[i].type != M_TEXT) {
|
||||
if (canuse_mode && vesa_mode_width_cap > 0 && (unsigned int)ModeList_VGA[i].swidth > (unsigned int)vesa_mode_width_cap)
|
||||
canuse_mode = false;
|
||||
|
||||
if (canuse_mode && vesa_mode_height_cap > 0 && (unsigned int)ModeList_VGA[i].sheight > (unsigned int)vesa_mode_height_cap)
|
||||
canuse_mode = false;
|
||||
}
|
||||
|
||||
if (ModeList_VGA[i].mode>=0x100 && canuse_mode) {
|
||||
if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
|
||||
phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode);
|
||||
int10.rom.used+=2;
|
||||
modecount++;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
int10.rom.vesa_alloc_modes = ~0;
|
||||
int10.rom.vesa_modes = RealMake(0xc000,int10.rom.used);
|
||||
modecount = INT10_WriteVESAModeList(0xFFFF/*max mode count*/);
|
||||
int10.rom.vesa_alloc_modes = (Bit16u)modecount;
|
||||
int10.rom.used += modecount * 2u;
|
||||
phys_writew(PhysMake(0xc000,int10.rom.used),0xffff);
|
||||
int10.rom.used+=2;
|
||||
int10.rom.oemstring=RealMake(0xc000,int10.rom.used);
|
||||
|
@ -151,53 +151,19 @@ Bitu OUTPUT_DIRECT3D_SetSize()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fixedWidth && fixedHeight)
|
||||
sdl.clip.x = sdl.clip.y = 0;
|
||||
if (fixedWidth && fixedHeight)
|
||||
{
|
||||
sdl.clip.w = fixedWidth;
|
||||
sdl.clip.h = fixedHeight;
|
||||
|
||||
if (render.aspect)
|
||||
{
|
||||
if (fixedWidth > sdl.srcAspect.xToY * fixedHeight) // output broader than input => black bars left and right
|
||||
{
|
||||
sdl.clip.w = static_cast<int>(fixedHeight * sdl.srcAspect.xToY);
|
||||
}
|
||||
else // black bars top and bottom
|
||||
{
|
||||
sdl.clip.h = static_cast<int>(fixedWidth * sdl.srcAspect.yToX);
|
||||
}
|
||||
}
|
||||
|
||||
sdl.clip.x = (fixedWidth - sdl.clip.w) / 2;
|
||||
sdl.clip.y = (fixedHeight - sdl.clip.h) / 2;
|
||||
windowWidth = fixedWidth;
|
||||
windowHeight = fixedHeight;
|
||||
sdl.clip.w = windowWidth = fixedWidth;
|
||||
sdl.clip.h = windowHeight = fixedHeight;
|
||||
if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, fixedWidth, fixedHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdl.clip.w = windowWidth = (Bit16u)(sdl.draw.width * sdl.draw.scalex);
|
||||
sdl.clip.h = windowHeight = (Bit16u)(sdl.draw.height * sdl.draw.scaley);
|
||||
|
||||
if (render.aspect) {
|
||||
// we solve problem of aspect ratio based window extension here when window size is not set explicitly
|
||||
if (windowWidth * sdl.srcAspect.y != windowHeight * sdl.srcAspect.x)
|
||||
{
|
||||
// abnormal aspect ratio detected, apply correction
|
||||
if (windowWidth * sdl.srcAspect.y > windowHeight * sdl.srcAspect.x)
|
||||
{
|
||||
// wide pixel ratio, height should be extended to fit
|
||||
sdl.clip.h = windowHeight = (Bitu)floor((double)windowWidth * sdl.srcAspect.y / sdl.srcAspect.x + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// long pixel ratio, width should be extended
|
||||
sdl.clip.w = windowWidth = (Bitu)floor((double)windowHeight * sdl.srcAspect.x / sdl.srcAspect.y + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdl.clip.x = (windowWidth - sdl.clip.w) / 2;
|
||||
sdl.clip.y = (windowHeight - sdl.clip.h) / 2;
|
||||
windowWidth = (Bit16u)(sdl.draw.width * sdl.draw.scalex);
|
||||
windowHeight = (Bit16u)(sdl.draw.height * sdl.draw.scaley);
|
||||
if (render.aspect) aspectCorrectExtend(windowWidth, windowHeight);
|
||||
sdl.clip.w = windowWidth; sdl.clip.h = windowHeight;
|
||||
}
|
||||
|
||||
// when xBRZ scaler is used, we can adjust render target size to exactly what xBRZ scaler will output, leaving final scaling to default D3D scaler / shaders
|
||||
@ -373,4 +339,4 @@ void OUTPUT_DIRECT3D_Shutdown()
|
||||
delete d3d;
|
||||
}
|
||||
|
||||
#endif /*C_DIRECT3D*/
|
||||
#endif /*C_DIRECT3D*/
|
||||
|
@ -82,10 +82,10 @@ static SDL_Surface* SetupSurfaceScaledOpenGL(Bit32u sdl_flags, Bit32u bpp)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Voodoo_OGL_GetWidth() != 0 && Voodoo_OGL_GetHeight() != 0 && Voodoo_OGL_Active() && sdl.desktop.prevent_fullscreen)
|
||||
sdl.clip.x = 0; sdl.clip.y = 0;
|
||||
if (Voodoo_OGL_GetWidth() != 0 && Voodoo_OGL_GetHeight() != 0 && Voodoo_OGL_Active() && sdl.desktop.prevent_fullscreen)
|
||||
{
|
||||
/* 3Dfx openGL do not allow resize */
|
||||
sdl.clip.x = 0; sdl.clip.y = 0;
|
||||
sdl.clip.w = windowWidth = (Bit16u)Voodoo_OGL_GetWidth();
|
||||
sdl.clip.h = windowHeight = (Bit16u)Voodoo_OGL_GetHeight();
|
||||
}
|
||||
@ -93,48 +93,14 @@ static SDL_Surface* SetupSurfaceScaledOpenGL(Bit32u sdl_flags, Bit32u bpp)
|
||||
{
|
||||
sdl.clip.w = windowWidth = fixedWidth;
|
||||
sdl.clip.h = windowHeight = fixedHeight;
|
||||
|
||||
// adjust resulting image aspect ratio
|
||||
if (render.aspect)
|
||||
{
|
||||
if (fixedWidth > sdl.srcAspect.xToY * fixedHeight) // output broader than input => black bars left and right
|
||||
{
|
||||
sdl.clip.w = static_cast<int>(fixedHeight * sdl.srcAspect.xToY);
|
||||
}
|
||||
else // black bars top and bottom
|
||||
{
|
||||
sdl.clip.h = static_cast<int>(fixedWidth * sdl.srcAspect.yToX);
|
||||
}
|
||||
}
|
||||
|
||||
sdl.clip.x = (fixedWidth - sdl.clip.w) / 2;
|
||||
sdl.clip.y = (fixedHeight - sdl.clip.h) / 2;
|
||||
if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, fixedWidth, fixedHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdl.clip.w = windowWidth = (Bit16u)(sdl.draw.width * sdl.draw.scalex);
|
||||
sdl.clip.h = windowHeight = (Bit16u)(sdl.draw.height * sdl.draw.scaley);
|
||||
|
||||
if (render.aspect) {
|
||||
// we solve problem of aspect ratio based window extension here when window size is not set explicitly
|
||||
if (windowWidth * sdl.srcAspect.y != windowHeight * sdl.srcAspect.x)
|
||||
{
|
||||
// abnormal aspect ratio detected, apply correction
|
||||
if (windowWidth * sdl.srcAspect.y > windowHeight * sdl.srcAspect.x)
|
||||
{
|
||||
// wide pixel ratio, height should be extended to fit
|
||||
sdl.clip.h = windowHeight = (Bitu)floor((double)windowWidth * sdl.srcAspect.y / sdl.srcAspect.x + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// long pixel ratio, width should be extended
|
||||
sdl.clip.w = windowWidth = (Bitu)floor((double)windowHeight * sdl.srcAspect.x / sdl.srcAspect.y + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdl.clip.x = (windowWidth - sdl.clip.w) / 2;
|
||||
sdl.clip.y = (windowHeight - sdl.clip.h) / 2;
|
||||
windowWidth = (Bit16u)(sdl.draw.width * sdl.draw.scalex);
|
||||
windowHeight = (Bit16u)(sdl.draw.height * sdl.draw.scaley);
|
||||
if (render.aspect) aspectCorrectExtend(windowWidth, windowHeight);
|
||||
sdl.clip.w = windowWidth; sdl.clip.h = windowHeight;
|
||||
}
|
||||
|
||||
LOG(LOG_MISC, LOG_DEBUG)("GFX_SetSize OpenGL window=%ux%u clip=x,y,w,h=%d,%d,%d,%d",
|
||||
@ -628,4 +594,4 @@ void OUTPUT_OPENGL_Shutdown()
|
||||
// nothing to shutdown (yet?)
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -81,36 +81,11 @@ void OUTPUT_SURFACE_EndUpdate(const Bit16u *changedLines)
|
||||
const int srcHeight = sdl.draw.height;
|
||||
if (sdl_xbrz.renderbuf.size() == srcWidth * srcHeight && srcWidth > 0 && srcHeight > 0)
|
||||
{
|
||||
#if 1
|
||||
// please use sdl.clip to keep screen positioning consistent with the rest of the emulator
|
||||
int clipWidth = sdl.clip.w;
|
||||
int clipHeight = sdl.clip.h;
|
||||
int clipX = sdl.clip.x;
|
||||
int clipY = sdl.clip.y;
|
||||
#else
|
||||
// we assume render buffer is *not* scaled!
|
||||
// recalculation to full output width/height is deliberate here, with xBRZ we nicely fill entire output size!
|
||||
const int outputHeight = sdl.surface->h;
|
||||
const int outputWidth = sdl.surface->w;
|
||||
|
||||
int clipWidth = outputWidth;
|
||||
int clipHeight = outputHeight;
|
||||
int clipX = 0;
|
||||
int clipY = 0;
|
||||
|
||||
if (render.aspect) {
|
||||
if (outputWidth > sdl.srcAspect.xToY * outputHeight) // output broader than input => black bars left and right
|
||||
{
|
||||
clipWidth = static_cast<int>(outputHeight * sdl.srcAspect.xToY);
|
||||
clipX = (outputWidth - clipWidth) / 2;
|
||||
}
|
||||
else // black bars top and bottom
|
||||
{
|
||||
clipHeight = static_cast<int>(outputWidth * sdl.srcAspect.yToX);
|
||||
clipY = (outputHeight - clipHeight) / 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 1. xBRZ-scale render buffer into xbrz pixel buffer
|
||||
int xbrzWidth = 0;
|
||||
|
@ -93,23 +93,7 @@ retry:
|
||||
#if C_XBRZ || C_SURFACE_POSTRENDER_ASPECT
|
||||
// there is a small problem we need to solve here: aspect corrected windows can be smaller than needed due to source with non-4:3 pixel ratio
|
||||
// if we detect non-4:3 pixel ratio here with aspect correction on, we correct it so original fits into resized window properly
|
||||
if (render.aspect)
|
||||
{
|
||||
if (width * sdl.srcAspect.y != height * sdl.srcAspect.x)
|
||||
{
|
||||
// abnormal aspect ratio detected, apply correction
|
||||
if (width * sdl.srcAspect.y > height * sdl.srcAspect.x)
|
||||
{
|
||||
// wide pixel ratio, height should be extended to fit
|
||||
height = (Bitu)floor((double)width * sdl.srcAspect.y / sdl.srcAspect.x + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// long pixel ratio, width should be extended
|
||||
width = (Bitu)floor((double)height * sdl.srcAspect.x / sdl.srcAspect.y + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (render.aspect) aspectCorrectExtend(width, height);
|
||||
#endif
|
||||
|
||||
sdl.clip.w = width; sdl.clip.h = height;
|
||||
@ -135,29 +119,7 @@ retry:
|
||||
sdl.clip.x = sdl.clip.y = 0;
|
||||
sdl.clip.w = sdl.desktop.full.width;
|
||||
sdl.clip.h = sdl.desktop.full.height;
|
||||
|
||||
if (render.aspect) {
|
||||
int ax,ay;
|
||||
int sh = sdl.desktop.full.height;
|
||||
int sw = (int)floor(sdl.desktop.full.height * sdl.srcAspect.xToY);
|
||||
|
||||
if (sw > sdl.desktop.full.width) {
|
||||
sh = (sh * sdl.desktop.full.width) / sw;
|
||||
sw = sdl.desktop.full.width;
|
||||
}
|
||||
|
||||
ax = (sdl.desktop.full.width - sw) / 2;
|
||||
ay = (sdl.desktop.full.height - sh) / 2;
|
||||
if (ax < 0) ax = 0;
|
||||
if (ay < 0) ay = 0;
|
||||
sdl.clip.x = ax;
|
||||
sdl.clip.y = ay;
|
||||
sdl.clip.w = sw;
|
||||
sdl.clip.h = sh;
|
||||
|
||||
assert((sdl.clip.x+sdl.clip.w) <= sdl.desktop.full.width);
|
||||
assert((sdl.clip.y+sdl.clip.h) <= sdl.desktop.full.height);
|
||||
}
|
||||
if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, sdl.desktop.full.width, sdl.desktop.full.height);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -231,28 +193,7 @@ retry:
|
||||
sdl.clip.x = sdl.clip.y = 0;
|
||||
sdl.clip.w = final_width;
|
||||
sdl.clip.h = final_height;
|
||||
|
||||
if (render.aspect) {
|
||||
int sh = final_height;
|
||||
int sw = (int)floor(final_height * sdl.srcAspect.xToY);
|
||||
|
||||
if (sw > final_width) {
|
||||
sh = (sh * final_width) / sw;
|
||||
sw = final_width;
|
||||
}
|
||||
|
||||
ax = (final_width - sw) / 2;
|
||||
ay = (final_height - sh) / 2;
|
||||
if (ax < 0) ax = 0;
|
||||
if (ay < 0) ay = 0;
|
||||
sdl.clip.x = ax;
|
||||
sdl.clip.y = ay;
|
||||
sdl.clip.w = sw;
|
||||
sdl.clip.h = sh;
|
||||
|
||||
assert((sdl.clip.x+sdl.clip.w) <= final_width);
|
||||
assert((sdl.clip.y+sdl.clip.h) <= final_height);
|
||||
}
|
||||
if (render.aspect) aspectCorrectFitClip(sdl.clip.w, sdl.clip.h, sdl.clip.x, sdl.clip.y, final_width, final_height);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1,6 +1,13 @@
|
||||
#ifndef DOSBOX_OUTPUT_TOOLS_H
|
||||
#define DOSBOX_OUTPUT_TOOLS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "sdlmain.h"
|
||||
|
||||
// common headers and static routines reused in different outputs go there
|
||||
|
||||
static inline int int_log2(int val)
|
||||
@ -10,4 +17,46 @@ static inline int int_log2(int val)
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif
|
||||
template <class WH>
|
||||
inline void aspectCorrectExtend(volatile WH &width, volatile WH &height)
|
||||
{
|
||||
if (width * sdl.srcAspect.y != height * sdl.srcAspect.x)
|
||||
{
|
||||
// abnormal aspect ratio detected, apply correction
|
||||
if (width * sdl.srcAspect.y > height * sdl.srcAspect.x)
|
||||
{
|
||||
// wide pixel ratio, height should be extended to fit
|
||||
height = (WH)floor((double)width * sdl.srcAspect.yToX + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// long pixel ratio, width should be extended
|
||||
width = (WH)floor((double)height * sdl.srcAspect.xToY + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class WH, class XY, class TWH>
|
||||
inline void aspectCorrectFitClip(volatile WH &clipW, volatile WH &clipH, volatile XY &clipX, volatile XY &clipY, const TWH fullW, const TWH fullH)
|
||||
{
|
||||
XY ax, ay;
|
||||
WH sh = fullH;
|
||||
WH sw = (WH)floor((double)fullH * sdl.srcAspect.xToY);
|
||||
|
||||
if (sw > fullW) {
|
||||
sh = (WH)floor(((double)sh * fullW) / sw);
|
||||
sw = fullW;
|
||||
}
|
||||
|
||||
ax = (WH)floor((fullW - sw) / 2);
|
||||
ay = (WH)floor((fullH - sh) / 2);
|
||||
if (ax < 0) ax = 0;
|
||||
if (ay < 0) ay = 0;
|
||||
|
||||
clipX = ax; clipY = ay; clipW = sw; clipH = sh;
|
||||
|
||||
assert((sdl.clip.x + sdl.clip.w) <= sdl.desktop.full.width);
|
||||
assert((sdl.clip.y + sdl.clip.h) <= sdl.desktop.full.height);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -45,8 +45,17 @@
|
||||
/* Define to 1 to use inlined memory functions in cpu core */
|
||||
#define C_CORE_INLINE 1
|
||||
|
||||
/* Define to 1 if you have the <d3d9.h> header file. */
|
||||
#if !defined(C_SDL2)
|
||||
#define HAVE_D3D9_H 1
|
||||
#endif
|
||||
|
||||
#if HAVE_D3D9_H
|
||||
/* Define to 1 if you want to add Direct3D output to the list of available outputs */
|
||||
#define C_DIRECT3D 1
|
||||
/* Define to 1 to use Direct3D shaders, requires d3d9.h and libd3dx9 */
|
||||
#define C_D3DSHADERS 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 to enable internal debugger, requires libcurses */
|
||||
#define C_DEBUG 1
|
||||
@ -151,11 +160,6 @@
|
||||
/* Define to 1 to use ALSA for MIDI */
|
||||
#undef HAVE_ALSA
|
||||
|
||||
/* Define to 1 if you have the <d3d9.h> header file. */
|
||||
#if !defined(C_SDL2)
|
||||
#define HAVE_D3D9_H 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the <ddraw.h> header file. */
|
||||
#if !defined(C_SDL2)
|
||||
#define HAVE_DDRAW_H 1
|
||||
|
@ -1128,13 +1128,13 @@ static int keybhack_jp = 0;
|
||||
static int keybhack_jp_ro = -1;
|
||||
static int keybhack_jp_yen = -1;
|
||||
|
||||
void SDL1_hax_X11_clearfix(void) {
|
||||
void DECLSPEC SDL1_hax_X11_clearfix(void) {
|
||||
keybhack_jp = 0;
|
||||
keybhack_jp_ro = -1;
|
||||
keybhack_jp_yen = -1;
|
||||
}
|
||||
|
||||
void SDL1_hax_X11_jpfix(int ro_scan,int yen_scan) {
|
||||
void DECLSPEC SDL1_hax_X11_jpfix(int ro_scan,int yen_scan) {
|
||||
SDL1_hax_X11_clearfix();
|
||||
|
||||
keybhack_jp = 1;
|
||||
|
@ -165,7 +165,7 @@ SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return)
|
||||
*/
|
||||
#ifdef LONG64
|
||||
SDL_X11_MODULE(IO_32BIT)
|
||||
SDL_X11_SYM(int,_XData32,(Display *dpy,register long *data,unsigned len),(dpy,data,len),return)
|
||||
SDL_X11_SYM(int,_XData32,(Display *dpy,register _Xconst long *data,unsigned len),(dpy,data,len),return)
|
||||
SDL_X11_SYM(void,_XRead32,(Display *dpy,register long *data,long len),(dpy,data,len),)
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user