Added floating bus emulation.

Summary of changes:
AppleWin.cpp: Made dwCyclesThisFrame global -> g_dwCyclesThisFrame.
CPU.cpp: Made InternalCpuExecute()'s nCyclesLeft static -> nInternalCyclesLeft.
CPU.cpp: Added CpuGetCyclesThisFrame().
Memory.cpp: Added MemGet80Store().
Memory.cpp: Added MemReadFloatingBus().
Memory.cpp: Added MemReadFloatingBus(BYTE const highbit).
Memory.cpp: Changed NullIo() to call MemReadFloatingBus().
Video.cpp: Added video scanner constants and VideoGetScannerAddress(bool* pbVblBar_OUT).
Video.cpp: Changed VideoCheckVbl() to call VideoGetScannerAddress().
Various files: Replaced MemReturnRandomData() calls with MemReadFloatingBus().
This commit is contained in:
nick_westgate 2006-03-12 09:05:39 +00:00
parent 92b86a43e1
commit 35ec4f29b2
10 changed files with 211 additions and 59 deletions

View File

@ -53,6 +53,8 @@ double g_fCurrentCLK6502 = CLK_6502; // Affected by Config dialog's speed slide
static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
int g_nCpuCyclesFeedback = 0;
DWORD g_dwCyclesThisFrame = 0;
FILE* g_fh = NULL;
bool g_bDisableDirectSound = false;
@ -86,7 +88,6 @@ ULONGLONG g_nPerfFreq = 0;
void ContinueExecution()
{
static DWORD dwCyclesThisFrame = 0;
static BOOL pageflipping = 0; //?
const double fUsecPerSec = 1.e6;
@ -128,7 +129,7 @@ void ContinueExecution()
DWORD dwExecutedCycles = CpuExecute(nCyclesToExecute);
dwCyclesThisFrame += dwExecutedCycles;
g_dwCyclesThisFrame += dwExecutedCycles;
//
@ -137,7 +138,7 @@ void ContinueExecution()
CheckFastPaging();
DiskUpdatePosition(dwExecutedCycles);
JoyUpdatePosition();
VideoUpdateVbl(dwCyclesThisFrame);
VideoUpdateVbl(g_dwCyclesThisFrame);
SpkrUpdate(cyclenum);
CommUpdate(cyclenum);
@ -182,9 +183,9 @@ void ContinueExecution()
//
if(dwCyclesThisFrame >= dwClksPerFrame)
if(g_dwCyclesThisFrame >= dwClksPerFrame)
{
dwCyclesThisFrame -= dwClksPerFrame;
g_dwCyclesThisFrame -= dwClksPerFrame;
if(mode != MODE_LOGO)
{

View File

@ -18,7 +18,9 @@ extern BOOL restart;
extern DWORD g_dwSpeed;
extern double g_fCurrentCLK6502;
extern int g_nCpuCyclesFeedback;
extern int g_nCpuCyclesFeedback;
extern DWORD g_dwCyclesThisFrame;
extern FILE* g_fh; // Filehandle for log file
extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (so no MB support)

View File

@ -104,6 +104,8 @@ unsigned __int64 g_nCumulativeCycles = 0;
static ULONG g_nCyclesSubmitted; // Number of cycles submitted to CpuExecute()
static ULONG g_nCyclesExecuted;
static signed long nInternalCyclesLeft;
/****************************************************************************
*
* GENERAL PURPOSE MACROS
@ -132,10 +134,10 @@ static ULONG g_nCyclesExecuted;
regs.sp = 0x1FF;
#define READ ( \
((addr & 0xFF00) == 0xC000) \
? ioread[addr & 0xFF](regs.pc,(BYTE)addr,0,0,nCyclesLeft) \
? ioread[addr & 0xFF](regs.pc,(BYTE)addr,0,0,nInternalCyclesLeft) \
: ( \
(((addr & 0xFF00) == 0xC400) || ((addr & 0xFF00) == 0xC500)) \
? CxReadFunc(regs.pc, addr, 0, 0, nCyclesLeft) \
? CxReadFunc(regs.pc, addr, 0, 0, nInternalCyclesLeft) \
: *(mem+addr) \
) \
)
@ -152,9 +154,9 @@ static ULONG g_nCyclesExecuted;
if (page) \
*(page+(addr & 0xFF)) = (BYTE)(a); \
else if ((addr & 0xFF00) == 0xC000) \
iowrite[addr & 0xFF](regs.pc,(BYTE)addr,1,(BYTE)(a),nCyclesLeft); \
iowrite[addr & 0xFF](regs.pc,(BYTE)addr,1,(BYTE)(a),nInternalCyclesLeft); \
else if(((addr & 0xFF00) == 0xC400) || ((addr & 0xFF00) == 0xC500)) \
CxWriteFunc(regs.pc, addr, 1, (BYTE)(a), nCyclesLeft); \
CxWriteFunc(regs.pc, addr, 1, (BYTE)(a), nInternalCyclesLeft); \
}
//
@ -483,7 +485,7 @@ static DWORD InternalCpuExecute (DWORD totalcycles)
do
{
signed long nCyclesLeft = (totalcycles<<8) - (cycles<<8);
nInternalCyclesLeft = (totalcycles<<8) - (cycles<<8);
USHORT uExtraCycles = 0;
if(regs.bIRQ && !(regs.ps & AF_INTERRUPT))
@ -819,6 +821,14 @@ void CpuCalcCycles(ULONG nCyclesLeft)
//===========================================================================
ULONG CpuGetCyclesThisFrame()
{
CpuCalcCycles(nInternalCyclesLeft); // TODO: simplify the whole cycle system!
return g_dwCyclesThisFrame + g_nCyclesExecuted;
}
//===========================================================================
DWORD CpuExecute (DWORD cycles)
{
static BOOL laststep = 0;

View File

@ -22,6 +22,7 @@ void CpuDestroy ();
void CpuCalcCycles(ULONG nCyclesLeft);
DWORD CpuExecute (DWORD);
void CpuGetCode (WORD,LPBYTE *,DWORD *);
ULONG CpuGetCyclesThisFrame();
void CpuInitialize ();
void CpuReinitialize ();
void CpuResetCompilerData ();

View File

@ -395,7 +395,7 @@ BYTE __stdcall JoyReadButton (WORD, BYTE address, BYTE, BYTE, ULONG)
break;
}
return MemReturnRandomData(pressed);
return MemReadFloatingBus(pressed);
}
//===========================================================================
@ -431,7 +431,7 @@ BYTE __stdcall JoyReadPosition (WORD programcounter, BYTE address, BYTE, BYTE, U
BOOL nPdlCntrActive = g_nCumulativeCycles <= (g_nJoyCntrResetCycle + (unsigned __int64) ((double)nPdlPos * PDL_CNTR_INTERVAL));
return MemReturnRandomData(nPdlCntrActive);
return MemReadFloatingBus(nPdlCntrActive);
}
//===========================================================================
@ -453,7 +453,7 @@ BYTE __stdcall JoyResetPosition (WORD, BYTE, BYTE, BYTE, ULONG nCyclesLeft)
if(joyinfo[joytype[1]].device == DEVICE_JOYSTICK)
CheckJoystick1();
return MemReturnRandomData(1);
return MemReadFloatingBus();
}
//===========================================================================

View File

@ -616,37 +616,14 @@ void BackMainImage () {
//===========================================================================
BYTE __stdcall NullIo (WORD programcounter, BYTE address, BYTE write, BYTE value, ULONG nCycles) {
if ((address & 0xF0) == 0xA0) {
static const BYTE retval[16] = {0x58,0xFC,0x5B,0xFF,0x58,0xFC,0x5B,0xFF,
0x0B,0x10,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
return retval[address & 15];
}
else if ((address >= 0xB0) && (address <= 0xCF)) {
BYTE r = (BYTE)(rand() & 0xFF);
if (r >= 0x10)
return 0xA0;
else if (r >= 8)
return (r > 0xC) ? 0xFF : 0x00;
else
return (address & 0xF7);
}
else if ((address & 0xF0) == 0xD0) {
BYTE r = (BYTE)(rand() & 0xFF);
if (r >= 0xC0)
return 0xC0;
else if (r >= 0x80)
return 0x80;
else if ((address == 0xD0) || (address == 0xDF))
return 0;
else if (r >= 0x40)
return 0x40;
else if (r >= 0x30)
return 0x90;
else
return 0;
}
else
return MemReturnRandomData(1);
if (!write)
{
return MemReadFloatingBus();
}
else
{
return 0;
}
}
//===========================================================================
@ -837,6 +814,13 @@ void MemDestroy () {
ZeroMemory(memshadow,sizeof(memshadow));
}
//===========================================================================
bool MemGet80Store()
{
return SW_80STORE != 0;
}
//===========================================================================
LPBYTE MemGetAuxPtr (WORD offset)
{
@ -1018,6 +1002,21 @@ BYTE MemReturnRandomData (BYTE highbit) {
return retval[r & 15] | (highbit ? 0x80 : 0);
}
//===========================================================================
BYTE MemReadFloatingBus()
{
return*(LPBYTE)(mem + VideoGetScannerAddress());
}
//===========================================================================
BYTE MemReadFloatingBus(BYTE const highbit)
{
BYTE r = *(LPBYTE)(mem + VideoGetScannerAddress());
return (r & ~0x80) | ((highbit) ? 0x80 : 0);
}
//===========================================================================
void MemSetFastPaging (BOOL on) {
if (fastpaging && modechanging) {
@ -1110,13 +1109,13 @@ BYTE __stdcall MemSetPaging (WORD programcounter, BYTE address, BYTE write, BYTE
if ((address >= 4) && (address <= 5) &&
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
modechanging = 1;
return write ? 0 : MemReturnRandomData(1);
return write ? 0 : MemReadFloatingBus(1);
}
if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
(((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
modechanging = 1;
return write ? 0 : MemReturnRandomData(1);
return write ? 0 : MemReadFloatingBus(1);
}
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
@ -1142,10 +1141,9 @@ BYTE __stdcall MemSetPaging (WORD programcounter, BYTE address, BYTE write, BYTE
}
if ((address <= 1) || ((address >= 0x54) && (address <= 0x57)))
VideoSetMode(programcounter,address,write,value,0);
return write ? 0
: MemReturnRandomData(((address == 0x54) || (address == 0x55))
? (SW_PAGE2 != 0) : 1);
return VideoSetMode(programcounter,address,write,value,0);
return write ? 0 : MemReadFloatingBus();
}
//===========================================================================

View File

@ -24,9 +24,12 @@ extern UINT g_uMaxExPages; // user requested ram pages (from cmd line)
#endif
void MemDestroy ();
bool MemGet80Store();
LPBYTE MemGetAuxPtr (WORD);
LPBYTE MemGetMainPtr (WORD);
void MemInitialize ();
BYTE MemReadFloatingBus();
BYTE MemReadFloatingBus(BYTE highbit);
void MemReset ();
void MemResetPaging ();
BYTE MemReturnRandomData (BYTE highbit);

View File

@ -492,7 +492,7 @@ BYTE __stdcall SpkrToggle (WORD, BYTE address, BYTE write, BYTE, ULONG nCyclesLe
}
return MemReturnRandomData(1);
return MemReadFloatingBus();
}
//=============================================================================

View File

@ -150,6 +150,23 @@ enum Color_Palette_Index_e
#define HGR_MATRIX_YOFFSET 2 // For tv emulation mode
// video scanner constants
int const kHBurstClock = 53; // clock when Color Burst starts
int const kHBurstClocks = 4; // clocks per Color Burst duration
int const kHClock0State = 0x18; // H[543210] = 011000
int const kHClocks = 65; // clocks per horizontal scan (including HBL)
int const kHPEClock = 40; // clock when HPE (horizontal preset enable) goes low
int const kHPresetClock = 41; // clock when H state presets
int const kHSyncClock = 49; // clock when HSync starts
int const kHSyncClocks = 4; // clocks per HSync duration
int const kNTSCScanLines = 262; // total scan lines including VBL (NTSC)
int const kNTSCVSyncLine = 224; // line when VSync starts (NTSC)
int const kPALScanLines = 312; // total scan lines including VBL (PAL)
int const kPALVSyncLine = 264; // line when VSync starts (PAL)
int const kVLine0State = 0x100; // V[543210CBA] = 100000000
int const kVPresetLine = 256; // line when V state presets
int const kVSyncLines = 4; // lines per VSync duration
typedef BOOL (*UpdateFunc_t)(int,int,int,int,int);
static BYTE celldirty[40][32];
@ -195,6 +212,8 @@ DWORD videotype = VT_COLOR_TVEMU;
static bool g_bTextFlashState = false;
static bool g_bTextFlashFlag = false;
static bool bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
//-------------------------------------
// Video consts:
@ -1430,7 +1449,7 @@ void VideoBenchmark () {
DiskUpdatePosition(executedcycles);
JoyUpdatePosition();
VideoUpdateVbl(0);
}
}
}
if (cycle & 1)
FillMemory(mem+0x2000,0x2000,0xAA);
@ -1465,7 +1484,7 @@ void VideoBenchmark () {
//===========================================================================
BYTE __stdcall VideoCheckMode (WORD, BYTE address, BYTE, BYTE, ULONG) {
if (address == 0x7F)
return MemReturnRandomData(SW_DHIRES != 0);
return MemReadFloatingBus(SW_DHIRES != 0);
else {
BOOL result = 0;
switch (address) {
@ -1526,13 +1545,18 @@ BYTE __stdcall VideoCheckVbl (WORD, BYTE, BYTE, BYTE, ULONG)
BBBE F0 F5 BEQ $BBB5
BBC0 C9 0F CMP #$0F
BBC2 F0 F1 BEQ $BBB5
*/
// return MemReturnRandomData(dwVBlCounter <= nVBlStop_NTSC);
if (dwVBlCounter <= nVBlStop_NTSC)
return (BYTE)(dwVBlCounter & 0x7F); // 0x00;
else
return 0x80 | ((BYTE)(dwVBlCounter & 1));
*/
bool bVblBar;
VideoGetScannerAddress(&bVblBar);
BYTE r = KeybGetKeycode();
return (r & ~0x80) | ((bVblBar) ? 0x80 : 0);
}
//===========================================================================
@ -1957,10 +1981,7 @@ BYTE __stdcall VideoSetMode (WORD, BYTE address, BYTE write, BYTE, ULONG) {
}
lastpageflip = emulmsec;
}
if (address == 0x50)
return VideoCheckVbl(0,0,0,0,0);
else
return MemReturnRandomData(1);
return MemReadFloatingBus();
}
//===========================================================================
@ -2006,6 +2027,8 @@ DWORD VideoGetSnapshot(SS_IO_Video* pSS)
return 0;
}
//===========================================================================
DWORD VideoSetSnapshot(SS_IO_Video* pSS)
{
charoffs = !pSS->bAltCharSet ? 0 : 256;
@ -2018,3 +2041,116 @@ DWORD VideoSetSnapshot(SS_IO_Video* pSS)
return 0;
}
//===========================================================================
WORD VideoGetScannerAddress(bool* pbVblBar_OUT)
{
// get video scanner position
//
int nCycles = CpuGetCyclesThisFrame();
// machine state switches
//
int nHires = (SW_HIRES) ? 1 : 0;
int nPage2 = (SW_PAGE2) ? 1 : 0;
int n80Store = (MemGet80Store()) ? 1 : 0;
// calculate video parameters according to display standard
//
int nScanLines = bVideoScannerNTSC ? kNTSCScanLines : kPALScanLines;
int nVSyncLine = bVideoScannerNTSC ? kNTSCVSyncLine : kPALVSyncLine;
int nScanCycles = nScanLines * kHClocks;
// calculate horizontal scanning state
//
int nHClock = (nCycles + kHPEClock) % kHClocks; // which horizontal scanning clock
int nHState = kHClock0State + nHClock; // H state bits
if (nHClock >= kHPresetClock) // check for horizontal preset
{
nHState -= 1; // correct for state preset (two 0 states)
}
int h_0 = (nHState >> 0) & 1; // get horizontal state bits
int h_1 = (nHState >> 1) & 1;
int h_2 = (nHState >> 2) & 1;
int h_3 = (nHState >> 3) & 1;
int h_4 = (nHState >> 4) & 1;
int h_5 = (nHState >> 5) & 1;
// calculate vertical scanning state
//
int nVLine = nCycles / kHClocks; // which vertical scanning line
int nVState = kVLine0State + nVLine; // V state bits
if ((nVLine >= kVPresetLine)) // check for previous vertical state preset
{
nVState -= nScanLines; // compensate for preset
}
int v_A = (nVState >> 0) & 1; // get vertical state bits
int v_B = (nVState >> 1) & 1;
int v_C = (nVState >> 2) & 1;
int v_0 = (nVState >> 3) & 1;
int v_1 = (nVState >> 4) & 1;
int v_2 = (nVState >> 5) & 1;
int v_3 = (nVState >> 6) & 1;
int v_4 = (nVState >> 7) & 1;
int v_5 = (nVState >> 8) & 1;
// calculate scanning memory address
//
if (SW_HIRES && SW_MIXED && (v_4 & v_2))
{
nHires = 0; // (address is in text memory)
}
int nAddend0 = 0x68; // 1 1 0 1
int nAddend1 = (h_5 << 5) | (h_4 << 4) | (h_3 << 3);
int nAddend2 = (v_4 << 6) | (v_3 << 5) | (v_4 << 4) | (v_3 << 3);
int nSum = (nAddend0 + nAddend1 + nAddend2) & (0x0F << 3);
int nAddress = 0;
nAddress |= h_0 << 0; // a0
nAddress |= h_1 << 1; // a1
nAddress |= h_2 << 2; // a2
nAddress |= nSum; // a3 - aa6
nAddress |= v_0 << 7; // a7
nAddress |= v_1 << 8; // a8
nAddress |= v_2 << 9; // a9
nAddress |= ((nHires) ? v_A : (1 ^ (nPage2 & (1 ^ n80Store)))) << 10; // a10
nAddress |= ((nHires) ? v_B : (nPage2 & (1 ^ n80Store))) << 11; // a11
if (nHires) // hires?
{
// Y: insert hires only address bits
//
nAddress |= v_C << 12; // a12
nAddress |= (1 ^ (nPage2 & (1 ^ n80Store))) << 13; // a13
nAddress |= (nPage2 & (1 ^ n80Store)) << 14; // a14
}
else
{
// N: text, so no higher address bits unless Apple ][, not Apple //e
//
if ((!apple2e) && // Apple ][?
(kHPEClock <= nHClock) && // Y: HBL?
(nHClock <= (kHClocks - 1)))
{
nAddress |= 1 << 12; // Y: a12 (add $1000 to address!)
}
}
// update VBL' state
//
if (pbVblBar_OUT != NULL)
{
if (v_4 & v_3) // VBL?
{
*pbVblBar_OUT = false; // Y: VBL' is false
}
else
{
*pbVblBar_OUT = true; // N: VBL' is true
}
}
return static_cast<WORD>(nAddress);
}
//===========================================================================

View File

@ -32,6 +32,7 @@ void VideoRedrawScreen ();
void VideoRefreshScreen ();
void VideoReinitialize ();
void VideoResetState ();
WORD VideoGetScannerAddress(bool* pbVblBar_OUT = NULL);
void VideoUpdateVbl (DWORD dwCyclesThisFrame);
void VideoUpdateFlash();
bool VideoGetSW80COL();