Beginnings of Mockingboard tracing for automated testing

This commit is contained in:
Aaron Culliney 2016-07-31 13:03:58 -07:00
parent 5883545390
commit 8921f79a14
8 changed files with 378 additions and 189 deletions

View File

@ -132,7 +132,7 @@ EXTRA_testprefs_SOURCES = $(ASM_SRC_x86) $(VIDEO_SRC) $(AUDIO_SRC) $(META_SRC)
####################################### #######################################
testtrace_SOURCES = src/test/testtrace.c $(A2_TEST_SOURCES) testtrace_SOURCES = src/test/testtrace.c $(A2_TEST_SOURCES)
testtrace_CFLAGS = $(A2_TEST_CFLAGS) -DTEST_TRACE=1 -DCPU_TRACING=1 -DDISK_TRACING=1 -DVM_TRACING=1 -DSPEAKER_TRACING=1 testtrace_CFLAGS = $(A2_TEST_CFLAGS) -DTEST_TRACE=1 -DCPU_TRACING=1 -DDISK_TRACING=1 -DVM_TRACING=1 -DSPEAKER_TRACING=1 -DMB_TRACING=1
testtrace_CCASFLAGS = $(testtrace_CFLAGS) testtrace_CCASFLAGS = $(testtrace_CFLAGS)
testtrace_LDFLAGS = $(apple2ix_LDFLAGS) testtrace_LDFLAGS = $(apple2ix_LDFLAGS)
testtrace_LDADD = @testtrace_ASM_O@ @testtrace_VIDEO_O@ @testtrace_AUDIO_O@ @testtrace_META_O@ @X_LIBS@ testtrace_LDADD = @testtrace_ASM_O@ @testtrace_VIDEO_O@ @testtrace_AUDIO_O@ @testtrace_META_O@ @X_LIBS@

View File

@ -1047,6 +1047,7 @@ void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE1_PERIOD, ay_tone_period[1]); yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE1_PERIOD, ay_tone_period[1]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE2_PERIOD, ay_tone_period[2]); yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE2_PERIOD, ay_tone_period[2]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_PERIOD, ay_noise_period); yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_PERIOD, ay_noise_period);
// APPLE2IX FIXME WHAT ABOUT : SS_YAML_KEY_ENV_PERIOD "Env Period" ... AppleWin forgot about this? Also do this on load ...
yamlSaveHelper.SaveUint(SS_YAML_KEY_RNG, rng); yamlSaveHelper.SaveUint(SS_YAML_KEY_RNG, rng);
yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_TOGGLE, noise_toggle); yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_TOGGLE, noise_toggle);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_FIRST, env_first); yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_FIRST, env_first);
@ -1184,6 +1185,36 @@ static uint64_t g_uLastCumulativeCycles = 0;
static unsigned __int64 g_uLastCumulativeCycles = 0; static unsigned __int64 g_uLastCumulativeCycles = 0;
#endif #endif
#if MB_TRACING
void _mb_trace_AY8910(int chip, FILE *mb_trace_fp) {
if (!mb_trace_fp) {
return;
}
assert(chip < MAX_8910);
CAY8910 *_this = &g_AY8910[chip];
fprintf(mb_trace_fp, "\tAY8910(%d):\n", chip);
fprintf(mb_trace_fp, "\t\tay_tone_tick:%u,%u,%u\n", _this->ay_tone_tick[0], _this->ay_tone_tick[1], _this->ay_tone_tick[2]);
fprintf(mb_trace_fp, "\t\tay_tone_high:%u,%u,%u\n", _this->ay_tone_high[0], _this->ay_tone_high[1], _this->ay_tone_high[2]);
fprintf(mb_trace_fp, "\t\tay_noise_tick:%u ay_tone_subcycles:%u ay_env_subcycles:%u\n", _this->ay_noise_tick, _this->ay_tone_subcycles, _this->ay_env_subcycles);
fprintf(mb_trace_fp, "\t\tay_env_internal_tick:%u ay_env_tick:%u ay_tick_incr:%u\n", _this->ay_env_internal_tick, _this->ay_env_tick, _this->ay_tick_incr);
fprintf(mb_trace_fp, "\t\tay_tone_period:%u,%u,%u\n", _this->ay_tone_period[0], _this->ay_tone_period[1], _this->ay_tone_period[2]);
fprintf(mb_trace_fp, "\t\tay_noise_period:%u ay_env_period:%u rng:%d noise_toggle:%d\n", _this->ay_noise_period, _this->ay_env_period, _this->rng, _this->noise_toggle);
fprintf(mb_trace_fp, "\t\tenv_first:%d env_rev:%d env_counter:%d\n", _this->env_first, _this->env_rev, _this->env_counter);
fprintf(mb_trace_fp, "\t\tenv_first:%d env_rev:%d env_counter:%d\n", _this->env_first, _this->env_rev, _this->env_counter);
fprintf(mb_trace_fp, "\t\tsound_ay_registers: %02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n", _this->sound_ay_registers[0], _this->sound_ay_registers[1], _this->sound_ay_registers[2], _this->sound_ay_registers[3], _this->sound_ay_registers[4], _this->sound_ay_registers[5], _this->sound_ay_registers[6], _this->sound_ay_registers[7], _this->sound_ay_registers[8], _this->sound_ay_registers[9], _this->sound_ay_registers[10], _this->sound_ay_registers[11], _this->sound_ay_registers[12], _this->sound_ay_registers[13], _this->sound_ay_registers[14], _this->sound_ay_registers[15]);
fprintf(mb_trace_fp, "\t\tay_change_count:(%d)\n", _this->ay_change_count);
for (unsigned int i=0; i<_this->ay_change_count; i++) {
fprintf(mb_trace_fp, "\t\t\t%u: tstates:%lu ofs:%04X reg:%02X val:%02X\n", i, _this->ay_change[i].tstates, _this->ay_change[i].ofs, _this->ay_change[i].reg, _this->ay_change[i].val);
}
}
#endif
void _AYWriteReg(int chip, int r, int v) void _AYWriteReg(int chip, int r, int v)
{ {

View File

@ -32,6 +32,9 @@ void AY8910UpdateSetCycles();
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix); UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix); UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
#endif #endif
#if MB_TRACING
void _mb_trace_AY8910(int chip, FILE *mb_trace_fp);
#endif
//------------------------------------- //-------------------------------------
// FUSE stuff // FUSE stuff

