- Implemented some more controllers for the OPL player:

* RPN select (controllers 100 and 101)
  *  RPN 0 (pitch bend sensitivity)
  * NPRN select (controllers 98 and 99)
  * Data entry (controllers 6 and 38)
  * All notes off (controller 123)
  * All sounds off (controller 120)
  * Reset controllers (controller 121)


SVN r1195 (trunk)
This commit is contained in:
Randy Heit 2008-09-05 02:04:50 +00:00
parent 49565ccb84
commit fae19e87b7
8 changed files with 321 additions and 65 deletions

View file

@ -82,9 +82,9 @@ void musicBlock::writeModulation(uint slot, struct OPL2instrument *instr, int st
instr->trem_vibr_2 | state); instr->trem_vibr_2 | state);
} }
uint musicBlock::calcVolume(uint channelVolume, uint MUSvolume, uint noteVolume) uint musicBlock::calcVolume(uint channelVolume, uint channelExpression, uint noteVolume)
{ {
noteVolume = ((ulong)channelVolume * MUSvolume * noteVolume) / (256*127); noteVolume = ((ulong)channelVolume * channelExpression * noteVolume) / (127*127);
if (noteVolume > 127) if (noteVolume > 127)
return 127; return 127;
else else
@ -107,7 +107,8 @@ int musicBlock::occupyChannel(uint slot, uint channel,
volume = driverdata.channelLastVolume[channel]; volume = driverdata.channelLastVolume[channel];
else else
driverdata.channelLastVolume[channel] = volume; driverdata.channelLastVolume[channel] = volume;
ch->realvolume = calcVolume(driverdata.channelVolume[channel], 256, ch->volume = volume); ch->realvolume = calcVolume(driverdata.channelVolume[channel],
driverdata.channelExpression[channel], ch->volume = volume);
if (instrument->flags & FL_FIXED_PITCH) if (instrument->flags & FL_FIXED_PITCH)
note = instrument->note; note = instrument->note;
else if (channel == PERCUSSION) else if (channel == PERCUSSION)
@ -273,7 +274,9 @@ void musicBlock::OPLpitchWheel(uint channel, int pitch)
uint i; uint i;
uint id = channel; uint id = channel;
pitch >>= 7; // Convert pitch from 14-bit to 7-bit, then scale it, since the player
// code only understands sensitivities of 2 semitones.
pitch = (pitch - 8192) * driverdata.channelPitchSens[channel] / (200 * 128) + 64;
driverdata.channelPitch[channel] = pitch; driverdata.channelPitch[channel] = pitch;
for(i = 0; i < io->OPLchannels; i++) for(i = 0; i < io->OPLchannels; i++)
{ {
@ -298,6 +301,7 @@ void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
case ctrlPatch: /* change instrument */ case ctrlPatch: /* change instrument */
OPLprogramChange(channel, value); OPLprogramChange(channel, value);
break; break;
case ctrlModulation: case ctrlModulation:
driverdata.channelModulation[channel] = value; driverdata.channelModulation[channel] = value;
for(i = 0; i < io->OPLchannels; i++) for(i = 0; i < io->OPLchannels; i++)
@ -320,19 +324,28 @@ void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
} }
} }
break; break;
case ctrlVolume: /* change volume */ case ctrlVolume: /* change volume */
driverdata.channelVolume[channel] = value; driverdata.channelVolume[channel] = value;
/* fall-through */
case ctrlExpression: /* change expression */
if (controller == ctrlExpression)
{
driverdata.channelExpression[channel] = value;
}
for(i = 0; i < io->OPLchannels; i++) for(i = 0; i < io->OPLchannels; i++)
{ {
struct channelEntry *ch = &channels[i]; struct channelEntry *ch = &channels[i];
if (ch->channel == id) if (ch->channel == id)
{ {
ch->time = MLtime; ch->time = MLtime;
ch->realvolume = calcVolume(value, 256, ch->volume); ch->realvolume = calcVolume(driverdata.channelVolume[channel],
driverdata.channelExpression[channel], ch->volume);
io->OPLwriteVolume(i, ch->instr, ch->realvolume); io->OPLwriteVolume(i, ch->instr, ch->realvolume);
} }
} }
break; break;
case ctrlPan: /* change pan (balance) */ case ctrlPan: /* change pan (balance) */
driverdata.channelPan[channel] = value -= 64; driverdata.channelPan[channel] = value -= 64;
for(i = 0; i < io->OPLchannels; i++) for(i = 0; i < io->OPLchannels; i++)
@ -345,14 +358,76 @@ void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
} }
} }
break; break;
case ctrlSustainPedal: /* change sustain pedal (hold) */ case ctrlSustainPedal: /* change sustain pedal (hold) */
driverdata.channelSustain[channel] = value; driverdata.channelSustain[channel] = value;
if (value < 0x40) if (value < 0x40)
releaseSustain(channel); releaseSustain(channel);
break; break;
case ctrlNotesOff: /* turn off all notes that are not sustained */
for (i = 0; i < io->OPLchannels; ++i)
{
if (channels[i].channel == id)
{
if (driverdata.channelSustain[id] < 0x40)
releaseChannel(i, 0);
else
channels[i].flags |= CH_SUSTAIN;
}
}
break;
case ctrlSoundsOff: /* release all notes for this channel */
for (i = 0; i < io->OPLchannels; ++i)
{
if (channels[i].channel == id)
{
releaseChannel(i, 0);
}
}
break;
case ctrlRPNHi:
driverdata.channelRPN[id] = (driverdata.channelRPN[id] & 0x007F) | (value << 7);
break;
case ctrlRPNLo:
driverdata.channelRPN[id] = (driverdata.channelRPN[id] & 0x3F80) | value;
break;
case ctrlNRPNLo:
case ctrlNRPNHi:
driverdata.channelRPN[id] = 0x3FFF;
break;
case ctrlDataEntryHi:
if (driverdata.channelRPN[id] == 0)
{
driverdata.channelPitchSens[id] = value * 100 + (driverdata.channelPitchSens[id] % 100);
}
break;
case ctrlDataEntryLo:
if (driverdata.channelRPN[id] == 0)
{
driverdata.channelPitchSens[id] = value + (driverdata.channelPitchSens[id] / 100) * 100;
}
break;
} }
} }
void musicBlock::OPLresetControllers(uint chan, int vol)
{
driverdata.channelVolume[chan] = vol;
driverdata.channelExpression[chan] = 127;
driverdata.channelSustain[chan] = 0;
driverdata.channelLastVolume[chan] = 64;
driverdata.channelPitch[chan] = 64;
driverdata.channelRPN[chan] = 0x3fff;
driverdata.channelPitchSens[chan] = 200;
}
void musicBlock::OPLprogramChange(uint channel, int value) void musicBlock::OPLprogramChange(uint channel, int value)
{ {
driverdata.channelInstr[channel] = value; driverdata.channelInstr[channel] = value;
@ -364,10 +439,7 @@ void musicBlock::OPLplayMusic(int vol)
for (i = 0; i < CHANNELS; i++) for (i = 0; i < CHANNELS; i++)
{ {
driverdata.channelVolume[i] = vol; /* default volume 127 for MUS (full volume) */ OPLresetControllers(i, vol);
driverdata.channelSustain[i] = 0;
driverdata.channelLastVolume[i] = 64;
driverdata.channelPitch[i] = 64;
} }
} }
@ -379,18 +451,6 @@ void musicBlock::OPLstopMusic()
releaseChannel(i, 1); releaseChannel(i, 1);
} }
void musicBlock::OPLchangeVolume(uint volume)
{
uchar *channelVolume = driverdata.channelVolume;
uint i;
for(i = 0; i < io->OPLchannels; i++)
{
struct channelEntry *ch = &channels[i];
ch->realvolume = calcVolume(channelVolume[ch->channel & 0xF], volume, ch->volume);
io->OPLwriteVolume(i, ch->instr, ch->realvolume);
}
}
int musicBlock::OPLloadBank (FileReader &data) int musicBlock::OPLloadBank (FileReader &data)
{ {
static const uchar masterhdr[8] = { '#','O','P','L','_','I','I','#' }; static const uchar masterhdr[8] = { '#','O','P','L','_','I','I','#' };

View file

@ -468,15 +468,21 @@ void OPLMIDIDevice::HandleEvent(int status, int parm1, int parm2)
{ {
case 0: OPLchangeControl(channel, ctrlBank, parm2); break; case 0: OPLchangeControl(channel, ctrlBank, parm2); break;
case 1: OPLchangeControl(channel, ctrlModulation, parm2); break; case 1: OPLchangeControl(channel, ctrlModulation, parm2); break;
case 6: OPLchangeControl(channel, ctrlDataEntryHi, parm2); break;
case 7: OPLchangeControl(channel, ctrlVolume, parm2); break; case 7: OPLchangeControl(channel, ctrlVolume, parm2); break;
case 10: OPLchangeControl(channel, ctrlPan, parm2); break; case 10: OPLchangeControl(channel, ctrlPan, parm2); break;
case 11: OPLchangeControl(channel, ctrlExpression, parm2); break; case 11: OPLchangeControl(channel, ctrlExpression, parm2); break;
case 38: OPLchangeControl(channel, ctrlDataEntryLo, parm2); break;
case 64: OPLchangeControl(channel, ctrlSustainPedal, parm2); break; case 64: OPLchangeControl(channel, ctrlSustainPedal, parm2); break;
case 67: OPLchangeControl(channel, ctrlSoftPedal, parm2); break; case 67: OPLchangeControl(channel, ctrlSoftPedal, parm2); break;
case 91: OPLchangeControl(channel, ctrlReverb, parm2); break; case 91: OPLchangeControl(channel, ctrlReverb, parm2); break;
case 93: OPLchangeControl(channel, ctrlChorus, parm2); break; case 93: OPLchangeControl(channel, ctrlChorus, parm2); break;
case 98: OPLchangeControl(channel, ctrlNRPNLo, parm2); break;
case 99: OPLchangeControl(channel, ctrlNRPNHi, parm2); break;
case 100: OPLchangeControl(channel, ctrlRPNLo, parm2); break;
case 101: OPLchangeControl(channel, ctrlRPNHi, parm2); break;
case 120: OPLchangeControl(channel, ctrlSoundsOff, parm2); break; case 120: OPLchangeControl(channel, ctrlSoundsOff, parm2); break;
case 121: OPLchangeControl(channel, ctrlResetCtrls, parm2); break; case 121: OPLresetControllers(channel, 100); break;
case 123: OPLchangeControl(channel, ctrlNotesOff, parm2); break; case 123: OPLchangeControl(channel, ctrlNotesOff, parm2); break;
case 126: OPLchangeControl(channel, ctrlMono, parm2); break; case 126: OPLchangeControl(channel, ctrlMono, parm2); break;
case 127: OPLchangeControl(channel, ctrlPoly, parm2); break; case 127: OPLchangeControl(channel, ctrlPoly, parm2); break;

View file

@ -154,9 +154,12 @@ struct OPLdata {
uchar channelVolume[CHANNELS]; // volume uchar channelVolume[CHANNELS]; // volume
uchar channelLastVolume[CHANNELS]; // last volume uchar channelLastVolume[CHANNELS]; // last volume
schar channelPan[CHANNELS]; // pan, 0=normal schar channelPan[CHANNELS]; // pan, 0=normal
schar channelPitch[CHANNELS]; // pitch wheel, 0=normal schar channelPitch[CHANNELS]; // pitch wheel, 64=normal
uchar channelSustain[CHANNELS]; // sustain pedal value uchar channelSustain[CHANNELS]; // sustain pedal value
uchar channelModulation[CHANNELS]; // modulation pot value uchar channelModulation[CHANNELS]; // modulation pot value
ushort channelPitchSens[CHANNELS]; // pitch sensitivity, 2=default
ushort channelRPN[CHANNELS]; // RPN number for data entry
uchar channelExpression[CHANNELS]; // expression
}; };
struct OPLio { struct OPLio {
@ -227,9 +230,9 @@ struct musicBlock {
void OPLpitchWheel(uint channel, int pitch); void OPLpitchWheel(uint channel, int pitch);
void OPLchangeControl(uint channel, uchar controller, int value); void OPLchangeControl(uint channel, uchar controller, int value);
void OPLprogramChange(uint channel, int value); void OPLprogramChange(uint channel, int value);
void OPLresetControllers(uint channel, int vol);
void OPLplayMusic(int vol); void OPLplayMusic(int vol);
void OPLstopMusic(); void OPLstopMusic();
void OPLchangeVolume(uint volume);
int OPLloadBank (FileReader &data); int OPLloadBank (FileReader &data);
@ -250,7 +253,7 @@ protected:
void writeFrequency(uint slot, uint note, int pitch, uint keyOn); void writeFrequency(uint slot, uint note, int pitch, uint keyOn);
void writeModulation(uint slot, struct OPL2instrument *instr, int state); void writeModulation(uint slot, struct OPL2instrument *instr, int state);
uint calcVolume(uint channelVolume, uint MUSvolume, uint noteVolume); uint calcVolume(uint channelVolume, uint channelExpression, uint noteVolume);
int occupyChannel(uint slot, uint channel, int occupyChannel(uint slot, uint channel,
int note, int volume, struct OP2instrEntry *instrument, uchar secondary); int note, int volume, struct OP2instrEntry *instrument, uchar secondary);
int releaseChannel(uint slot, uint killed); int releaseChannel(uint slot, uint killed);
@ -273,12 +276,17 @@ enum MUSctrl {
ctrlChorus, ctrlChorus,
ctrlSustainPedal, ctrlSustainPedal,
ctrlSoftPedal, ctrlSoftPedal,
_ctrlCount_, ctrlRPNHi,
ctrlSoundsOff = _ctrlCount_, ctrlRPNLo,
ctrlNRPNHi,
ctrlNRPNLo,
ctrlDataEntryHi,
ctrlDataEntryLo,
ctrlSoundsOff,
ctrlNotesOff, ctrlNotesOff,
ctrlMono, ctrlMono,
ctrlPoly, ctrlPoly,
ctrlResetCtrls
}; };
#define OPL_SAMPLE_RATE 49716.0 #define OPL_SAMPLE_RATE 49716.0

View file

@ -52,6 +52,9 @@ static void Palette32Generic (const PalEntry *pal);
static void Palette32RGB (const PalEntry *pal); static void Palette32RGB (const PalEntry *pal);
static void Palette32BGR (const PalEntry *pal); static void Palette32BGR (const PalEntry *pal);
static void Scale8 (BYTE *src, int srcpitch,
void *destin, int destpitch, int destwidth, int destheight,
fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac);
static void Convert8 (BYTE *src, int srcpitch, static void Convert8 (BYTE *src, int srcpitch,
void *destin, int destpitch, int destwidth, int destheight, void *destin, int destpitch, int destwidth, int destheight,
fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac); fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac);
@ -69,6 +72,11 @@ void PfxState::SetFormat (int bits, uint32 redMask, uint32 greenMask, uint32 blu
{ {
switch (bits) switch (bits)
{ {
case -8:
Convert = Scale8;
SetPalette = NULL;
break;
case 8: case 8:
Convert = Convert8; Convert = Convert8;
SetPalette = NULL; SetPalette = NULL;
@ -132,7 +140,7 @@ void PfxState::SetFormat (int bits, uint32 redMask, uint32 greenMask, uint32 blu
default: default:
I_FatalError ("Can't draw to %d-bit displays", bits); I_FatalError ("Can't draw to %d-bit displays", bits);
} }
if (bits != 8) if (bits != 8 && bits != -8)
{ {
RedLeft = AnalyzeMask (redMask, &RedShift); RedLeft = AnalyzeMask (redMask, &RedShift);
GreenLeft = AnalyzeMask (greenMask, &GreenShift); GreenLeft = AnalyzeMask (greenMask, &GreenShift);
@ -260,7 +268,7 @@ static void Palette32BGR (const PalEntry *pal)
// Bitmap converters ------------------------------------------------------- // Bitmap converters -------------------------------------------------------
static void Convert8 (BYTE *src, int srcpitch, static void Scale8 (BYTE *src, int srcpitch,
void *destin, int destpitch, int destwidth, int destheight, void *destin, int destpitch, int destwidth, int destheight,
fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac) fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac)
{ {
@ -273,8 +281,129 @@ static void Convert8 (BYTE *src, int srcpitch,
BYTE *dest = (BYTE *)destin; BYTE *dest = (BYTE *)destin;
if (xstep == FRACUNIT && ystep == FRACUNIT) if (xstep == FRACUNIT && ystep == FRACUNIT)
{
for (y = destheight; y != 0; y--)
{
memcpy(dest, src, destwidth);
dest += destpitch;
src += srcpitch;
}
}
else if (xstep == FRACUNIT/2 && ystep == FRACUNIT/2)
{
BYTE *dest2 = dest + destpitch;
destpitch = destpitch * 2 - destwidth;
srcpitch -= destwidth / 2;
for (y = destheight / 2; y != 0; --y)
{
for (x = destwidth / 2; x != 0; --x)
{
BYTE foo = src[0];
dest[0] = foo;
dest[1] = foo;
dest2[0] = foo;
dest2[1] = foo;
dest += 2;
dest2 += 2;
src += 1;
}
dest += destpitch;
dest2 += destpitch;
src += srcpitch;
}
}
else if (xstep == FRACUNIT/4 && ystep == FRACUNIT/4)
{
int gap = destpitch * 4 - destwidth;
srcpitch -= destwidth / 4;
for (y = destheight / 4; y != 0; --y)
{
for (BYTE *end = dest + destpitch; dest != end; dest += 4)
{
BYTE foo = src[0];
dest[0] = foo;
dest[1] = foo;
dest[2] = foo;
dest[3] = foo;
dest[0 + destpitch] = foo;
dest[1 + destpitch] = foo;
dest[2 + destpitch] = foo;
dest[3 + destpitch] = foo;
dest[0 + destpitch*2] = foo;
dest[1 + destpitch*2] = foo;
dest[2 + destpitch*2] = foo;
dest[3 + destpitch*2] = foo;
dest[0 + destpitch*3] = foo;
dest[1 + destpitch*3] = foo;
dest[2 + destpitch*3] = foo;
dest[3 + destpitch*3] = foo;
src += 1;
}
dest += gap;
src += srcpitch;
}
}
else
{ {
destpitch -= destwidth; destpitch -= destwidth;
for (y = destheight; y != 0; y--)
{
fixed_t xf = xfrac;
x = destwidth;
while (((size_t)dest & 3) && x != 0)
{
*dest++ = src[xf >> FRACBITS];
xf += xstep;
x--;
}
for (savedx = x, x >>= 2; x != 0; x--)
{
DWORD work;
#ifdef WORDS_BIGENDIAN
work = src[xf >> FRACBITS] << 24; xf += xstep;
work |= src[xf >> FRACBITS] << 16; xf += xstep;
work |= src[xf >> FRACBITS] << 8; xf += xstep;
work |= src[xf >> FRACBITS]; xf += xstep;
#else
work = src[xf >> FRACBITS]; xf += xstep;
work |= src[xf >> FRACBITS] << 8; xf += xstep;
work |= src[xf >> FRACBITS] << 16; xf += xstep;
work |= src[xf >> FRACBITS] << 24; xf += xstep;
#endif
*(DWORD *)dest = work;
dest += 4;
}
for (savedx &= 3; savedx != 0; savedx--, xf += xstep)
{
*dest++ = src[xf >> FRACBITS];
}
yfrac += ystep;
while (yfrac >= FRACUNIT)
{
yfrac -= FRACUNIT;
src += srcpitch;
}
dest += destpitch;
}
}
}
static void Convert8 (BYTE *src, int srcpitch,
void *destin, int destpitch, int destwidth, int destheight,
fixed_t xstep, fixed_t ystep, fixed_t xfrac, fixed_t yfrac)
{
if ((destwidth | destheight) == 0)
{
return;
}
int x, y, savedx;
BYTE *dest = (BYTE *)destin;
destpitch -= destwidth;
if (xstep == FRACUNIT && ystep == FRACUNIT)
{
srcpitch -= destwidth; srcpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
@ -311,7 +440,6 @@ static void Convert8 (BYTE *src, int srcpitch,
} }
else else
{ {
destpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
fixed_t xf = xfrac; fixed_t xf = xfrac;
@ -367,9 +495,9 @@ static void Convert16 (BYTE *src, int srcpitch,
int x, y, savedx; int x, y, savedx;
WORD *dest = (WORD *)destin; WORD *dest = (WORD *)destin;
destpitch = (destpitch >> 1) - destwidth;
if (xstep == FRACUNIT && ystep == FRACUNIT) if (xstep == FRACUNIT && ystep == FRACUNIT)
{ {
destpitch = (destpitch >> 1) - destwidth;
srcpitch -= destwidth; srcpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
@ -402,7 +530,6 @@ static void Convert16 (BYTE *src, int srcpitch,
} }
else else
{ {
destpitch = (destpitch >> 1) - destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
fixed_t xf = xfrac; fixed_t xf = xfrac;
@ -454,9 +581,9 @@ static void Convert24 (BYTE *src, int srcpitch,
int x, y; int x, y;
BYTE *dest = (BYTE *)destin; BYTE *dest = (BYTE *)destin;
destpitch = destpitch - destwidth*3;
if (xstep == FRACUNIT && ystep == FRACUNIT) if (xstep == FRACUNIT && ystep == FRACUNIT)
{ {
destpitch = destpitch - destwidth*3;
srcpitch -= destwidth; srcpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
@ -475,7 +602,6 @@ static void Convert24 (BYTE *src, int srcpitch,
} }
else else
{ {
destpitch = destpitch - destwidth*3;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
fixed_t xf = xfrac; fixed_t xf = xfrac;
@ -511,9 +637,9 @@ static void Convert32 (BYTE *src, int srcpitch,
int x, y, savedx; int x, y, savedx;
DWORD *dest = (DWORD *)destin; DWORD *dest = (DWORD *)destin;
destpitch = (destpitch >> 2) - destwidth;
if (xstep == FRACUNIT && ystep == FRACUNIT) if (xstep == FRACUNIT && ystep == FRACUNIT)
{ {
destpitch = (destpitch >> 2) - destwidth;
srcpitch -= destwidth; srcpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
@ -540,7 +666,6 @@ static void Convert32 (BYTE *src, int srcpitch,
} }
else else
{ {
destpitch -= destwidth;
for (y = destheight; y != 0; y--) for (y = destheight; y != 0; y--)
{ {
fixed_t xf = xfrac; fixed_t xf = xfrac;

View file

@ -460,6 +460,7 @@ bool D3DFB::CreateResources ()
} }
if (FAILED(D3DDevice->CreatePixelShader (GammaFixerDef, &GammaFixerShader))) if (FAILED(D3DDevice->CreatePixelShader (GammaFixerDef, &GammaFixerShader)))
{ {
// Cannot print during screen creation.
// Printf ("Using Shader Model 1.4: Windowed mode gamma will not work.\n"); // Printf ("Using Shader Model 1.4: Windowed mode gamma will not work.\n");
GammaFixerShader = NULL; GammaFixerShader = NULL;
} }

View file

@ -3,7 +3,7 @@
** Code to let ZDoom use DirectDraw 3 ** Code to let ZDoom use DirectDraw 3
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit ** Copyright 1998-2008 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -132,12 +132,12 @@ DDrawFB::DDrawFB (int width, int height, bool fullscreen)
BlitSurf = NULL; BlitSurf = NULL;
Clipper = NULL; Clipper = NULL;
GDIPalette = NULL; GDIPalette = NULL;
ClipRegion = NULL;
ClipSize = 0; ClipSize = 0;
BufferCount = 1; BufferCount = 1;
Gamma = 1.0; Gamma = 1.0;
BufferPitch = Pitch; BufferPitch = Pitch;
FlipFlags = vid_vsync ? DDFLIP_WAIT : DDFLIP_WAIT|DDFLIP_NOVSYNC; FlipFlags = vid_vsync ? DDFLIP_WAIT : DDFLIP_WAIT|DDFLIP_NOVSYNC;
PixelDoubling = 0;
NeedGammaUpdate = false; NeedGammaUpdate = false;
NeedPalUpdate = false; NeedPalUpdate = false;
@ -239,20 +239,21 @@ bool DDrawFB::CreateResources ()
if (mode->width == Width && mode->height == Height) if (mode->width == Width && mode->height == Height)
{ {
TrueHeight = mode->realheight; TrueHeight = mode->realheight;
PixelDoubling = mode->doubling;
break; break;
} }
} }
hr = DDraw->SetDisplayMode (Width, TrueHeight, bits = vid_displaybits, vid_refreshrate, 0); hr = DDraw->SetDisplayMode (Width << PixelDoubling, TrueHeight << PixelDoubling, bits = vid_displaybits, vid_refreshrate, 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
hr = DDraw->SetDisplayMode (Width, TrueHeight, bits = vid_displaybits, 0, 0); hr = DDraw->SetDisplayMode (Width << PixelDoubling, TrueHeight << PixelDoubling, bits = vid_displaybits, 0, 0);
bits = 32; bits = 32;
while (FAILED(hr) && bits >= 8) while (FAILED(hr) && bits >= 8)
{ {
hr = DDraw->SetDisplayMode (Width, Height, bits, vid_refreshrate, 0); hr = DDraw->SetDisplayMode (Width << PixelDoubling, Height << PixelDoubling, bits, vid_refreshrate, 0);
if (FAILED(hr)) if (FAILED(hr))
{ {
hr = DDraw->SetDisplayMode (Width, Height, bits, 0, 0); hr = DDraw->SetDisplayMode (Width << PixelDoubling, Height << PixelDoubling, bits, 0, 0);
} }
bits -= 8; bits -= 8;
} }
@ -290,6 +291,7 @@ bool DDrawFB::CreateResources ()
// Create the primary surface // Create the primary surface
ddsd.dwFlags = DDSD_CAPS; ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// PixelDoubling = 1;
do do
{ {
hr = DDraw->CreateSurface (&ddsd, &PrimarySurf, NULL); hr = DDraw->CreateSurface (&ddsd, &PrimarySurf, NULL);
@ -304,8 +306,8 @@ bool DDrawFB::CreateResources ()
MaybeCreatePalette (); MaybeCreatePalette ();
// Resize the window to match desired dimensions // Resize the window to match desired dimensions
int sizew = Width + GetSystemMetrics (SM_CXSIZEFRAME)*2; int sizew = (Width << PixelDoubling) + GetSystemMetrics (SM_CXSIZEFRAME)*2;
int sizeh = Height + GetSystemMetrics (SM_CYSIZEFRAME) * 2 + int sizeh = (Height << PixelDoubling) + GetSystemMetrics (SM_CYSIZEFRAME) * 2 +
GetSystemMetrics (SM_CYCAPTION); GetSystemMetrics (SM_CYCAPTION);
LOG2 ("Resize window to %dx%d\n", sizew, sizeh); LOG2 ("Resize window to %dx%d\n", sizew, sizeh);
VidResizing = true; VidResizing = true;
@ -334,8 +336,8 @@ bool DDrawFB::CreateResources ()
// Create the backbuffer // Create the backbuffer
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.dwWidth = Width; ddsd.dwWidth = Width << PixelDoubling;
ddsd.dwHeight = Height; ddsd.dwHeight = Height << PixelDoubling;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | (UseBlitter ? DDSCAPS_SYSTEMMEMORY : 0); ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | (UseBlitter ? DDSCAPS_SYSTEMMEMORY : 0);
hr = DDraw->CreateSurface (&ddsd, &BackSurf, NULL); hr = DDraw->CreateSurface (&ddsd, &BackSurf, NULL);
@ -661,6 +663,11 @@ void DDrawFB::MaybeCreatePalette ()
NeedPalUpdate = true; NeedPalUpdate = true;
} }
} }
if (PixelDoubling)
{
UsePfx = true;
GPfx.SetFormat (-8, 0, 0, 0);
}
} }
} }
else else
@ -681,11 +688,6 @@ void DDrawFB::ReleaseResources ()
Unlock (); Unlock ();
} }
if (ClipRegion != NULL)
{
delete[] ClipRegion;
ClipRegion = NULL;
}
SAFE_RELEASE( Clipper ); SAFE_RELEASE( Clipper );
SAFE_RELEASE( PrimarySurf ); SAFE_RELEASE( PrimarySurf );
SAFE_RELEASE( BackSurf ); SAFE_RELEASE( BackSurf );
@ -1110,8 +1112,8 @@ void DDrawFB::Update ()
if (UsePfx) if (UsePfx)
{ {
GPfx.Convert (MemBuffer, BufferPitch, GPfx.Convert (MemBuffer, BufferPitch,
writept, Pitch, Width, Height, writept, Pitch, Width << PixelDoubling, Height << PixelDoubling,
FRACUNIT, FRACUNIT, 0, 0); FRACUNIT >> PixelDoubling, FRACUNIT >> PixelDoubling, 0, 0);
} }
else else
{ {
@ -1207,8 +1209,8 @@ bool DDrawFB::PaintToWindow ()
if (LockSurf (NULL, NULL) != NoGood) if (LockSurf (NULL, NULL) != NoGood)
{ {
GPfx.Convert (MemBuffer, BufferPitch, GPfx.Convert (MemBuffer, BufferPitch,
Buffer, Pitch, Width, Height, Buffer, Pitch, Width << PixelDoubling, Height << PixelDoubling,
FRACUNIT, FRACUNIT, 0, 0); FRACUNIT >> PixelDoubling, FRACUNIT >> PixelDoubling, 0, 0);
LockingSurf->Unlock (NULL); LockingSurf->Unlock (NULL);
if (FAILED (hr = PrimarySurf->Blt (&rect, BackSurf, NULL, DDBLT_WAIT|DDBLT_ASYNC, NULL))) if (FAILED (hr = PrimarySurf->Blt (&rect, BackSurf, NULL, DDBLT_WAIT|DDBLT_ASYNC, NULL)))
{ {

View file

@ -108,6 +108,7 @@ class Win32Video : public IVideo
void AddD3DModes (D3DFORMAT format); void AddD3DModes (D3DFORMAT format);
void AddLowResModes (); void AddLowResModes ();
void AddLetterboxModes (); void AddLetterboxModes ();
void ScaleModes (int doubling);
friend class DDrawFB; friend class DDrawFB;
friend class D3DFB; friend class D3DFB;
@ -193,13 +194,13 @@ private:
LPDIRECTDRAWSURFACE LockingSurf; LPDIRECTDRAWSURFACE LockingSurf;
LPDIRECTDRAWCLIPPER Clipper; LPDIRECTDRAWCLIPPER Clipper;
HPALETTE GDIPalette; HPALETTE GDIPalette;
BYTE *ClipRegion;
DWORD ClipSize; DWORD ClipSize;
PalEntry Flash; PalEntry Flash;
int FlashAmount; int FlashAmount;
int BufferCount; int BufferCount;
int BufferPitch; int BufferPitch;
int TrueHeight; int TrueHeight;
int PixelDoubling;
float Gamma; float Gamma;
bool NeedGammaUpdate; bool NeedGammaUpdate;

View file

@ -185,7 +185,18 @@ bool Win32Video::InitD3D9 ()
FreeModes (); FreeModes ();
AddD3DModes (D3DFMT_X8R8G8B8); AddD3DModes (D3DFMT_X8R8G8B8);
AddD3DModes (D3DFMT_R5G6B5); AddD3DModes (D3DFMT_R5G6B5);
AddLowResModes (); if (Args->CheckParm ("-2"))
{ // Force all modes to be pixel-doubled.
ScaleModes (1);
}
else if (Args->CheckParm ("-4"))
{ // Force all modes to be pixel-quadrupled.
ScaleModes (2);
}
else
{
AddLowResModes ();
}
AddLetterboxModes (); AddLetterboxModes ();
if (m_Modes == NULL) if (m_Modes == NULL)
{ // Too bad. We didn't find any modes for D3D9. We probably won't find any { // Too bad. We didn't find any modes for D3D9. We probably won't find any
@ -256,12 +267,24 @@ void Win32Video::InitDDraw ()
"If you started ZDoom from a fullscreen DOS box, run it from " "If you started ZDoom from a fullscreen DOS box, run it from "
"a DOS window instead. If that does not work, you may need to reboot."); "a DOS window instead. If that does not work, you may need to reboot.");
} }
if (OSPlatform == os_Win95) if (Args->CheckParm ("-2"))
{ // Force all modes to be pixel-doubled.
ScaleModes(1);
}
else if (Args->CheckParm ("-4"))
{ // Force all modes to be pixel-quadrupled.
ScaleModes(2);
}
else
{ {
// Windows 95 will let us use Mode X. If we didn't find any linear if (OSPlatform == os_Win95)
// modes in the loop above, add the Mode X modes here. {
AddMode (320, 200, 8, 200, 0); // Windows 95 will let us use Mode X. If we didn't find any linear
AddMode (320, 240, 8, 240, 0); // modes in the loop above, add the Mode X modes here.
AddMode (320, 200, 8, 200, 0);
AddMode (320, 240, 8, 240, 0);
}
AddLowResModes ();
} }
AddLetterboxModes (); AddLetterboxModes ();
} }
@ -358,7 +381,7 @@ void Win32Video::AddLowResModes()
{ {
nextmode = mode->next; nextmode = mode->next;
if (mode->realheight == mode->height && if (mode->realheight == mode->height &&
mode->doubling == 0&& mode->doubling == 0 &&
mode->height >= 200*2 && mode->height >= 200*2 &&
mode->height <= 480*2 && mode->height <= 480*2 &&
mode->width >= 320*2 && mode->width >= 320*2 &&
@ -371,7 +394,7 @@ void Win32Video::AddLowResModes()
{ {
nextmode = mode->next; nextmode = mode->next;
if (mode->realheight == mode->height && if (mode->realheight == mode->height &&
mode->doubling == 0&& mode->doubling == 0 &&
mode->height >= 200*4 && mode->height >= 200*4 &&
mode->height <= 480*4 && mode->height <= 480*4 &&
mode->width >= 320*4 && mode->width >= 320*4 &&
@ -455,6 +478,36 @@ void Win32Video::FreeModes ()
m_Modes = NULL; m_Modes = NULL;
} }
// For every mode, set its scaling factor. Modes that end up with too
// small a display area are discarded.
void Win32Video::ScaleModes (int doubling)
{
ModeInfo *mode, **prev;
prev = &m_Modes;
mode = m_Modes;
while (mode != NULL)
{
assert(mode->doubling == 0);
mode->width >>= doubling;
mode->height >>= doubling;
mode->realheight >>= doubling;
mode->doubling = doubling;
if ((mode->width & 7) != 0 || mode->width < 320 || mode->height < 200)
{ // Mode became too small. Delete it.
*prev = mode->next;
delete mode;
}
else
{
prev = &mode->next;
}
mode = *prev;
}
}
void Win32Video::StartModeIterator (int bits, bool fs) void Win32Video::StartModeIterator (int bits, bool fs)
{ {
m_IteratorMode = m_Modes; m_IteratorMode = m_Modes;