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:
Jonathan Campbell 2018-07-05 08:01:55 -07:00 committed by GitHub
commit 59b1f08837
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 738 additions and 270 deletions

View 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.

View File

@ -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"

View File

@ -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*/

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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*/

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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