Video mode: "Color (RGB Card/Monitor)" . RGB HGR rendering (no half-dot-shift, no vertical blend) . RGB DHGR rendering - Color 140-mode is a real 140x192 mode with no color fringe (Video7 patent, shows that way on real hardware) - Mixed mode: correct transition for Color 140-mode <-> B&W (validated on a real IIc adapter.) . Complete Féline support (eg. 2 distinct greys) . Fixed Video7 SL7 inverse text . Fixed DHIRES mixed mode detection . NB. Prince of Persia will switch to B&W (560-mode) when going from HGR back to DHGR (same on real hardware). Video mode: "Color (Composite Idealized)" . Previously this was "Color (RGB Monitor)" (and before that, the AppleWin 1.25 "Color (Standard)") . Now this mode does not support the extra RGB cards' video modes
This commit is contained in:
parent
b9d80a0317
commit
08458a9d29
6 changed files with 537 additions and 82 deletions
|
@ -1751,6 +1751,10 @@ static bool ProcessCmdLine(LPSTR lpCmdLine)
|
|||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_MONITOR_RGB;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-video-mode=rgb-videocard") == 0)
|
||||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_VIDEOCARD_RGB;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-video-mode=composite-monitor") == 0) // GH#763
|
||||
{
|
||||
g_cmdLine.newVideoType = VT_COLOR_MONITOR_NTSC;
|
||||
|
@ -2041,6 +2045,9 @@ static void RepeatInitialization(void)
|
|||
FrameCreateWindow(); // g_hFrameWindow is now valid
|
||||
LogFileOutput("Main: FrameCreateWindow() - post\n");
|
||||
|
||||
// Init palette color
|
||||
VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
|
||||
|
||||
// Allow the 4 hardcoded slots to be configurated as empty
|
||||
// NB. this state is not persisted to the Registry/conf.ini (just as '-s7 empty' isn't)
|
||||
// TODO: support bSlotEmpty[] for slots: 0,4,5
|
||||
|
|
117
source/NTSC.cpp
117
source/NTSC.cpp
|
@ -443,6 +443,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
static void updateScreenText80 ( long cycles6502 );
|
||||
static void updateScreenText40RGB ( long cycles6502 );
|
||||
static void updateScreenText80RGB ( long cycles6502 );
|
||||
static void updateScreenDoubleHires80Simplified(long cycles6502);
|
||||
static void updateScreenDoubleHires80RGB(long cycles6502);
|
||||
|
||||
//===========================================================================
|
||||
static void set_csbits()
|
||||
|
@ -830,7 +832,7 @@ inline void updateVideoScannerAddress()
|
|||
(g_pFuncUpdateGraphicsScreen == updateScreenText80) ||
|
||||
(g_pFuncUpdateGraphicsScreen == updateScreenText80RGB) ||
|
||||
(g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && (g_pFuncUpdateTextScreen == updateScreenText80 || g_pFuncUpdateGraphicsScreen == updateScreenText80RGB)))
|
||||
&& (g_eVideoType != VT_COLOR_MONITOR_RGB)) // Fix for "Ansi Story" (Turn the disk over) - Top row of TEXT80 is shifted by 1 pixel
|
||||
&& (g_eVideoType != VT_COLOR_MONITOR_RGB) && (g_eVideoType != VT_COLOR_VIDEOCARD_RGB)) // Fix for "Ansi Story" (Turn the disk over) - Top row of TEXT80 is shifted by 1 pixel
|
||||
{
|
||||
g_pVideoAddress -= 1;
|
||||
}
|
||||
|
@ -1235,7 +1237,41 @@ void updateScreenDoubleHires40 (long cycles6502) // wsUpdateVideoHires0
|
|||
|
||||
//===========================================================================
|
||||
|
||||
void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
void updateScreenDoubleHires80Simplified(long cycles6502) // wsUpdateVideoDblHires
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen(cycles6502);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
g_nColorBurstPixels = 1024;
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
uint8_t a = *MemGetAuxPtr(addr);
|
||||
uint8_t m = *MemGetMainPtr(addr);
|
||||
|
||||
UpdateDHiResCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true, true);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void updateScreenDoubleHires80RGB (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
|
@ -1270,31 +1306,16 @@ void updateScreenDoubleHires80Simplified (long cycles6502 ) // wsUpdateVideoDblH
|
|||
int width = UpdateDHiRes160Cell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += width;
|
||||
}
|
||||
else if (RGB_Is560Mode() || (RGB_IsMixMode() && !((a | m) & 0x80)))
|
||||
else if (RGB_Is560Mode())// || (RGB_IsMixMode() && !((a | m) & 0x80)))
|
||||
{
|
||||
update7MonoPixels(a);
|
||||
update7MonoPixels(m);
|
||||
}
|
||||
else if (!RGB_IsMixMode() || (RGB_IsMixMode() && (a & m & 0x80)))
|
||||
else
|
||||
{
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true, true);
|
||||
UpdateDHiResCellRGB(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, RGB_IsMixMode(), RGB_IsMixModeInvertBit7());
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
else // RGB_IsMixMode() && ((a ^ m) & 0x80)
|
||||
{
|
||||
if (a & 0x80) // RGB color, then monochrome
|
||||
{
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, true ,false);
|
||||
g_pVideoAddress += 7;
|
||||
update7MonoPixels(m);
|
||||
}
|
||||
else // monochrome, then RGB color
|
||||
{
|
||||
update7MonoPixels(a);
|
||||
UpdateDHiResCell(g_nVideoClockHorz-VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, false, true);
|
||||
g_pVideoAddress += 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
|
@ -1514,6 +1535,36 @@ static void updateScreenSingleHires40Duochrome(long cycles6502)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void updateScreenSingleHires40RGB(long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
{
|
||||
g_pFuncUpdateTextScreen(cycles6502);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cycles6502 > 0; --cycles6502)
|
||||
{
|
||||
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
|
||||
{
|
||||
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
|
||||
{
|
||||
g_nColorBurstPixels = 1024;
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint16_t addr = getVideoScannerAddressHGR();
|
||||
|
||||
UpdateHiResRGBCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress);
|
||||
g_pVideoAddress += 14;
|
||||
}
|
||||
}
|
||||
updateVideoScannerHorzEOLSimple();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void updateScreenSingleHires40 (long cycles6502)
|
||||
{
|
||||
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED)
|
||||
|
@ -1670,7 +1721,7 @@ void updateScreenText40RGB(long cycles6502)
|
|||
if (0 == g_nVideoCharSet && 0x40 == (m & 0xC0)) // Flash only if mousetext not active
|
||||
c ^= g_nTextFlashMask;
|
||||
|
||||
UpdateText40ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, c);
|
||||
UpdateText40ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, c, m);
|
||||
g_pVideoAddress += 14;
|
||||
|
||||
}
|
||||
|
@ -1712,7 +1763,8 @@ void updateScreenText80 (long cycles6502)
|
|||
aux ^= g_nTextFlashMask;
|
||||
|
||||
uint16_t bits = (main << 7) | (aux & 0x7f);
|
||||
if (g_eVideoType != VT_COLOR_MONITOR_RGB) // No extra 14M bit needed for VT_COLOR_MONITOR_RGB
|
||||
if ((g_eVideoType != VT_COLOR_MONITOR_RGB) // No extra 14M bit needed for VT_COLOR_MONITOR_RGB
|
||||
&& (g_eVideoType != VT_COLOR_VIDEOCARD_RGB))
|
||||
bits = (bits << 1) | g_nLastColumnPixelNTSC; // GH#555: Align TEXT80 chars with DHGR
|
||||
|
||||
updatePixels( bits );
|
||||
|
@ -1754,9 +1806,9 @@ void updateScreenText80RGB(long cycles6502)
|
|||
if ((0 == g_nVideoCharSet) && 0x40 == (a & 0xC0)) // Flash only if mousetext not active
|
||||
aux ^= g_nTextFlashMask;
|
||||
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)aux);
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)aux, a);
|
||||
g_pVideoAddress += 7;
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)main);
|
||||
UpdateText80ColorCell(g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START, g_nVideoClockVert, addr, g_pVideoAddress, (uint8_t)main, m);
|
||||
g_pVideoAddress += 7;
|
||||
|
||||
uint16_t bits = (main << 7) | (aux & 0x7f);
|
||||
|
@ -1846,7 +1898,7 @@ uint16_t NTSC_VideoGetScannerAddressForDebugger(void)
|
|||
//===========================================================================
|
||||
void NTSC_SetVideoTextMode( int cols )
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
{
|
||||
if (cols == 40)
|
||||
g_pFuncUpdateTextScreen = updateScreenText40RGB;
|
||||
|
@ -1921,7 +1973,7 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
}
|
||||
|
||||
// Video7_SL7 extra RGB modes handling
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB
|
||||
&& RGB_GetVideocard() == RGB_Videocard_e::Video7_SL7
|
||||
// Exclude following modes (fallback through regular NTSC rendering with RGB text)
|
||||
// VF_DHIRES = 1 -> regular Apple IIe modes
|
||||
|
@ -1976,12 +2028,12 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText80;
|
||||
}
|
||||
else if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenText40;
|
||||
|
@ -1994,6 +2046,8 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80Simplified;
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleHires80;
|
||||
}
|
||||
|
@ -2006,6 +2060,8 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40Simplified;
|
||||
else if (g_eVideoType == VT_COLOR_VIDEOCARD_RGB)
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40RGB;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleHires40;
|
||||
}
|
||||
|
@ -2016,7 +2072,7 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
{
|
||||
if (uVideoModeFlags & VF_80COL)
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if ((g_eVideoType == VT_COLOR_MONITOR_RGB) || (g_eVideoType == VT_COLOR_VIDEOCARD_RGB))
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenDoubleLores80;
|
||||
|
@ -2028,7 +2084,7 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
|
|||
}
|
||||
else
|
||||
{
|
||||
if (g_eVideoType == VT_COLOR_MONITOR_RGB)
|
||||
if ((g_eVideoType == VT_COLOR_MONITOR_RGB) || (g_eVideoType == VT_COLOR_VIDEOCARD_RGB))
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40Simplified;
|
||||
else
|
||||
g_pFuncUpdateGraphicsScreen = updateScreenSingleLores40;
|
||||
|
@ -2105,6 +2161,7 @@ void NTSC_SetVideoStyle(void)
|
|||
goto _mono;
|
||||
|
||||
case VT_COLOR_MONITOR_RGB:
|
||||
case VT_COLOR_VIDEOCARD_RGB:
|
||||
case VT_MONO_WHITE:
|
||||
r = 0xFF;
|
||||
g = 0xFF;
|
||||
|
|
|
@ -117,7 +117,9 @@ const BYTE DoubleHiresPalIndex[16] = {
|
|||
|
||||
#define SETRGBCOLOR(r,g,b) {b,g,r,0}
|
||||
|
||||
static RGBQUAD PalIndex2RGB[] =
|
||||
static RGBQUAD* g_pPaletteRGB;
|
||||
|
||||
static RGBQUAD PaletteRGB_NTSC[] =
|
||||
{
|
||||
// hires
|
||||
#if DO_OPT_PALETTE
|
||||
|
@ -128,6 +130,7 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00), // For TV emulation HGR Video Mode
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
#else
|
||||
// Note: this is a placeholder. This palette is overwritten by VideoInitializeOriginal()
|
||||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00), // For TV emulation HGR Video Mode
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
SETRGBCOLOR(/*BLUE, */ 0x0D,0xA1,0xFF), // FC Linards Tweaked 0x00,0x00,0xFF -> 0x0D,0xA1,0xFF
|
||||
|
@ -145,6 +148,7 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*HGR_PINK, */ 0xFF,0x32,0xB5), // 0xD0,0x40,0xA0 -> 0xFF,0x32,0xB5
|
||||
|
||||
// lores & dhires
|
||||
// Note: this is a placeholder. This palette is overwritten by VideoInitializeOriginal()
|
||||
SETRGBCOLOR(/*BLACK,*/ 0x00,0x00,0x00), // 0
|
||||
SETRGBCOLOR(/*DEEP_RED,*/ 0x9D,0x09,0x66), // 0xD0,0x00,0x30 -> Linards Tweaked 0x9D,0x09,0x66
|
||||
SETRGBCOLOR(/*DARK_BLUE,*/ 0x2A,0x2A,0xE5), // 4 // Linards Tweaked 0x00,0x00,0x80 -> 0x2A,0x2A,0xE5
|
||||
|
@ -163,6 +167,44 @@ static RGBQUAD PalIndex2RGB[] =
|
|||
SETRGBCOLOR(/*WHITE,*/ 0xFF,0xFF,0xFF),
|
||||
};
|
||||
|
||||
// Le Chat Mauve Feline's palette
|
||||
// extracted from a white-balanced RGB video capture
|
||||
static RGBQUAD PaletteRGB_Feline[] =
|
||||
{
|
||||
SETRGBCOLOR(/*HGR_BLACK, */ 0x00,0x00,0x00),
|
||||
SETRGBCOLOR(/*HGR_WHITE, */ 0xFF,0xFF,0xFF),
|
||||
SETRGBCOLOR(/*BLUE, */ 0x00,0x8A,0xB5),
|
||||
SETRGBCOLOR(/*ORANGE, */ 0xFF,0x72,0x47),
|
||||
SETRGBCOLOR(/*GREEN, */ 0x6F,0xE6,0x2C),
|
||||
SETRGBCOLOR(/*MAGENTA, */ 0xAA,0x1A,0xD1),
|
||||
|
||||
// TV emu
|
||||
SETRGBCOLOR(/*HGR_GREY1, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_GREY2, */ 0x80,0x80,0x80),
|
||||
SETRGBCOLOR(/*HGR_YELLOW,*/ 0x9E,0x9E,0x00),
|
||||
SETRGBCOLOR(/*HGR_AQUA, */ 0x00,0xCD,0x4A),
|
||||
SETRGBCOLOR(/*HGR_PURPLE,*/ 0x61,0x61,0xFF),
|
||||
SETRGBCOLOR(/*HGR_PINK, */ 0xFF,0x32,0xB5),
|
||||
|
||||
// Feline
|
||||
SETRGBCOLOR(/*BLACK,*/ 0x00,0x00,0x00),
|
||||
SETRGBCOLOR(/*DEEP_RED,*/ 0xAC,0x12,0x4C),
|
||||
SETRGBCOLOR(/*DARK_BLUE,*/ 0x00,0x07,0x83),
|
||||
SETRGBCOLOR(/*MAGENTA,*/ 0xAA,0x1A,0xD1),
|
||||
SETRGBCOLOR(/*DARK_GREEN,*/ 0x00,0x83,0x2F),
|
||||
SETRGBCOLOR(/*DARK_GRAY,*/ 0x9F,0x97,0x7E),
|
||||
SETRGBCOLOR(/*BLUE,*/ 0x00,0x8A,0xB5),
|
||||
SETRGBCOLOR(/*LIGHT_BLUE,*/ 0x9F,0x9E,0xFF),
|
||||
SETRGBCOLOR(/*BROWN,*/ 0x7A,0x5F,0x00),
|
||||
SETRGBCOLOR(/*ORANGE,*/ 0xFF,0x72,0x47),
|
||||
SETRGBCOLOR(/*LIGHT_GRAY,*/ 0x78,0x68,0x7F),
|
||||
SETRGBCOLOR(/*PINK,*/ 0xFF,0x7A,0xCF),
|
||||
SETRGBCOLOR(/*GREEN,*/ 0x6F,0xE6,0x2C),
|
||||
SETRGBCOLOR(/*YELLOW,*/ 0xFF,0xF6,0x7B),
|
||||
SETRGBCOLOR(/*AQUA,*/ 0x6C,0xEE,0xB2),
|
||||
SETRGBCOLOR(/*WHITE,*/ 0xFF,0xFF,0xFF),
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void V_CreateLookup_DoubleHires ()
|
||||
|
@ -501,8 +543,8 @@ static void CopyMixedSource(int x, int y, int sx, int sy, bgra_t *pVideoAddress)
|
|||
}
|
||||
else
|
||||
{
|
||||
_ASSERT( colormixbuffer[h] < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ colormixbuffer[h] ];
|
||||
_ASSERT( colormixbuffer[h] < (sizeof(PaletteRGB_NTSC)/sizeof(PaletteRGB_NTSC[0])) );
|
||||
const RGBQUAD& rRGB = g_pPaletteRGB[ colormixbuffer[h] ];
|
||||
*(pDst+nBytes) = *reinterpret_cast<const UINT32 *>(&rRGB);
|
||||
}
|
||||
|
||||
|
@ -533,8 +575,8 @@ static void CopySource(int w, int h, int sx, int sy, bgra_t *pVideoAddress, cons
|
|||
{
|
||||
for (int nBytes=0; nBytes<w; ++nBytes)
|
||||
{
|
||||
_ASSERT( *(pSrc+nBytes+nSrcAdjustment) < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ *(pSrc+nBytes+nSrcAdjustment) ];
|
||||
_ASSERT( *(pSrc+nBytes+nSrcAdjustment) < (sizeof(PaletteRGB_NTSC)/sizeof(PaletteRGB_NTSC[0])) );
|
||||
const RGBQUAD& rRGB = g_pPaletteRGB[ *(pSrc+nBytes+nSrcAdjustment) ];
|
||||
*(pDst+nBytes) = *reinterpret_cast<const UINT32 *>(&rRGB);
|
||||
}
|
||||
}
|
||||
|
@ -569,25 +611,25 @@ void UpdateHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
|||
#define COLOR ((xpixel + PIXEL) & 3)
|
||||
#define VALUE (dwordval >> (4 + PIXEL - COLOR))
|
||||
|
||||
void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool updateAux, bool updateMain)
|
||||
void UpdateDHiResCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool updateAux, bool updateMain)
|
||||
{
|
||||
const int xpixel = x*14;
|
||||
const int xpixel = x * 14;
|
||||
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
BYTE byteval1 = (x > 0) ? *(pMain-1) : 0;
|
||||
BYTE byteval1 = (x > 0) ? *(pMain - 1) : 0;
|
||||
BYTE byteval2 = *pAux;
|
||||
BYTE byteval3 = *pMain;
|
||||
BYTE byteval4 = (x < 39) ? *(pAux+1) : 0;
|
||||
BYTE byteval4 = (x < 39) ? *(pAux + 1) : 0;
|
||||
|
||||
DWORD dwordval = (byteval1 & 0x70) | ((byteval2 & 0x7F) << 7) |
|
||||
((byteval3 & 0x7F) << 14) | ((byteval4 & 0x07) << 21);
|
||||
DWORD dwordval = (byteval1 & 0x70) | ((byteval2 & 0x7F) << 7) |
|
||||
((byteval3 & 0x7F) << 14) | ((byteval4 & 0x07) << 21);
|
||||
|
||||
#define PIXEL 0
|
||||
if (updateAux)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
CopySource(7, 2, SRCOFFS_DHIRES + 10 * HIBYTE(VALUE) + COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
pVideoAddress += 7;
|
||||
}
|
||||
#undef PIXEL
|
||||
|
@ -595,11 +637,323 @@ void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool
|
|||
#define PIXEL 7
|
||||
if (updateMain)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
CopySource(7, 2, SRCOFFS_DHIRES + 10 * HIBYTE(VALUE) + COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
}
|
||||
#undef PIXEL
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// RGB videocards HGR
|
||||
|
||||
void UpdateHiResRGBCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress)
|
||||
{
|
||||
const int xpixel = x * 14;
|
||||
int xoffset = x & 1; // offset to start of the 2 bytes
|
||||
addr -= xoffset;
|
||||
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
// We need all 28 bits because each pixel needs a three bit evaluation
|
||||
uint8_t byteval1 = (x < 2 ? 0 : *(pMain - 1));
|
||||
uint8_t byteval2 = *pMain;
|
||||
uint8_t byteval3 = *(pMain + 1);
|
||||
uint8_t byteval4 = (x >= 38 ? 0 : *(pMain + 2));
|
||||
|
||||
// all 28 bits chained
|
||||
DWORD dwordval = (byteval1 & 0x7F) | ((byteval2 & 0x7F) << 7) | ((byteval3 & 0x7F) << 14) | ((byteval4 & 0x7F) << 21);
|
||||
|
||||
// Extraction of 14 color pixels
|
||||
UINT32 colors[14];
|
||||
int color = 0;
|
||||
DWORD dwordval_tmp = dwordval;
|
||||
dwordval_tmp = dwordval_tmp >> 7;
|
||||
bool offset = (byteval2 & 0x80);
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
if (i == 7) offset = (byteval3 & 0x80);
|
||||
color = dwordval_tmp & 0x3;
|
||||
// Two cases because AppleWin's palette is in a strange order
|
||||
if (offset)
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[1 + color]);
|
||||
else
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[6 - color]);
|
||||
if (i%2) dwordval_tmp >>= 2;
|
||||
}
|
||||
// Black and White
|
||||
UINT32 bw[2];
|
||||
bw[0] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[0]);
|
||||
bw[1] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[1]);
|
||||
|
||||
DWORD mask = 0x01C0; // 00|000001 1|1000000
|
||||
DWORD chck1 = 0x0140; // 00|000001 0|1000000
|
||||
DWORD chck2 = 0x0080; // 00|000000 1|0000000
|
||||
|
||||
// HIRES render in RGB works on a pixel-basis (1-bit data in framebuffer)
|
||||
// The pixel can be 'color', if it makes a 101 or 010 pattern with the two neighbour bits
|
||||
// In all other cases, it's black if 0 and white if 1
|
||||
// The value of 'color' is defined on a 2-bits basis
|
||||
|
||||
UINT32* pDst = (UINT32*)pVideoAddress;
|
||||
|
||||
if (xoffset)
|
||||
{
|
||||
// Second byte of the 14 pixels block
|
||||
dwordval = dwordval >> 7;
|
||||
xoffset = 7;
|
||||
}
|
||||
|
||||
for (int i = xoffset; i < xoffset+7; i++)
|
||||
{
|
||||
if (((dwordval & mask) == chck1) || ((dwordval & mask) == chck2))
|
||||
{
|
||||
// Color pixel
|
||||
*(pDst) = colors[i];
|
||||
*(pDst + 1) = *(pDst);
|
||||
pDst += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// B&W pixel
|
||||
*(pDst) = bw[(dwordval & chck2 ? 1 : 0)];
|
||||
*(pDst + 1) = *(pDst);
|
||||
pDst += 2;
|
||||
}
|
||||
// Next pixel
|
||||
dwordval = dwordval >> 1;
|
||||
}
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
|
||||
// Second line
|
||||
UINT32* pSrc = (UINT32*)pVideoAddress;
|
||||
pDst = pSrc - GetFrameBufferWidth();
|
||||
if (bIsHalfScanLines)
|
||||
{
|
||||
// Scanlines
|
||||
std::fill(pDst, pDst + 14, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 14; i++)
|
||||
*(pDst + i) = *(pSrc + i);
|
||||
}
|
||||
}
|
||||
|
||||
bool dhgr_lastcell_iscolor = true;
|
||||
int dhgr_lastbit = 0;
|
||||
|
||||
void UpdateDHiResCellRGB(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool isMixMode, bool isBit7Inversed)
|
||||
{
|
||||
const int xpixel = x * 14;
|
||||
int xoffset = x & 1; // offset to start of the 2 bytes
|
||||
addr -= xoffset;
|
||||
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
|
||||
// We need all 28 bits because one 4-bits pixel overlaps two 14-bits cells
|
||||
uint8_t byteval1 = *pAux;
|
||||
uint8_t byteval2 = *pMain;
|
||||
uint8_t byteval3 = *(pAux + 1);
|
||||
uint8_t byteval4 = *(pMain + 1);
|
||||
|
||||
// all 28 bits chained
|
||||
DWORD dwordval = (byteval1 & 0x7F) | ((byteval2 & 0x7F) << 7) | ((byteval3 & 0x7F) << 14) | ((byteval4 & 0x7F) << 21);
|
||||
|
||||
// Extraction of 7 color pixels and 7x4 bits
|
||||
int bits[7];
|
||||
UINT32 colors[7];
|
||||
int color = 0;
|
||||
DWORD dwordval_tmp = dwordval;
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
bits[i] = dwordval_tmp & 0xF;
|
||||
color = ((bits[i] & 7) << 1) | ((bits[i] & 8) >> 3); // DHGR colors are rotated 1 bit to the right
|
||||
colors[i] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + color]);
|
||||
dwordval_tmp >>= 4;
|
||||
}
|
||||
UINT32 bw[2];
|
||||
bw[0] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + 0]);
|
||||
bw[1] = *reinterpret_cast<const UINT32*>(&g_pPaletteRGB[12 + 15]);
|
||||
|
||||
if (isBit7Inversed)
|
||||
{
|
||||
// Invert mixed mode detection
|
||||
byteval1 = ~byteval1;
|
||||
byteval2 = ~byteval2;
|
||||
byteval3 = ~byteval3;
|
||||
byteval4 = ~byteval4;
|
||||
}
|
||||
|
||||
// RGB DHGR is quite a mess:
|
||||
// Color mode is a real 140x192 RGB mode with no color fringe (ref. patent US4631692, "THE 140x192 VIDEO MODE")
|
||||
// BW mode is a real 560x192 monochrome mode
|
||||
// Mixed mode seems easy but has a few traps since it's based on 4-bits cells coded into 7-bits bytes:
|
||||
// - Bit 7 of each byte defines the mode of the following 7 bits (BW or Color);
|
||||
// - BW pixels are 1 bit wide, color pixels are usually 4 bits wide;
|
||||
// - A color pixel can be less than 4 bits wide if it crosses a byte boundary and falls into a BW byte;
|
||||
// - If a 4-bit cell of BW bits crosses a byte boundary and falls into a Color byte, then the last BW bit is repeated until the next color pixel starts.
|
||||
//
|
||||
// (Tested on Le Chat Mauve IIc adapter, which was made under patent of Video-7)
|
||||
|
||||
UINT32* pDst = (UINT32*)pVideoAddress;
|
||||
|
||||
if (xoffset == 0) // First cell
|
||||
{
|
||||
if ((byteval1 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Color
|
||||
|
||||
// Color cell 0
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
*(pDst++) = colors[0];
|
||||
// Color cell 1
|
||||
*(pDst++) = colors[1];
|
||||
*(pDst++) = colors[1];
|
||||
*(pDst++) = colors[1];
|
||||
|
||||
dwordval >>= 7;
|
||||
dhgr_lastcell_iscolor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// BW
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
dhgr_lastbit = dwordval & 1;
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
dhgr_lastcell_iscolor = false;
|
||||
}
|
||||
|
||||
if ((byteval2 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 1
|
||||
if (dhgr_lastcell_iscolor)
|
||||
{
|
||||
*(pDst++) = colors[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit once
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
}
|
||||
// Color cell 2
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
*(pDst++) = colors[2];
|
||||
// Color cell 3
|
||||
*(pDst++) = colors[3];
|
||||
*(pDst++) = colors[3];
|
||||
dhgr_lastcell_iscolor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
dhgr_lastbit = dwordval & 1;
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
dhgr_lastcell_iscolor = false;
|
||||
}
|
||||
}
|
||||
else // Second cell
|
||||
{
|
||||
dwordval >>= 14;
|
||||
|
||||
if ((byteval3 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 3
|
||||
if (dhgr_lastcell_iscolor)
|
||||
{
|
||||
*(pDst++) = colors[3];
|
||||
*(pDst++) = colors[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit twice
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
}
|
||||
// Color cell 4
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
*(pDst++) = colors[4];
|
||||
// Color cell 5
|
||||
*(pDst++) = colors[5];
|
||||
|
||||
dwordval >>= 7;
|
||||
dhgr_lastcell_iscolor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
dhgr_lastbit = dwordval & 1;
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
dhgr_lastcell_iscolor = false;
|
||||
}
|
||||
|
||||
if ((byteval4 & 0x80) || !isMixMode)
|
||||
{
|
||||
// Remaining of color cell 5
|
||||
if (dhgr_lastcell_iscolor)
|
||||
{
|
||||
*(pDst++) = colors[5];
|
||||
*(pDst++) = colors[5];
|
||||
*(pDst++) = colors[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Repeat last BW bit three times
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
}
|
||||
// Color cell 6
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
*(pDst++) = colors[6];
|
||||
dhgr_lastcell_iscolor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
dhgr_lastbit = dwordval & 1;
|
||||
*(pDst++) = bw[dhgr_lastbit];
|
||||
dwordval >>= 1;
|
||||
}
|
||||
dhgr_lastcell_iscolor = false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
|
||||
// Second line
|
||||
UINT32* pSrc = (UINT32*)pVideoAddress ;
|
||||
pDst = pSrc - GetFrameBufferWidth();
|
||||
if (bIsHalfScanLines)
|
||||
{
|
||||
// Scanlines
|
||||
std::fill(pDst, pDst + 14, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 14; i++)
|
||||
*(pDst + i) = *(pSrc + i);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
// Squash the 640 pixel image into 560 pixels
|
||||
int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
|
@ -708,7 +1062,7 @@ void UpdateDLoResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
|||
//===========================================================================
|
||||
// Color TEXT (some RGB cards only)
|
||||
// Default BG and FG are usually defined by hardware switches, defaults to black/white
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits)
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character)
|
||||
{
|
||||
uint8_t foreground = g_nRegularTextFG;
|
||||
uint8_t background = g_nRegularTextBG;
|
||||
|
@ -718,13 +1072,25 @@ void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, u
|
|||
foreground = val >> 4;
|
||||
background = val & 0x0F;
|
||||
}
|
||||
else if (g_RGBVideocard == RGB_Videocard_e::Video7_SL7 && character < 0x80)
|
||||
{
|
||||
// in regular 40COL mode, the SL7 videocard renders inverse characters as B&W
|
||||
foreground = 15;
|
||||
background = 0;
|
||||
}
|
||||
|
||||
UpdateDuochromeCell(2, 14, pVideoAddress, bits, foreground, background);
|
||||
}
|
||||
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits)
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character)
|
||||
{
|
||||
UpdateDuochromeCell(2, 7, pVideoAddress, bits, g_nRegularTextFG, g_nRegularTextBG);
|
||||
if (g_RGBVideocard == RGB_Videocard_e::Video7_SL7 && character < 0x80)
|
||||
{
|
||||
// in all 80COL modes, the SL7 videocard renders inverse characters as B&W
|
||||
UpdateDuochromeCell(2, 7, pVideoAddress, bits, 15, 0);
|
||||
}
|
||||
else
|
||||
UpdateDuochromeCell(2, 7, pVideoAddress, bits, g_nRegularTextFG, g_nRegularTextBG);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -755,8 +1121,8 @@ void UpdateDuochromeCell(int h, int w, bgra_t* pVideoAddress, uint8_t bits, uint
|
|||
background += 12;
|
||||
foreground += 12;
|
||||
// get bg/fg colors
|
||||
colors[0] = PalIndex2RGB[background];
|
||||
colors[1] = PalIndex2RGB[foreground];
|
||||
colors[0] = g_pPaletteRGB[background];
|
||||
colors[1] = g_pPaletteRGB[foreground];
|
||||
int nbits = bits;
|
||||
int doublepixels = (w == 14); // Double pixel (HiRes or Text40)
|
||||
|
||||
|
@ -815,11 +1181,24 @@ void VideoInitializeOriginal(baseColors_t pBaseNtscColors)
|
|||
// CREATE THE SOURCE IMAGE AND DRAW INTO THE SOURCE BIT BUFFER
|
||||
V_CreateDIBSections();
|
||||
|
||||
memcpy(&PalIndex2RGB[BLACK], *pBaseNtscColors, sizeof(RGBQUAD)*kNumBaseColors);
|
||||
PalIndex2RGB[HGR_BLUE] = PalIndex2RGB[BLUE];
|
||||
PalIndex2RGB[HGR_ORANGE] = PalIndex2RGB[ORANGE];
|
||||
PalIndex2RGB[HGR_GREEN] = PalIndex2RGB[GREEN];
|
||||
PalIndex2RGB[HGR_VIOLET] = PalIndex2RGB[MAGENTA];
|
||||
// Replace the default palette with true NTSC-generated colors
|
||||
memcpy(&PaletteRGB_NTSC[BLACK], *pBaseNtscColors, sizeof(RGBQUAD) * kNumBaseColors);
|
||||
PaletteRGB_NTSC[HGR_BLUE] = PaletteRGB_NTSC[BLUE];
|
||||
PaletteRGB_NTSC[HGR_ORANGE] = PaletteRGB_NTSC[ORANGE];
|
||||
PaletteRGB_NTSC[HGR_GREEN] = PaletteRGB_NTSC[GREEN];
|
||||
PaletteRGB_NTSC[HGR_VIOLET] = PaletteRGB_NTSC[MAGENTA];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// RGB videocards may use a different palette thant the NTSC-generated one
|
||||
void VideoSwitchVideocardPalette(RGB_Videocard_e videocard, VideoType_e type)
|
||||
{
|
||||
g_pPaletteRGB = PaletteRGB_NTSC;
|
||||
if (type==VideoType_e::VT_COLOR_VIDEOCARD_RGB && videocard == RGB_Videocard_e::LeChatMauve_Feline)
|
||||
{
|
||||
g_pPaletteRGB = PaletteRGB_Feline;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -837,13 +1216,14 @@ static bool g_rgbInvertBit7 = false;
|
|||
// . NB. There's a final 5th AN3 transition to set DHGR mode
|
||||
void RGB_SetVideoMode(WORD address)
|
||||
{
|
||||
if ((address&~1) == 0x0C) // 0x0C or 0x0D? (80COL)
|
||||
|
||||
if ((address & ~1) == 0x0C) // 0x0C or 0x0D? (80COL)
|
||||
{
|
||||
g_rgbSet80COL = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address&~1) != 0x5E) // 0x5E or 0x5F? (DHIRES)
|
||||
if ((address & ~1) != 0x5E) // 0x5E or 0x5F? (DHIRES)
|
||||
return;
|
||||
|
||||
// Precondition before toggling AN3:
|
||||
|
@ -853,33 +1233,37 @@ void RGB_SetVideoMode(WORD address)
|
|||
// . Apple II desktop sets DHGR B&W mode with HIRES off! (GH#631)
|
||||
// Maybe there is no video-mode precondition?
|
||||
// . After setting 80COL on/off then need a 0x5E->0x5F toggle. So if we see a 0x5F then reset (GH#633)
|
||||
if ((g_uVideoMode & VF_MIXED) || (g_rgbSet80COL && address == 0x5F))
|
||||
{
|
||||
g_rgbMode = 0;
|
||||
g_rgbPrevAN3Addr = 0;
|
||||
g_rgbSet80COL = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (address == 0x5F && g_rgbPrevAN3Addr == 0x5E) // Check for AN3 clock transition
|
||||
// From Video7 patent and Le Chat Mauve manuals (under patent of Video7), no precondition is needed.
|
||||
|
||||
// In Prince of Persia, in the game demo, the RGB card switches to BW DHIRES after the HGR animation with Jaffar.
|
||||
// It's actually the same on real hardware (tested on IIc RGB adapter).
|
||||
|
||||
if (address == 0x5F)
|
||||
{
|
||||
g_rgbFlags = (g_rgbFlags<<1) & 3;
|
||||
g_rgbFlags |= ((g_uVideoMode & VF_80COL) ? 0 : 1); // clock in !80COL
|
||||
g_rgbMode = g_rgbFlags; // latch F2,F1
|
||||
if ((g_rgbPrevAN3Addr == 0x5E) && g_rgbSet80COL)
|
||||
{
|
||||
g_rgbFlags = (g_rgbFlags << 1) & 3;
|
||||
g_rgbFlags |= ((g_uVideoMode & VF_80COL) ? 0 : 1); // clock in !80COL
|
||||
g_rgbMode = g_rgbFlags; // latch F2,F1
|
||||
}
|
||||
|
||||
g_rgbSet80COL = false;
|
||||
}
|
||||
|
||||
g_rgbPrevAN3Addr = address;
|
||||
g_rgbSet80COL = false;
|
||||
}
|
||||
|
||||
bool RGB_Is140Mode(void) // Extended 80-Column Text/AppleColor Card's Mode 2
|
||||
{
|
||||
return g_rgbMode == 0;
|
||||
// Feline falls back to this mode instead of 160
|
||||
return g_rgbMode == 0 || (g_RGBVideocard == RGB_Videocard_e::LeChatMauve_Feline && g_rgbMode == 1);
|
||||
}
|
||||
|
||||
bool RGB_Is160Mode(void) // Extended 80-Column Text/AppleColor Card: N/A
|
||||
{
|
||||
return g_rgbMode == 1;
|
||||
// Unsupported by Feline
|
||||
return g_rgbMode == 1 && (g_RGBVideocard != RGB_Videocard_e::LeChatMauve_Feline);
|
||||
}
|
||||
|
||||
bool RGB_IsMixMode(void) // Extended 80-Column Text/AppleColor Card's Mode 3
|
||||
|
|
|
@ -10,18 +10,21 @@ enum RGB_Videocard_e
|
|||
|
||||
|
||||
void UpdateHiResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool updateAux, bool updateMain);
|
||||
void UpdateDHiResCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool updateAux, bool updateMain);
|
||||
void UpdateDHiResCellRGB(int x, int y, uint16_t addr, bgra_t* pVideoAddress, bool isMixMode, bool isBit7Inversed);
|
||||
int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateLoResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateDLoResCell(int x, int y, uint16_t addr, bgra_t *pVideoAddress);
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits);
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits);
|
||||
void UpdateText40ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character);
|
||||
void UpdateText80ColorCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress, uint8_t bits, uint8_t character);
|
||||
void UpdateHiResDuochromeCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress);
|
||||
void UpdateDuochromeCell(int h, int w, bgra_t* pVideoAddress, uint8_t bits, uint8_t foreground, uint8_t background);
|
||||
void UpdateHiResRGBCell(int x, int y, uint16_t addr, bgra_t* pVideoAddress);
|
||||
|
||||
const UINT kNumBaseColors = 16;
|
||||
typedef bgra_t (*baseColors_t)[kNumBaseColors];
|
||||
void VideoInitializeOriginal(baseColors_t pBaseNtscColors);
|
||||
void VideoSwitchVideocardPalette(RGB_Videocard_e videocard, VideoType_e type);
|
||||
|
||||
void RGB_SetVideoMode(WORD address);
|
||||
bool RGB_Is140Mode(void);
|
||||
|
|
|
@ -101,8 +101,9 @@ static LPDIRECTDRAW g_lpDD = NULL;
|
|||
// NOTE: KEEP IN SYNC: VideoType_e g_aVideoChoices g_apVideoModeDesc
|
||||
TCHAR g_aVideoChoices[] =
|
||||
TEXT("Monochrome (Custom)\0")
|
||||
TEXT("Color (RGB Monitor)\0")
|
||||
TEXT("Color (NTSC Monitor)\0")
|
||||
TEXT("Color (Composite Idealized)\0") // newly added
|
||||
TEXT("Color (RGB Card/Monitor)\0") // was "Color (RGB Monitor)"
|
||||
TEXT("Color (Composite Monitor)\0") // was "Color (NTSC Monitor)"
|
||||
TEXT("Color TV\0")
|
||||
TEXT("B&W TV\0")
|
||||
TEXT("Monochrome (Amber)\0")
|
||||
|
@ -114,14 +115,15 @@ static LPDIRECTDRAW g_lpDD = NULL;
|
|||
// The window title will be set to this.
|
||||
const char *g_apVideoModeDesc[ NUM_VIDEO_MODES ] =
|
||||
{
|
||||
"Monochrome Monitor (Custom)"
|
||||
, "Color (RGB Monitor)"
|
||||
, "Color (NTSC/PAL Monitor)"
|
||||
"Monochrome (Custom)"
|
||||
, "Color (Composite Idealized)"
|
||||
, "Color (RGB Card/Monitor)"
|
||||
, "Color (Composite Monitor)"
|
||||
, "Color TV"
|
||||
, "B&W TV"
|
||||
, "Amber Monitor"
|
||||
, "Green Monitor"
|
||||
, "White Monitor"
|
||||
, "Monochrome (Amber)"
|
||||
, "Monochrome (Green)"
|
||||
, "Monochrome (White)"
|
||||
};
|
||||
|
||||
// Prototypes (Private) _____________________________________________
|
||||
|
@ -615,6 +617,7 @@ void VideoReinitialize (bool bInitVideoScannerAddress /*= true*/)
|
|||
NTSC_SetVideoStyle();
|
||||
NTSC_SetVideoTextMode( g_uVideoMode & VF_80COL ? 80 : 40 );
|
||||
NTSC_SetVideoMode( g_uVideoMode ); // Pre-condition: g_nVideoClockHorz (derived from g_dwCyclesThisFrame)
|
||||
VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
{
|
||||
VT_MONO_CUSTOM
|
||||
, VT_COLOR_MONITOR_RGB // Color rendering from AppleWin 1.25 (GH#357)
|
||||
, VT_COLOR_VIDEOCARD_RGB // Real RGB card rendering
|
||||
, VT_COLOR_MONITOR_NTSC // NTSC or PAL
|
||||
, VT_COLOR_TV
|
||||
, VT_MONO_TV
|
||||
|
|
Loading…
Add table
Reference in a new issue