Improve VideoGetScannerAddress() to generate NTSC tables; and check tables with all video cycles

This commit is contained in:
tomcw 2018-08-05 22:19:51 +01:00
parent 5e02eaee53
commit d623533e06
3 changed files with 121 additions and 70 deletions

View File

@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Includes // Includes
#include "StdAfx.h" #include "StdAfx.h"
#include "Applewin.h" #include "Applewin.h"
#include "CPU.h" #include "CPU.h" // CpuGetCyclesThisVideoFrame()
#include "Frame.h" // FRAMEBUFFER_W FRAMEBUFFER_H #include "Frame.h" // FRAMEBUFFER_W FRAMEBUFFER_H
#include "Memory.h" // MemGetMainPtr() MemGetBankPtr() #include "Memory.h" // MemGetMainPtr() MemGetBankPtr()
#include "Video.h" // g_pFramebufferbits #include "Video.h" // g_pFramebufferbits
@ -41,9 +41,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "ntsc_rgb.h" #include "ntsc_rgb.h"
#endif #endif
//LPBYTE MemGetMainPtr(const WORD);
//LPBYTE MemGetBankPtr(const UINT nBank);
// Defines // Defines
#define HGR_TEST_PATTERN 0 #define HGR_TEST_PATTERN 0
@ -199,8 +196,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define SIGNAL_1 0.7465656072f #define SIGNAL_1 0.7465656072f
// Tables // Tables
static unsigned short g_aClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ]; // Video scanner tables are now runtime-generated using UTAIIe logic
static unsigned short g_aClockVertOffsetsHGR[VIDEO_SCANNER_MAX_VERT];
static unsigned short g_aClockVertOffsetsTXT[33];
static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
#ifdef _DEBUG
static unsigned short g_kClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ] = static unsigned short g_kClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ] =
{ {
0x0000,0x0400,0x0800,0x0C00,0x1000,0x1400,0x1800,0x1C00,0x0080,0x0480,0x0880,0x0C80,0x1080,0x1480,0x1880,0x1C80, 0x0000,0x0400,0x0800,0x0C00,0x1000,0x1400,0x1800,0x1C00,0x0080,0x0480,0x0880,0x0C80,0x1080,0x1480,0x1880,0x1C80,
@ -226,8 +228,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0B80,0x0F80,0x1380,0x1780,0x1B80,0x1F80 0x0B80,0x0F80,0x1380,0x1780,0x1B80,0x1F80
}; };
static unsigned short g_aClockVertOffsetsTXT[33];
static unsigned short g_kClockVertOffsetsTXT[33] = static unsigned short g_kClockVertOffsetsTXT[33] =
{ {
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380, 0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
@ -238,8 +238,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x380 0x380
}; };
static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
static unsigned short kAPPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] = static unsigned short kAPPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{ {
{0x1068,0x1068,0x1069,0x106A,0x106B,0x106C,0x106D,0x106E,0x106F, {0x1068,0x1068,0x1069,0x106A,0x106B,0x106C,0x106D,0x106E,0x106F,
@ -288,8 +286,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F} 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F}
}; };
static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
static unsigned short kAPPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] = static unsigned short kAPPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{ {
{0x0068,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, {0x0068,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
@ -337,6 +333,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F} 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F}
}; };
#endif
/* /*
http://www.kreativekorp.com/miscpages/a2info/munafo.shtml http://www.kreativekorp.com/miscpages/a2info/munafo.shtml
@ -397,11 +394,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static csbits_t csbits; // charset, optionally followed by alt charset static csbits_t csbits; // charset, optionally followed by alt charset
// Prototypes // Prototypes
// prototype from CPU.h
//unsigned char CpuRead(unsigned short addr, unsigned long uExecutedCycles);
// prototypes from Memory.h
//unsigned char * MemGetAuxPtr (unsigned short);
//unsigned char * MemGetMainPtr (unsigned short);
INLINE float clampZeroOne( const float & x ); INLINE float clampZeroOne( const float & x );
INLINE uint8_t getCharSetBits( const int iChar ); INLINE uint8_t getCharSetBits( const int iChar );
INLINE uint16_t getLoResBits( uint8_t iByte ); INLINE uint16_t getLoResBits( uint8_t iByte );
@ -419,8 +411,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INLINE void updatePixels( uint16_t bits ); INLINE void updatePixels( uint16_t bits );
INLINE void updateVideoScannerHorzEOL(); INLINE void updateVideoScannerHorzEOL();
INLINE void updateVideoScannerAddress(); INLINE void updateVideoScannerAddress();
INLINE uint16_t updateVideoScannerAddressTXT(); INLINE uint16_t getVideoScannerAddressTXT();
INLINE uint16_t updateVideoScannerAddressHGR(); INLINE uint16_t getVideoScannerAddressHGR();
static void initChromaPhaseTables(); static void initChromaPhaseTables();
static real initFilterChroma (real z); static real initFilterChroma (real z);
@ -775,16 +767,16 @@ inline void updateVideoScannerAddress()
} }
//=========================================================================== //===========================================================================
INLINE uint16_t updateVideoScannerAddressTXT() INLINE uint16_t getVideoScannerAddressTXT()
{ {
return (g_aClockVertOffsetsTXT[g_nVideoClockVert/8] + return (g_aClockVertOffsetsTXT[g_nVideoClockVert/8] +
g_pHorzClockOffset [g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nTextPage * 0x400)); g_pHorzClockOffset [g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nTextPage * 0x400));
} }
//=========================================================================== //===========================================================================
INLINE uint16_t updateVideoScannerAddressHGR() INLINE uint16_t getVideoScannerAddressHGR()
{ {
// NB. Not a bug: For both A2 and //e then use APPLE_IIE_HORZ_CLOCK_OFFSET - see VideoGetScannerAddress() where only TEXT mode adds $1000 // NB. For both A2 and //e use APPLE_IIE_HORZ_CLOCK_OFFSET - see VideoGetScannerAddress() where only TEXT mode adds $1000
return (g_aClockVertOffsetsHGR[g_nVideoClockVert ] + return (g_aClockVertOffsetsHGR[g_nVideoClockVert ] +
APPLE_IIE_HORZ_CLOCK_OFFSET[g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nHiresPage * 0x2000)); APPLE_IIE_HORZ_CLOCK_OFFSET[g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nHiresPage * 0x2000));
} }
@ -1142,7 +1134,7 @@ void updateScreenDoubleHires40 (long cycles6502) // wsUpdateVideoHires0
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressHGR(); uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1173,7 +1165,7 @@ void updateScreenDoubleHires80 (long cycles6502 ) // wsUpdateVideoDblHires
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressHGR(); uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1210,7 +1202,7 @@ void updateScreenDoubleLores40 (long cycles6502) // wsUpdateVideo7MLores
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressTXT(); uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1242,7 +1234,7 @@ void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressTXT(); uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1283,7 +1275,7 @@ void updateScreenSingleHires40 (long cycles6502)
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressHGR(); uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1324,7 +1316,7 @@ void updateScreenSingleLores40 (long cycles6502)
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressTXT(); uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{ {
@ -1350,7 +1342,7 @@ void updateScreenText40 (long cycles6502)
{ {
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressTXT(); uint16_t addr = getVideoScannerAddressTXT();
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG)) if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
{ {
@ -1382,7 +1374,7 @@ void updateScreenText80 (long cycles6502)
{ {
for (; cycles6502 > 0; --cycles6502) for (; cycles6502 > 0; --cycles6502)
{ {
uint16_t addr = updateVideoScannerAddressTXT(); uint16_t addr = getVideoScannerAddressTXT();
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG)) if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
{ {
@ -1477,9 +1469,9 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
uint16_t addr; uint16_t addr;
bool bHires = (g_uVideoMode & VF_HIRES) && !(g_uVideoMode & VF_TEXT); // SW_HIRES && !SW_TEXT bool bHires = (g_uVideoMode & VF_HIRES) && !(g_uVideoMode & VF_TEXT); // SW_HIRES && !SW_TEXT
if( bHires ) if( bHires )
addr = updateVideoScannerAddressHGR(); addr = getVideoScannerAddressHGR();
else else
addr = updateVideoScannerAddressTXT(); addr = getVideoScannerAddressTXT();
g_nVideoClockVert = currVideoClockVert; g_nVideoClockVert = currVideoClockVert;
g_nVideoClockHorz = currVideoClockHorz; g_nVideoClockHorz = currVideoClockHorz;
@ -1839,55 +1831,93 @@ bool NTSC_GetColorBurst( void )
} }
//=========================================================================== //===========================================================================
void GenerateVideoTables( void )
static bool CheckVideoTables2( eApple2Type type, uint32_t mode )
{
SetApple2Type(type);
NTSC_VideoInitAppleType();
g_uVideoMode = mode;
g_dwCyclesThisFrame = 0;
g_nVideoClockHorz = g_nVideoClockVert = 0;
for (DWORD cycles=0; cycles<VIDEO_SCANNER_MAX_VERT*VIDEO_SCANNER_MAX_HORZ; cycles++)
{
WORD addr1 = VideoGetScannerAddress(cycles);
WORD addr2 = g_uVideoMode & VF_TEXT ? getVideoScannerAddressTXT()
: getVideoScannerAddressHGR();
_ASSERT(addr1 == addr2);
if (addr1 != addr2)
{
char str[80];
sprintf(str, "vpos=%04X, hpos=%02X, Video_adr=$%04X, NTSC_adr=$%04X\n", g_nVideoClockVert, g_nVideoClockHorz, addr1, addr2);
OutputDebugString(str);
return false;
}
g_nVideoClockHorz++;
if (g_nVideoClockHorz == VIDEO_SCANNER_MAX_HORZ)
{
g_nVideoClockHorz = 0;
g_nVideoClockVert++;
}
}
return true;
}
static void CheckVideoTables( void )
{
CheckVideoTables2(A2TYPE_APPLE2PLUS, VF_HIRES);
CheckVideoTables2(A2TYPE_APPLE2PLUS, VF_TEXT);
CheckVideoTables2(A2TYPE_APPLE2E, VF_HIRES);
CheckVideoTables2(A2TYPE_APPLE2E, VF_TEXT);
}
static void GenerateVideoTables( void )
{ {
eApple2Type currentApple2Type = GetApple2Type(); eApple2Type currentApple2Type = GetApple2Type();
g_uVideoMode = VF_HIRES; //
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<256; i++, cycle+=VIDEO_SCANNER_MAX_HORZ) // g_aClockVertOffsetsHGR[]
{ //
if (i % 64 == 0) cycle=VIDEO_SCANNER_HORZ_START; // repeat every 64th scanline
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(NULL, cycle) - 0x2000;
_ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
}
// Repeat last 6 entries for scanlines [256...261] g_uVideoMode = VF_HIRES;
const UINT kLine256 = 64 - (VIDEO_SCANNER_MAX_VERT - 256); for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<VIDEO_SCANNER_MAX_VERT; i++, cycle+=VIDEO_SCANNER_MAX_HORZ)
for (UINT i=256, cycle=kLine256*VIDEO_SCANNER_MAX_HORZ+VIDEO_SCANNER_HORZ_START; i<VIDEO_SCANNER_MAX_VERT; i++, cycle+=VIDEO_SCANNER_MAX_HORZ)
{ {
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(NULL, cycle) - 0x2000; g_aClockVertOffsetsHGR[i] = VideoGetScannerAddressPartialV(cycle);
_ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]); _ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
} }
//
// g_aClockVertOffsetsTXT[]
// //
g_uVideoMode = VF_TEXT; g_uVideoMode = VF_TEXT;
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<256/8; i++, cycle+=VIDEO_SCANNER_MAX_HORZ*8) for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<(256+8)/8; i++, cycle+=VIDEO_SCANNER_MAX_HORZ*8)
{ {
if (i % 8 == 0) cycle=VIDEO_SCANNER_HORZ_START; // repeat every 8th scanline g_aClockVertOffsetsTXT[i] = VideoGetScannerAddressPartialV(cycle);
g_aClockVertOffsetsTXT[i] = VideoGetScannerAddress(NULL, cycle) - 0x400;
_ASSERT(g_aClockVertOffsetsTXT[i] == g_kClockVertOffsetsTXT[i]); _ASSERT(g_aClockVertOffsetsTXT[i] == g_kClockVertOffsetsTXT[i]);
} }
g_aClockVertOffsetsTXT[32] = g_aClockVertOffsetsTXT[31]; // repeat last entry for scanlines [256...263] //
_ASSERT(g_aClockVertOffsetsTXT[32] = g_kClockVertOffsetsTXT[31]); // APPLE_IIP_HORZ_CLOCK_OFFSET[]
// //
g_uVideoMode = VF_TEXT; g_uVideoMode = VF_TEXT;
SetApple2Type(A2TYPE_APPLE2); SetApple2Type(A2TYPE_APPLE2PLUS);
for (UINT j=0; j<5; j++) for (UINT j=0; j<5; j++)
{ {
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++) for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
{ {
if (j<4) APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddressPartialH(cycle);
APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddress(NULL, cycle) - 0x400;
else
APPLE_IIP_HORZ_CLOCK_OFFSET[4][i] = APPLE_IIP_HORZ_CLOCK_OFFSET[3][i];
_ASSERT(APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIP_HORZ_CLOCK_OFFSET[j][i]); _ASSERT(APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIP_HORZ_CLOCK_OFFSET[j][i]);
} }
} }
//
// APPLE_IIE_HORZ_CLOCK_OFFSET[]
// //
g_uVideoMode = VF_TEXT; g_uVideoMode = VF_TEXT;
@ -1896,14 +1926,15 @@ void GenerateVideoTables( void )
{ {
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++) for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
{ {
if (j<4) APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddressPartialH(cycle);
APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddress(NULL, cycle) - 0x400;
else
APPLE_IIE_HORZ_CLOCK_OFFSET[4][i] = APPLE_IIE_HORZ_CLOCK_OFFSET[3][i];
_ASSERT(APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIE_HORZ_CLOCK_OFFSET[j][i]); _ASSERT(APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIE_HORZ_CLOCK_OFFSET[j][i]);
} }
} }
//
CheckVideoTables();
VideoResetState(); VideoResetState();
SetApple2Type(currentApple2Type); SetApple2Type(currentApple2Type);
} }

View File

@ -770,7 +770,22 @@ void VideoLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
// References to Jim Sather's books are given as eg: // References to Jim Sather's books are given as eg:
// UTAIIe:5-7,P3 (Understanding the Apple IIe, chapter 5, page 7, Paragraph 3) // UTAIIe:5-7,P3 (Understanding the Apple IIe, chapter 5, page 7, Paragraph 3)
// //
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
static WORD g_PartialV=0, g_PartialH=0;
WORD VideoGetScannerAddressPartialV(DWORD nCycles)
{
VideoGetScannerAddress(nCycles);
return g_PartialV;
}
WORD VideoGetScannerAddressPartialH(DWORD nCycles)
{
VideoGetScannerAddress(nCycles);
return g_PartialH;
}
WORD VideoGetScannerAddress(DWORD nCycles)
{ {
// machine state switches // machine state switches
// //
@ -804,7 +819,7 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
// //
int nVLine = nCycles / kHClocks; // which vertical scanning line int nVLine = nCycles / kHClocks; // which vertical scanning line
int nVState = kVLine0State + nVLine; // V state bits int nVState = kVLine0State + nVLine; // V state bits
if ((nVLine >= kVPresetLine)) // check for previous vertical state preset if (nVLine >= kVPresetLine) // check for previous vertical state preset
{ {
nVState -= nScanLines; // compensate for preset nVState -= nScanLines; // compensate for preset
} }
@ -835,6 +850,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
nAddress |= h_1 << 1; // a1 nAddress |= h_1 << 1; // a1
nAddress |= h_2 << 2; // a2 nAddress |= h_2 << 2; // a2
nAddress |= nSum << 3; // a3 - a6 nAddress |= nSum << 3; // a3 - a6
g_PartialH = nAddress;
nAddress |= v_0 << 7; // a7 nAddress |= v_0 << 7; // a7
nAddress |= v_1 << 8; // a8 nAddress |= v_1 << 8; // a8
nAddress |= v_2 << 9; // a9 nAddress |= v_2 << 9; // a9
@ -849,6 +866,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
nAddress |= v_A << 10; // a10 nAddress |= v_A << 10; // a10
nAddress |= v_B << 11; // a11 nAddress |= v_B << 11; // a11
nAddress |= v_C << 12; // a12 nAddress |= v_C << 12; // a12
g_PartialV = nAddress - g_PartialH;
nAddress |= p2a << 13; // a13 nAddress |= p2a << 13; // a13
nAddress |= p2b << 14; // a14 nAddress |= p2b << 14; // a14
} }
@ -856,24 +875,23 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
{ {
// N: insert text-only address bits // N: insert text-only address bits
// //
nAddress |= p2a << 10; // a10 g_PartialV = nAddress - g_PartialH;
nAddress |= p2b << 11; // a11
// Apple ][ (not //e) and HBL? // Apple ][ (not //e) and HBL?
// //
if (IS_APPLE2 && // Apple II only (UTAIIe:I-4,#5) if (IS_APPLE2 && // Apple II only (UTAIIe:I-4,#5)
!h_5 && (!h_4 || !h_3)) // HBL (UTAIIe:8-10,F8.5) !h_5 && (!h_4 || !h_3)) // HBL (UTAIIe:8-10,F8.5)
{ {
nAddress |= 1 << 12; // Y: a12 (add $1000 to address!) nAddress |= 1 << 12; // Y: a12 (add $1000 to address!)
g_PartialH |= 1 << 12;
} }
}
// update VBL' state nAddress |= p2a << 10; // a10
// nAddress |= p2b << 11; // a11
if (pbVblBar_OUT != NULL)
{
*pbVblBar_OUT = !v_4 || !v_3; // VBL' = (v_4 & v_3)' (UTAIIe:5-10,#3)
} }
// VBL' = v_4' | v_3' = (v_4 & v_3)' (UTAIIe:5-10,#3)
return static_cast<WORD>(nAddress); return static_cast<WORD>(nAddress);
} }

View File

@ -169,7 +169,9 @@ void VideoRedrawScreen (void);
void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false); void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false);
void VideoReinitialize (); void VideoReinitialize ();
void VideoResetState (); void VideoResetState ();
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles); WORD VideoGetScannerAddressPartialV(DWORD nCycles);
WORD VideoGetScannerAddressPartialH(DWORD nCycles);
WORD VideoGetScannerAddress(DWORD nCycles);
bool VideoGetVblBar(DWORD uExecutedCycles); bool VideoGetVblBar(DWORD uExecutedCycles);
bool VideoGetSW80COL(void); bool VideoGetSW80COL(void);