mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-01-12 21:30:07 +00:00
Beginnings of Mockingboard tracing for automated testing
This commit is contained in:
parent
5883545390
commit
8921f79a14
@ -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_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_LDFLAGS = $(apple2ix_LDFLAGS)
|
||||
testtrace_LDADD = @testtrace_ASM_O@ @testtrace_VIDEO_O@ @testtrace_AUDIO_O@ @testtrace_META_O@ @X_LIBS@
|
||||
|
@ -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_TONE2_PERIOD, ay_tone_period[2]);
|
||||
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_NOISE_TOGGLE, noise_toggle);
|
||||
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;
|
||||
#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)
|
||||
{
|
||||
|
@ -32,6 +32,9 @@ void AY8910UpdateSetCycles();
|
||||
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
|
||||
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
|
||||
#endif
|
||||
#if MB_TRACING
|
||||
void _mb_trace_AY8910(int chip, FILE *mb_trace_fp);
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
// FUSE stuff
|
||||
|
@ -19,7 +19,7 @@ Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
|
||||
|
||||
AppleWin is free software; you can redistribute it and/or modify
|
||||
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.
|
||||
|
||||
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 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 *SSI263Voice[64] = { 0 };
|
||||
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
|
||||
AY8910_reset(nDevice+2*nAYDevice);
|
||||
#if MB_TRACING
|
||||
_mb_trace_AY8910(nDevice+2*nAYDevice, mb_trace_fp);
|
||||
#endif
|
||||
}
|
||||
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
|
||||
_AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA);
|
||||
#if MB_TRACING
|
||||
_mb_trace_AY8910(nDevice+2*nAYDevice, mb_trace_fp);
|
||||
#endif
|
||||
break;
|
||||
|
||||
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;
|
||||
// else Pro-Mockingboard (clone from HK)
|
||||
break;
|
||||
#if 1 // APPLE2IX
|
||||
default:
|
||||
mb_assert(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -419,6 +436,11 @@ static void UpdateIFR(SY6522_AY8910* pMB)
|
||||
if (bIRQ)
|
||||
{
|
||||
#if 1 // APPLE2IX
|
||||
#if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
fprintf(mb_trace_fp, "\t%s\n", "IRQ_6522");
|
||||
}
|
||||
#endif
|
||||
cpu65_interrupt(IS_6522);
|
||||
#else
|
||||
CpuIrqAssert(IS_6522);
|
||||
@ -427,6 +449,11 @@ static void UpdateIFR(SY6522_AY8910* pMB)
|
||||
else
|
||||
{
|
||||
#if 1 // APPLE2IX
|
||||
#if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
fprintf(mb_trace_fp, "\t%s\n", "!IRQ_6522");
|
||||
}
|
||||
#endif
|
||||
cpu65_uninterrupt(IS_6522);
|
||||
#else
|
||||
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)
|
||||
{
|
||||
#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;
|
||||
|
||||
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
|
||||
break;
|
||||
}
|
||||
|
||||
#if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
_mb_traceSY6522_AY8910(nDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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_Active = true;
|
||||
|
||||
@ -630,6 +704,13 @@ static uint8_t SY6522_Read(uint8_t nDevice, uint8_t nReg)
|
||||
break;
|
||||
}
|
||||
|
||||
#if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
_mb_traceSY6522_AY8910(nDevice);
|
||||
fprintf(mb_trace_fp, "\tret:%02X\n", nValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
return nValue;
|
||||
}
|
||||
|
||||
@ -865,6 +946,11 @@ static void MB_Update()
|
||||
{
|
||||
return;
|
||||
}
|
||||
# if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
fprintf(mb_trace_fp, "%s", "\tMB_Update()\n");
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
char szDbg[200];
|
||||
|
||||
@ -874,6 +960,7 @@ static void MB_Update()
|
||||
|
||||
if (g_bFullSpeed)
|
||||
{
|
||||
#if !MB_TRACING
|
||||
// Keep AY reg writes relative to the current 'frame'
|
||||
// - Required for Ultima3:
|
||||
// . Tune ends
|
||||
@ -886,6 +973,7 @@ static void MB_Update()
|
||||
// If any AY regs have changed then push them out to the AY chip
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@ -1016,26 +1104,65 @@ static void MB_Update()
|
||||
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;
|
||||
|
||||
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)
|
||||
// L = Address.b7=0, R = Address.b7=1
|
||||
int nDataL = 0, nDataR = 0;
|
||||
|
||||
for(unsigned int j=0; j<NUM_VOICES_PER_AY8910; j++)
|
||||
{
|
||||
int datL, datR;
|
||||
|
||||
// Slot4
|
||||
nDataL += (int) ((double)ppAYVoiceBuffer[0*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
|
||||
nDataR += (int) ((double)ppAYVoiceBuffer[1*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
|
||||
datL = (int) ((double)ppAYVoiceBuffer[0*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
|
||||
nDataL += (int) ((double)ppAYVoiceBuffer[2*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
|
||||
nDataR += (int) ((double)ppAYVoiceBuffer[3*NUM_VOICES_PER_AY8910+j][i] * fAttenuation);
|
||||
datL = (int) ((double)ppAYVoiceBuffer[2*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
|
||||
if(nDataL < nWaveDataMin)
|
||||
nDataL = nWaveDataMin;
|
||||
@ -1047,6 +1174,14 @@ static void MB_Update()
|
||||
else if(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+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)
|
||||
# if MB_TRACING
|
||||
if (!g_bFullSpeed) {
|
||||
# endif
|
||||
do {
|
||||
if (MockingboardVoice->Lock(MockingboardVoice, requestedBufSize, &pDSLockedBuffer0, &dwDSLockedBufferSize0)) {
|
||||
return;
|
||||
@ -1097,6 +1235,9 @@ static void MB_Update()
|
||||
++counter;
|
||||
} while (bufIdx < originalRequestedBufSize && counter < 2);
|
||||
assert(bufIdx == originalRequestedBufSize);
|
||||
# if MB_TRACING
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef RIFF_MB
|
||||
@ -1848,6 +1989,12 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
|
||||
#endif
|
||||
{
|
||||
#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();
|
||||
#else
|
||||
MB_UpdateCycles(nCyclesLeft);
|
||||
@ -1922,11 +2069,23 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO
|
||||
#else
|
||||
mb_assert(false);
|
||||
#endif
|
||||
else
|
||||
#if 1 // APPLE2IX
|
||||
return MemReadFloatingBus();
|
||||
|
||||
#if MB_TRACING
|
||||
# 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
|
||||
# if 1 // APPLE2IX
|
||||
return MemReadFloatingBus();
|
||||
# else
|
||||
return MemReadFloatingBus(nCyclesLeft);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1940,6 +2099,13 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
|
||||
#endif
|
||||
{
|
||||
#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();
|
||||
#else
|
||||
MB_UpdateCycles(nCyclesLeft);
|
||||
@ -2150,6 +2316,11 @@ void MB_EndOfVideoFrame()
|
||||
{
|
||||
if(g_SoundcardType == CT_Empty)
|
||||
return;
|
||||
#if MB_TRACING
|
||||
if (mb_trace_fp) {
|
||||
fprintf(mb_trace_fp, "%s", "MB_EndOfVideoFrame\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!g_bMBTimerIrqActive)
|
||||
MB_Update();
|
||||
@ -2172,8 +2343,8 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
g_uLastCumulativeCycles = cycles_count_total;
|
||||
#if 1 // APPLE2IX
|
||||
if (uCycles >= 0x10000) {
|
||||
printf("OOPS!!! Mockingboard failed assert!\n");
|
||||
return;
|
||||
LOG("OOPS!!! Mockingboard failed assert!");
|
||||
uCycles %= 0x10000;
|
||||
}
|
||||
#else
|
||||
_ASSERT(uCycles < 0x10000);
|
||||
@ -2194,6 +2365,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
|
||||
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
|
||||
g_uTimer1IrqCount++; // DEBUG
|
||||
#endif
|
||||
@ -2206,6 +2382,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
// One-shot mode
|
||||
// - Phasor's playback code uses one-shot mode
|
||||
// - 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);
|
||||
}
|
||||
else
|
||||
@ -2213,6 +2394,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
// Free-running mode
|
||||
// - Ultima4/5 change ACCESS_TIMER1 after a couple of IRQs into tune
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2223,6 +2409,11 @@ void MB_UpdateCycles(ULONG uExecutedCycles)
|
||||
&& (pMB->sy6522.IFR & IxR_TIMER1) // IRQ
|
||||
&& ((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!
|
||||
// . It never accesses IER/IFR/TIMER1 regs to clear 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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#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
|
||||
|
@ -9,8 +9,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MOCKINGBOARD_H__
|
||||
#define _MOCKINGBOARD_H__
|
||||
#ifndef _MOCKINGBOARD_H_
|
||||
#define _MOCKINGBOARD_H_
|
||||
|
||||
#ifdef APPLE2IX
|
||||
#include "audio/peripherals.h"
|
||||
@ -123,6 +123,11 @@ bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT ve
|
||||
#endif
|
||||
#ifdef APPLE2IX
|
||||
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
|
||||
|
||||
#if UNBREAK_SOON
|
||||
@ -130,4 +135,5 @@ std::string Phasor_GetSnapshotCardName(void);
|
||||
void Phasor_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
|
||||
bool Phasor_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||
#endif
|
||||
|
||||
#endif // whole file
|
||||
|
@ -38,6 +38,7 @@ void test_breakpoint(void *arg);
|
||||
void test_common_init(void);
|
||||
void test_common_setup(void);
|
||||
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);
|
||||
void sha1_to_str(const uint8_t * const md, char *buf);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -32,13 +32,14 @@ static void testtrace_setup(void *arg) {
|
||||
if (test_do_reboot) {
|
||||
cpu65_interrupt(ResetSig);
|
||||
}
|
||||
c_debugger_set_watchpoint(WATCHPOINT_ADDR);
|
||||
}
|
||||
|
||||
static void testtrace_teardown(void *arg) {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Cycles counter overflow test
|
||||
// Speaker/timing tests
|
||||
|
||||
extern unsigned long (*testing_getCyclesCount)(void);
|
||||
extern void (*testing_cyclesOverflow)(void);
|
||||
@ -72,9 +73,6 @@ TEST test_timing_overflow() {
|
||||
PASS();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tracing TESTS ...
|
||||
|
||||
#define EXPECTED_BEEP_TRACE_FILE_SIZE 770
|
||||
#define EXPECTED_BEEP_TRACE_SHA "69C728A65B5933D73F91D77694BEE7F674C9EDF7"
|
||||
TEST test_boot_sound() {
|
||||
@ -122,6 +120,97 @@ TEST test_boot_sound() {
|
||||
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
|
||||
// ... but if it's correct, you're fairly assured the cpu/vm is working =)
|
||||
#if ABUSIVE_TESTS
|
||||
@ -320,6 +409,9 @@ TEST test_cputrace_hello_po() {
|
||||
PASS();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// VM tracing
|
||||
|
||||
#define EXPECTED_VM_TRACE_FILE_SIZE 2832136
|
||||
#define EXPECTED_VM_TRACE_SHA "E39658183FF87974D8538B38B772A193C6C3276C"
|
||||
TEST test_boot_disk_vmtrace() {
|
||||
@ -479,6 +571,8 @@ GREATEST_SUITE(test_suite_trace) {
|
||||
RUN_TESTp(test_timing_overflow);
|
||||
RUN_TESTp(test_boot_sound);
|
||||
|
||||
RUN_TESTp(test_mockingboard_1);
|
||||
|
||||
#if ABUSIVE_TESTS
|
||||
RUN_TESTp(test_boot_disk_cputrace);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user