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_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@

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_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)
{

View File

@ -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

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
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

View File

@ -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

View 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);

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) {
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