mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-23 00:30:17 +00:00
Improve VideoGetScannerAddress() to generate NTSC tables; and check tables with all video cycles
This commit is contained in:
parent
5e02eaee53
commit
d623533e06
147
source/NTSC.cpp
147
source/NTSC.cpp
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user