View File

@ -19,7 +19,7 @@ Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
AppleWin is distributed in the hope that it will be useful, AppleWin is distributed in the hope that it will be useful,
@ -258,6 +258,13 @@ static short g_nMixBuffer[g_dwDSBufferSize / sizeof(short)];
#if 1 // APPLE2IX #if 1 // APPLE2IX
# if MB_TRACING
static FILE *mb_trace_fp = NULL;
static FILE *mb_trace_samples_fp = NULL;
static unsigned long cycles_mb_toggled_r = 0;
static unsigned long cycles_mb_toggled_w = 0;
# endif
static AudioBuffer_s *MockingboardVoice = NULL; static AudioBuffer_s *MockingboardVoice = NULL;
static AudioBuffer_s *SSI263Voice[64] = { 0 }; static AudioBuffer_s *SSI263Voice[64] = { 0 };
static pthread_cond_t ssi263_cond = PTHREAD_COND_INITIALIZER; static pthread_cond_t ssi263_cond = PTHREAD_COND_INITIALIZER;
@ -361,6 +368,9 @@ static void AY8910_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue, uint8_t
{ {
// RESET: Reset AY8910 only // RESET: Reset AY8910 only
AY8910_reset(nDevice+2*nAYDevice); AY8910_reset(nDevice+2*nAYDevice);
#if MB_TRACING
_mb_trace_AY8910(nDevice+2*nAYDevice, mb_trace_fp);
#endif
} }
else else
{ {
@ -382,6 +392,9 @@ static void AY8910_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue, uint8_t
case AY_WRITE: // 6: WRITE TO PSG case AY_WRITE: // 6: WRITE TO PSG
_AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA); _AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA);
#if MB_TRACING
_mb_trace_AY8910(nDevice+2*nAYDevice, mb_trace_fp);
#endif
break; break;
case AY_LATCH: // 7: LATCH ADDRESS case AY_LATCH: // 7: LATCH ADDRESS
@ -393,6 +406,10 @@ static void AY8910_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue, uint8_t
pMB->nAYCurrentRegister = pMB->sy6522.ORA & 0x0F; pMB->nAYCurrentRegister = pMB->sy6522.ORA & 0x0F;
// else Pro-Mockingboard (clone from HK) // else Pro-Mockingboard (clone from HK)
break; break;
#if 1 // APPLE2IX
default:
mb_assert(false);
#endif
} }
} }
} }
@ -419,6 +436,11 @@ static void UpdateIFR(SY6522_AY8910* pMB)
if (bIRQ) if (bIRQ)
{ {
#if 1 // APPLE2IX #if 1 // APPLE2IX
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\t%s\n", "IRQ_6522");
}
#endif
cpu65_interrupt(IS_6522); cpu65_interrupt(IS_6522);
#else #else
CpuIrqAssert(IS_6522); CpuIrqAssert(IS_6522);
@ -427,6 +449,11 @@ static void UpdateIFR(SY6522_AY8910* pMB)
else else
{ {
#if 1 // APPLE2IX #if 1 // APPLE2IX
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\t%s\n", "!IRQ_6522");
}
#endif
cpu65_uninterrupt(IS_6522); cpu65_uninterrupt(IS_6522);
#else #else
CpuIrqDeassert(IS_6522); CpuIrqDeassert(IS_6522);
@ -434,8 +461,44 @@ static void UpdateIFR(SY6522_AY8910* pMB)
} }
} }
#if MB_TRACING
static void _mb_traceWriteSample(INOUT char **tracingBufPtr, INOUT size_t *tracingBufSize, const char *samPrefix, int dat) {
int sz = INT_MAX;
char *buf = *tracingBufPtr;
int max = (int)*tracingBufSize;
sz = snprintf(buf, max, "%s[%08x]", samPrefix, dat);
assert(sz > 0 && sz < max);
buf += sz;
max -= sz;
assert(max >= 0);
*tracingBufPtr = buf;
*tracingBufSize = (size_t)max;
}
static void _mb_traceSY6522_AY8910(uint8_t nDevice) {
SY6522_AY8910* pMB = &g_MB[nDevice];
fprintf(mb_trace_fp, "\tSYS6522_AY8910(%d) nAY8910Number:%02X nAYCurrentRegister:%02X nTimerStatus:%02X\n", nDevice, pMB->nAY8910Number, pMB->nAYCurrentRegister, pMB->nTimerStatus);
SY6522 *sy6522 = &pMB->sy6522;
fprintf(mb_trace_fp, "\t\tSYS6522 : ORB:%02X ORA:%02X DDRB:%02X DDRA:%02X TIMER1_COUNTER:%04X TIMER1_LATCH:%04X TIMER2_COUNTER:%04X TIMER2_LATCH:%04X SERIAL_SHIFT:%02X ACR:%02X PCR:%02X IFR:%02X IER:%02X ORA_NO_HS:%02X\n", sy6522->ORB, sy6522->ORA, sy6522->DDRB, sy6522->DDRA, sy6522->TIMER1_COUNTER.w, sy6522->TIMER1_LATCH.w, sy6522->TIMER2_COUNTER.w, sy6522->TIMER2_LATCH.w, sy6522->SERIAL_SHIFT, sy6522->ACR, sy6522->PCR, sy6522->IFR, sy6522->IER, sy6522->ORA_NO_HS);
#if 0 // ENABLE_SSI263
TODO FIXME : trace SSI263 stuff
#endif
}
#endif
static void SY6522_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue) static void SY6522_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue)
{ {
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\tSY6522_Write(%02X, %02X, %02X)...\n", nDevice, nReg, nValue);
}
#endif
g_bMB_Active = true; g_bMB_Active = true;
SY6522_AY8910* pMB = &g_MB[nDevice]; SY6522_AY8910* pMB = &g_MB[nDevice];
@ -563,12 +626,23 @@ static void SY6522_Write(uint8_t nDevice, uint8_t nReg, uint8_t nValue)
case 0x0f: // ORA_NO_HS case 0x0f: // ORA_NO_HS
break; break;
} }
#if MB_TRACING
if (mb_trace_fp) {
_mb_traceSY6522_AY8910(nDevice);
}
#endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static uint8_t SY6522_Read(uint8_t nDevice, uint8_t nReg) static uint8_t SY6522_Read(uint8_t nDevice, uint8_t nReg)
{ {
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\tSY6522_Read(%02X, %02X)...\n", nDevice, nReg);
}
#endif
// g_bMB_RegAccessedFlag = true; // g_bMB_RegAccessedFlag = true;
g_bMB_Active = true; g_bMB_Active = true;
@ -630,6 +704,13 @@ static uint8_t SY6522_Read(uint8_t nDevice, uint8_t nReg)
break; break;
} }
#if MB_TRACING
if (mb_trace_fp) {
_mb_traceSY6522_AY8910(nDevice);
fprintf(mb_trace_fp, "\tret:%02X\n", nValue);
}
#endif
return nValue; return nValue;
} }
@ -865,6 +946,11 @@ static void MB_Update()
{ {
return; return;
} }
# if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "%s", "\tMB_Update()\n");
}
# endif
#else #else
char szDbg[200]; char szDbg[200];
@ -874,6 +960,7 @@ static void MB_Update()
if (g_bFullSpeed) if (g_bFullSpeed)
{ {
#if !MB_TRACING
// Keep AY reg writes relative to the current 'frame' // Keep AY reg writes relative to the current 'frame'
// - Required for Ultima3: // - Required for Ultima3:
// . Tune ends // . Tune ends
@ -886,6 +973,7 @@ static void MB_Update()
// If any AY regs have changed then push them out to the AY chip // If any AY regs have changed then push them out to the AY chip
return; return;
#endif
} }
// //
@ -1016,26 +1104,65 @@ static void MB_Update()
return; return;
// //
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "%s", "\tsubmitting samples...\n");
}
#endif
const double fAttenuation = g_bPhasorEnable ? 2.0/3.0 : 1.0; const double fAttenuation = g_bPhasorEnable ? 2.0/3.0 : 1.0;
for(int i=0; i<nNumSamples; i++) for(int i=0; i<nNumSamples; i++)
{ {
#if MB_TRACING
# define TRACING_BUF_SIZ 1024
size_t tracingBufLSize = TRACING_BUF_SIZ;
size_t tracingBufRSize = TRACING_BUF_SIZ;
char tracingBufL[TRACING_BUF_SIZ];
char *tracingBufLPtr = tracingBufL;
char tracingBufR[TRACING_BUF_SIZ];
char *tracingBufRPtr = tracingBufR;
#endif
// Mockingboard stereo (all voices on an AY8910 wire-or'ed together) // Mockingboard stereo (all voices on an AY8910 wire-or'ed together)
// L = Address.b7=0, R = Address.b7=1 // L = Address.b7=0, R = Address.b7=1
int nDataL = 0, nDataR = 0; int nDataL = 0, nDataR = 0;
for(unsigned int j=0; j<NUM_VOICES_PER_AY8910; j++) for(unsigned int j=0; j<NUM_VOICES_PER_AY8910; j++)
{ {
int datL, datR;
// Slot4 // Slot4
nDataL += (int) ((double)ppAYVoiceBuffer[0*NUM_VOICES_PER_AY8910+j][i] * fAttenuation); datL = (int) ((double)ppAYVoiceBuffer[0*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
nDataR += (int) ((double)ppAYVoiceBuffer[1*NUM_VOICES_PER_AY8910+j][i] * fAttenuation); datR = (int) ((double)ppAYVoiceBuffer[1*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
#if MB_TRACING
if (mb_trace_samples_fp) {
_mb_traceWriteSample(&tracingBufLPtr, &tracingBufLSize, "+4", datL);
_mb_traceWriteSample(&tracingBufRPtr, &tracingBufRSize, "+4", datR);
}
#endif
nDataL += datL;
nDataR += datR;
// Slot5 // Slot5
nDataL += (int) ((double)ppAYVoiceBuffer[2*NUM_VOICES_PER_AY8910+j][i] * fAttenuation); datL = (int) ((double)ppAYVoiceBuffer[2*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
nDataR += (int) ((double)ppAYVoiceBuffer[3*NUM_VOICES_PER_AY8910+j][i] * fAttenuation); datR = (int) ((double)ppAYVoiceBuffer[3*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
#if MB_TRACING
if (mb_trace_samples_fp) {
_mb_traceWriteSample(&tracingBufLPtr, &tracingBufLSize, "+5", datL);
_mb_traceWriteSample(&tracingBufRPtr, &tracingBufRSize, "+5", datR);
}
#endif
nDataL += datL;
nDataR += datR;
} }
#if MB_TRACING
if (mb_trace_samples_fp) {
_mb_traceWriteSample(&tracingBufLPtr, &tracingBufLSize, "==", nDataL);
_mb_traceWriteSample(&tracingBufRPtr, &tracingBufRSize, "==", nDataR);
}
#endif
// Cap the superpositioned output // Cap the superpositioned output
if(nDataL < nWaveDataMin) if(nDataL < nWaveDataMin)
nDataL = nWaveDataMin; nDataL = nWaveDataMin;
@ -1047,6 +1174,14 @@ static void MB_Update()
else if(nDataR > nWaveDataMax) else if(nDataR > nWaveDataMax)
nDataR = nWaveDataMax; nDataR = nWaveDataMax;
#if MB_TRACING
if (mb_trace_samples_fp) {
_mb_traceWriteSample(&tracingBufLPtr, &tracingBufLSize, "=>", nDataL);
_mb_traceWriteSample(&tracingBufRPtr, &tracingBufRSize, "=>", nDataR);
fprintf(mb_trace_samples_fp, "L:%s\nR:%s\n", tracingBufL, tracingBufR);
}
#endif
g_nMixBuffer[i*g_nMB_NumChannels+0] = (short)nDataL * samplesScale; // L g_nMixBuffer[i*g_nMB_NumChannels+0] = (short)nDataL * samplesScale; // L
g_nMixBuffer[i*g_nMB_NumChannels+1] = (short)nDataR * samplesScale; // R g_nMixBuffer[i*g_nMB_NumChannels+1] = (short)nDataR * samplesScale; // R
} }
@ -1080,6 +1215,9 @@ static void MB_Update()
} }
// make at least 2 attempts to submit data (could be at a ringBuffer boundary) // make at least 2 attempts to submit data (could be at a ringBuffer boundary)
# if MB_TRACING
if (!g_bFullSpeed) {
# endif
do { do {
if (MockingboardVoice->Lock(MockingboardVoice, requestedBufSize, &pDSLockedBuffer0, &dwDSLockedBufferSize0)) { if (MockingboardVoice->Lock(MockingboardVoice, requestedBufSize, &pDSLockedBuffer0, &dwDSLockedBufferSize0)) {
return; return;
@ -1097,6 +1235,9 @@ static void MB_Update()
++counter; ++counter;
} while (bufIdx < originalRequestedBufSize && counter < 2); } while (bufIdx < originalRequestedBufSize && counter < 2);
assert(bufIdx == originalRequestedBufSize); assert(bufIdx == originalRequestedBufSize);
# if MB_TRACING
}
# endif
#endif #endif
#ifdef RIFF_MB #ifdef RIFF_MB
@ -1848,6 +1989,12 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
#endif #endif
{ {
#if 1 // APPLE2IX #if 1 // APPLE2IX
# if MB_TRACING
if (mb_trace_fp) {
unsigned long uCycles = cycles_count_total - g_uLastCumulativeCycles;
fprintf(mb_trace_fp, "MB_Read|%04X|%lu\n", ea, uCycles);
}
# endif
MB_UpdateCycles(); MB_UpdateCycles();
#else #else
MB_UpdateCycles(nCyclesLeft); MB_UpdateCycles(nCyclesLeft);
@ -1922,11 +2069,23 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
#else #else
mb_assert(false); mb_assert(false);
#endif #endif
else
#if 1 // APPLE2IX #if MB_TRACING
return MemReadFloatingBus(); # if 1 // APPLE2IX
uint8_t b = MemReadFloatingBus();
# else
BYTE b = MemReadFloatingBus(nCyclesLeft);
# endif
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\tfall through ret:%02X\n", b);
}
return b;
#else #else
# if 1 // APPLE2IX
return MemReadFloatingBus();
# else
return MemReadFloatingBus(nCyclesLeft); return MemReadFloatingBus(nCyclesLeft);
# endif
#endif #endif
} }
@ -1940,6 +2099,13 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
#endif #endif
{ {
#if 1 // APPLE2IX #if 1 // APPLE2IX
# if MB_TRACING
// output cycle count delta when toggled
if (mb_trace_fp) {
unsigned long uCycles = cycles_count_total - g_uLastCumulativeCycles;
fprintf(mb_trace_fp, "MB_Write|%04X|%02X|%lu\n", ea, b, uCycles);
}
# endif
MB_UpdateCycles(); MB_UpdateCycles();
#else #else
MB_UpdateCycles(nCyclesLeft); MB_UpdateCycles(nCyclesLeft);
@ -2150,6 +2316,11 @@ void MB_EndOfVideoFrame()
{ {
if(g_SoundcardType == CT_Empty) if(g_SoundcardType == CT_Empty)
return; return;
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "%s", "MB_EndOfVideoFrame\n");
}
#endif
if(!g_bMBTimerIrqActive) if(!g_bMBTimerIrqActive)
MB_Update(); MB_Update();
@ -2172,8 +2343,8 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
g_uLastCumulativeCycles = cycles_count_total; g_uLastCumulativeCycles = cycles_count_total;
#if 1 // APPLE2IX #if 1 // APPLE2IX
if (uCycles >= 0x10000) { if (uCycles >= 0x10000) {
printf("OOPS!!! Mockingboard failed assert!\n"); LOG("OOPS!!! Mockingboard failed assert!");
return; uCycles %= 0x10000;
} }
#else #else
_ASSERT(uCycles < 0x10000); _ASSERT(uCycles < 0x10000);
@ -2194,6 +2365,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
if( bTimer1Underflow && (g_nMBTimerDevice == i) && g_bMBTimerIrqActive ) if( bTimer1Underflow && (g_nMBTimerDevice == i) && g_bMBTimerIrqActive )
{ {
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\ttimer1 (%d) underflow\n", i);
}
#endif
#if 0 // _DEBUG #if 0 // _DEBUG
g_uTimer1IrqCount++; // DEBUG g_uTimer1IrqCount++; // DEBUG
#endif #endif
@ -2206,6 +2382,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
// One-shot mode // One-shot mode
// - Phasor's playback code uses one-shot mode // - Phasor's playback code uses one-shot mode
// - Willy Byte sets to one-shot to stop the timer IRQ // - Willy Byte sets to one-shot to stop the timer IRQ
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\tstop timer %d\n", i);
}
#endif
StopTimer(pMB); StopTimer(pMB);
} }
else else
@ -2213,6 +2394,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
// Free-running mode // Free-running mode
// - Ultima4/5 change ACCESS_TIMER1 after a couple of IRQs into tune // - Ultima4/5 change ACCESS_TIMER1 after a couple of IRQs into tune
pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w;
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\tstart timer %d\n", i);
}
#endif
StartTimer(pMB); StartTimer(pMB);
} }
@ -2223,6 +2409,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
&& (pMB->sy6522.IFR & IxR_TIMER1) // IRQ && (pMB->sy6522.IFR & IxR_TIMER1) // IRQ
&& ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode && ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode
{ {
#if MB_TRACING
if (mb_trace_fp) {
fprintf(mb_trace_fp, "\ttimer1 (%d) alt underflow\n", i);
}
#endif
// Fix for Willy Byte - need to confirm that 6522 really does this! // Fix for Willy Byte - need to confirm that 6522 really does this!
// . It never accesses IER/IFR/TIMER1 regs to clear IRQ // . It never accesses IER/IFR/TIMER1 regs to clear IRQ
pMB->sy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ pMB->sy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ
@ -2742,3 +2933,38 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
} }
#endif // !APPLE2IX #endif // !APPLE2IX
//-----------------------------------------------------------------------------
#if MB_TRACING
void mb_traceBegin(const char *trace_file) {
if (trace_file) {
mb_trace_fp = fopen(trace_file, "w");
char *samp_file = NULL;
ASPRINTF(&samp_file, "%s.samp", trace_file);
assert(samp_file);
mb_trace_samples_fp = fopen(samp_file, "w");
FREE(samp_file);
}
}
void mb_traceFlush(void) {
if (mb_trace_fp) {
fflush(mb_trace_fp);
}
if (mb_trace_samples_fp) {
fflush(mb_trace_samples_fp);
}
}
void mb_traceEnd(void) {
mb_traceFlush();
if (mb_trace_fp) {
fclose(mb_trace_fp);
mb_trace_fp = NULL;
}
if (mb_trace_samples_fp) {
fclose(mb_trace_samples_fp);
mb_trace_samples_fp = NULL;
}
}
#endif

View File

@ -9,8 +9,8 @@
* *
*/ */
#ifndef _MOCKINGBOARD_H__ #ifndef _MOCKINGBOARD_H_
#define _MOCKINGBOARD_H__ #define _MOCKINGBOARD_H_
#ifdef APPLE2IX #ifdef APPLE2IX
#include "audio/peripherals.h" #include "audio/peripherals.h"
@ -123,6 +123,11 @@ bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT ve
#endif #endif
#ifdef APPLE2IX #ifdef APPLE2IX
void mb_io_initialize(unsigned int slot4, unsigned int slot5); void mb_io_initialize(unsigned int slot4, unsigned int slot5);
# if MB_TRACING
void mb_traceBegin(const char *trace_file);
void mb_traceFlush(void);
void mb_traceEnd(void);
# endif
#endif #endif
#if UNBREAK_SOON #if UNBREAK_SOON
@ -130,4 +135,5 @@ std::string Phasor_GetSnapshotCardName(void);
void Phasor_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot); void Phasor_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
bool Phasor_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version); bool Phasor_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
#endif #endif
#endif // whole file #endif // whole file

View File

@ -38,6 +38,7 @@ void test_breakpoint(void *arg);
void test_common_init(void); void test_common_init(void);
void test_common_setup(void); void test_common_setup(void);
void test_type_input(const char *input); void test_type_input(const char *input);
void test_type_input_deterministically(const char *input);
int test_setup_boot_disk(const char *fileName, int readonly); int test_setup_boot_disk(const char *fileName, int readonly);
void sha1_to_str(const uint8_t * const md, char *buf); void sha1_to_str(const uint8_t * const md, char *buf);

View File

@ -1,172 +0,0 @@
/*
* Apple // emulator for *ix
*
* This software package is subject to the GNU General Public License
* version 3 or later (your choice) as published by the Free Software
* Foundation.
*
* Copyright 2016 Aaron Culliney
*
*/
#include "testcommon.h"
#define BLANK_DSK "blank.dsk.gz"
static bool test_thread_running = false;
extern pthread_mutex_t interface_mutex; // TODO FIXME : raw access to CPU mutex because stepping debugger ...
static void testspeaker_setup(void *unused) {
test_common_setup();
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
apple_ii_64k[0][TESTOUT_ADDR] = 0x00;
joy_button0 = 0xff; // OpenApple
if (test_do_reboot) {
cpu65_interrupt(ResetSig);
}
}
static void testspeaker_teardown(void *unused) {
}
// ----------------------------------------------------------------------------
// Spaker tests ...
extern unsigned long (*testing_getCyclesCount)(void);
extern void (*testing_cyclesOverflow)(void);
static bool cycles_overflowed = false;
static unsigned long testspeaker_getCyclesCount(void) {
// advance cycles count to near overflow
return ULONG_MAX - (CLK_6502_INT);
}
static void testspeaker_cyclesOverflow(void) {
cycles_overflowed = true;
}
// ----------------------------------------------------------------------------
// TESTS ...
TEST test_timing_overflow() {
// force an almost overflow
testing_getCyclesCount = &testspeaker_getCyclesCount;
testing_cyclesOverflow = &testspeaker_cyclesOverflow;
ASSERT(!cycles_overflowed);
test_setup_boot_disk(BLANK_DSK, /*readonly:*/1);
BOOT_TO_DOS();
ASSERT(cycles_overflowed);
// appears emulator handled cycle count overflow gracefully ...
testing_getCyclesCount = NULL;
testing_cyclesOverflow = NULL;
PASS();
}
#define EXPECTED_BEEP_TRACE_FILE_SIZE 770
#define EXPECTED_BEEP_TRACE_SHA "69C728A65B5933D73F91D77694BEE7F674C9EDF7"
TEST test_boot_sound() {
const char *homedir = HOMEDIR;
char *testout = NULL;
ASPRINTF(&testout, "%s/a2_speaker_beep_test.txt", homedir);
if (testout) {
unlink(testout);
speaker_traceBegin(testout);
}
test_setup_boot_disk(BLANK_DSK, /*readonly:*/1);
BOOT_TO_DOS();
speaker_traceEnd();
disk6_eject(0);
do {
uint8_t md[SHA_DIGEST_LENGTH];
char mdstr0[(SHA_DIGEST_LENGTH*2)+1];
FILE *fp = fopen(testout, "r");
fseek(fp, 0, SEEK_END);
long expectedSize = ftell(fp);
ASSERT(expectedSize == EXPECTED_BEEP_TRACE_FILE_SIZE);
fseek(fp, 0, SEEK_SET);
unsigned char *buf = MALLOC(EXPECTED_BEEP_TRACE_FILE_SIZE);
if (fread(buf, 1, EXPECTED_BEEP_TRACE_FILE_SIZE, fp) != EXPECTED_BEEP_TRACE_FILE_SIZE) {
ASSERT(false);
}
fclose(fp); fp = NULL;
SHA1(buf, EXPECTED_BEEP_TRACE_FILE_SIZE, md);
FREE(buf);
sha1_to_str(md, mdstr0);
ASSERT(strcmp(mdstr0, EXPECTED_BEEP_TRACE_SHA) == 0);
} while(0);
unlink(testout);
FREE(testout);
PASS();
}
// ----------------------------------------------------------------------------
// Test Suite
GREATEST_SUITE(test_suite_speaker) {
pthread_mutex_lock(&interface_mutex);
test_thread_running = true;
GREATEST_SET_SETUP_CB(testspeaker_setup, NULL);
GREATEST_SET_TEARDOWN_CB(testspeaker_teardown, NULL);
//GREATEST_SET_BREAKPOINT_CB(test_breakpoint, NULL);
// TESTS --------------------------
RUN_TESTp(test_timing_overflow);
RUN_TESTp(test_boot_sound);
// --------------------------------
pthread_mutex_unlock(&interface_mutex);
}
SUITE(test_suite_speaker);
GREATEST_MAIN_DEFS();
static char **test_argv = NULL;
static int test_argc = 0;
static int _test_thread(void) {
int argc = test_argc;
char **argv = test_argv;
GREATEST_MAIN_BEGIN();
RUN_SUITE(test_suite_speaker);
GREATEST_MAIN_END();
}
static void *test_thread(void *dummyptr) {
_test_thread();
return NULL;
}
void test_speaker(int _argc, char **_argv) {
test_argc = _argc;
test_argv = _argv;
test_common_init();
pthread_t p;
pthread_create(&p, NULL, (void *)&test_thread, (void *)NULL);
while (!test_thread_running) {
struct timespec ts = { .tv_sec=0, .tv_nsec=33333333 };
nanosleep(&ts, NULL);
}
pthread_detach(p);
}

View File

@ -32,13 +32,14 @@ static void testtrace_setup(void *arg) {
if (test_do_reboot) { if (test_do_reboot) {
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);
} }
c_debugger_set_watchpoint(WATCHPOINT_ADDR);
} }
static void testtrace_teardown(void *arg) { static void testtrace_teardown(void *arg) {
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Cycles counter overflow test // Speaker/timing tests
extern unsigned long (*testing_getCyclesCount)(void); extern unsigned long (*testing_getCyclesCount)(void);
extern void (*testing_cyclesOverflow)(void); extern void (*testing_cyclesOverflow)(void);
@ -72,9 +73,6 @@ TEST test_timing_overflow() {
PASS(); PASS();
} }
// ----------------------------------------------------------------------------
// Tracing TESTS ...
#define EXPECTED_BEEP_TRACE_FILE_SIZE 770 #define EXPECTED_BEEP_TRACE_FILE_SIZE 770
#define EXPECTED_BEEP_TRACE_SHA "69C728A65B5933D73F91D77694BEE7F674C9EDF7" #define EXPECTED_BEEP_TRACE_SHA "69C728A65B5933D73F91D77694BEE7F674C9EDF7"
TEST test_boot_sound() { TEST test_boot_sound() {
@ -122,6 +120,97 @@ TEST test_boot_sound() {
PASS(); PASS();
} }
// ----------------------------------------------------------------------------
// Mockingboard tracing
#define NSCT_DSK "NSCT.dsk.gz"
#define NSCT_TRACE_SHA "35C58FEEB70E76FC31CEB55DB4C830B471B48AE3" // WARNING unstable if tests changed before this ...
#define NSCT_SAMPS_SHA "C48AFC2ABFECC98CECB8A5B63E2261181195E1B2"
#define NSCT_TRACE_TARGET_SIZ (512 * 65536) // 2^25
#define NSCT_SAMPS_TARGET_SIZ (2048 * 65536) // 2^27
TEST test_mockingboard_1() {
test_setup_boot_disk(NSCT_DSK, 0);
const char *homedir = HOMEDIR;
char *mbTraceFile = NULL;
ASPRINTF(&mbTraceFile, "%s/a2_mb_nsct", homedir);
ASSERT(mbTraceFile);
unlink(mbTraceFile);
char *mbSampsFile = NULL;
ASPRINTF(&mbSampsFile, "%s.samp", mbTraceFile);
ASSERT(mbSampsFile);
unlink(mbSampsFile);
// Poll for trace file of particular size
mb_traceBegin(mbTraceFile); // ".samp" file is automatically created ...
c_debugger_clear_watchpoints();
c_debugger_set_timeout(1);
do {
c_debugger_go();
FILE *fpTrace = fopen(mbTraceFile, "r");
fseek(fpTrace, 0, SEEK_END);
long minSizeTrace = ftell(fpTrace);
FILE *fpSamps = fopen(mbSampsFile, "r");
fseek(fpSamps, 0, SEEK_END);
long minSizeSamps = ftell(fpSamps);
if ( (minSizeTrace < NSCT_TRACE_TARGET_SIZ) || (minSizeSamps < NSCT_SAMPS_TARGET_SIZ) ) {
fclose(fpTrace);
fclose(fpSamps);
continue;
}
// trace has generated files of sufficient length
uint8_t md[SHA_DIGEST_LENGTH];
char mdstr0[(SHA_DIGEST_LENGTH*2)+1];
// verify trace file
do {
unsigned char *buf = MALLOC(NSCT_TRACE_TARGET_SIZ);
fseek(fpTrace, 0, SEEK_SET);
ASSERT(fread(buf, 1, NSCT_TRACE_TARGET_SIZ, fpTrace) == NSCT_TRACE_TARGET_SIZ);
fclose(fpTrace); fpTrace = NULL;
SHA1(buf, NSCT_TRACE_TARGET_SIZ, md);
FREE(buf);
sha1_to_str(md, mdstr0);
ASSERT(strcmp(mdstr0, NSCT_TRACE_SHA) == 0);
} while (0);
// verify trace samples file
do {
unsigned char *buf = MALLOC(NSCT_SAMPS_TARGET_SIZ);
fseek(fpSamps, 0, SEEK_SET);
ASSERT(fread(buf, 1, NSCT_SAMPS_TARGET_SIZ, fpSamps) == NSCT_SAMPS_TARGET_SIZ);
fclose(fpSamps); fpSamps = NULL;
SHA1(buf, NSCT_SAMPS_TARGET_SIZ, md);
FREE(buf);
sha1_to_str(md, mdstr0);
ASSERT(strcmp(mdstr0, NSCT_SAMPS_SHA) == 0);
} while (0);
break;
} while (1);
c_debugger_set_timeout(0);
mb_traceEnd();
unlink(mbTraceFile);
FREE(mbTraceFile);
unlink(mbSampsFile);
FREE(mbSampsFile);
disk6_eject(0);
PASS();
}
// ----------------------------------------------------------------------------
// CPU tracing
// This test is majorly abusive ... it creates an ~800MB file in $HOME // This test is majorly abusive ... it creates an ~800MB file in $HOME
// ... but if it's correct, you're fairly assured the cpu/vm is working =) // ... but if it's correct, you're fairly assured the cpu/vm is working =)
#if ABUSIVE_TESTS #if ABUSIVE_TESTS
@ -320,6 +409,9 @@ TEST test_cputrace_hello_po() {
PASS(); PASS();
} }
// ----------------------------------------------------------------------------
// VM tracing
#define EXPECTED_VM_TRACE_FILE_SIZE 2832136 #define EXPECTED_VM_TRACE_FILE_SIZE 2832136
#define EXPECTED_VM_TRACE_SHA "E39658183FF87974D8538B38B772A193C6C3276C" #define EXPECTED_VM_TRACE_SHA "E39658183FF87974D8538B38B772A193C6C3276C"
TEST test_boot_disk_vmtrace() { TEST test_boot_disk_vmtrace() {
@ -479,6 +571,8 @@ GREATEST_SUITE(test_suite_trace) {
RUN_TESTp(test_timing_overflow); RUN_TESTp(test_timing_overflow);
RUN_TESTp(test_boot_sound); RUN_TESTp(test_boot_sound);
RUN_TESTp(test_mockingboard_1);
#if ABUSIVE_TESTS #if ABUSIVE_TESTS
RUN_TESTp(test_boot_disk_cputrace); RUN_TESTp(test_boot_disk_cputrace);
#endif #endif