"HEADLESS" CPP define and envvar switches

* Allows running emulator in headless mode (default for some tests)
    * setting HEADLESS=1 envvar from commandline will force headless operation
This commit is contained in:
Aaron Culliney 2014-04-26 13:22:19 -07:00
parent 22bf206626
commit 8b0325d60d
10 changed files with 142 additions and 47 deletions

View File

@ -86,22 +86,22 @@ A2_TEST_CFLAGS = -DTESTING=1 -Isrc/greatest
TESTS = testcpu testdisplay testvm
check_PROGRAMS = testcpu testdisplay testvm
testcpu_SOURCES = src/test/testcpu.c $(A2_TEST_SOURCES) $(EXTRA_apple2ix_SOURCES)
testcpu_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS)
testcpu_SOURCES = src/test/testcpu.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC) $(VIDEO_SRC)
testcpu_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UINTERFACE_CLASSIC -DHEADLESS=1
testcpu_LDFLAGS = $(apple2ix_LDFLAGS)
testcpu_DEPENDENCIES = $(apple2ix_DEPENDENCIES)
testcpu_DEPENDENCIES = @VM_O@ @META_O@
testdisplay_SOURCES = src/test/testdisplay.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC)
testdisplay_SOURCES = src/test/testdisplay.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC) $(VIDEO_SRC)
# HACK FIXME TODO NOTE: why don't these CFLAGS here pass down to the .S and .c files in the subdirectories?
testdisplay_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UVIDEO_X11 -UINTERFACE_CLASSIC
testdisplay_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UINTERFACE_CLASSIC -DHEADLESS=0
testdisplay_LDFLAGS = $(apple2ix_LDFLAGS)
testdisplay_DEPENDENCIES = @VM_O@ @META_O@
testdisplay_DEPENDENCIES = @VM_O@ @META_O@ @VIDEO_O@
testvm_SOURCES = src/test/testvm.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC)
testvm_SOURCES = src/test/testvm.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC) $(VIDEO_SRC)
# HACK FIXME TODO NOTE: why don't these CFLAGS here pass down to the .S and .c files in the subdirectories?
testvm_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UVIDEO_X11 -UINTERFACE_CLASSIC
testvm_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UINTERFACE_CLASSIC -DHEADLESS=0
testvm_LDFLAGS = $(apple2ix_LDFLAGS)
testvm_DEPENDENCIES = @VM_O@ @META_O@
testvm_DEPENDENCIES = @VM_O@ @META_O@ @VIDEO_O@
###############################################################################
# Misc

View File

@ -129,11 +129,10 @@ AC_SEARCH_LIBS(XShmAttach, Xext, [
AC_MSG_WARN([Building emulator without support of X11 MITSHM extension...])
], [-lX11])
AC_DEFINE(VIDEO_X11, 1, [Enable common X11 video])
VIDEO_O="src/video/xvideo.o"
AC_SUBST(VIDEO_O)
AC_DEFINE(HEADLESS, 0, [Set to 1 to disable video output driver])
dnl ---------------------------------------------------------------------------
dnl Sound ...

View File

@ -577,9 +577,9 @@ void video_plotchar( int x, int y, int scheme, unsigned char c )
_plot_char80(&d,&s);
}
#ifdef VIDEO_X11
extern void X11_video_init();
extern void X11_video_shutdown();
#if !HEADLESS
extern void video_driver_init();
extern void video_driver_shutdown();
#endif
void video_init() {
@ -590,15 +590,19 @@ void video_init() {
memset(video__fb1,0,SCANWIDTH*SCANHEIGHT);
memset(video__fb2,0,SCANWIDTH*SCANHEIGHT);
#ifdef VIDEO_X11
X11_video_init();
#if !HEADLESS
if (!is_headless) {
video_driver_init();
}
#endif
}
void video_shutdown(void)
{
#ifdef VIDEO_X11
X11_video_shutdown();
#if !HEADLESS
if (!is_headless) {
video_driver_shutdown();
}
#endif
}

View File

@ -1151,7 +1151,8 @@ static int begin_cpu_stepping() {
}
#ifdef TESTING
video_sync(0);
extern void testing_video_sync();
testing_video_sync();
#else
if ((ch = c_mygetch(0)) != -1) {
break;

View File

@ -38,6 +38,7 @@ char disk_path[DISKSIZE];
int apple_mode = IIE_MODE;
int sound_volume = 2;
bool is_headless = false;
color_mode_t color_mode = COLOR;
a2_video_mode_t a2_video_mode = VIDEO_1X;
joystick_mode_t joy_mode = JOY_OFF;
@ -194,6 +195,12 @@ static char * clean_string(char *x)
/* Load the configuration. Must be called *once* at start. */
void load_settings(void)
{
/* running a headless emulator? */
char *headless = getenv("HEADLESS");
if (headless && (strncasecmp(headless, "1", 2) == 0) ) {
is_headless = true;
}
/* set system defaults before user defaults. */
strcpy(disk_path, "./disks");
strcpy(system_path, "./rom");

View File

@ -53,6 +53,7 @@ extern char disk_path[DISKSIZE];
extern int apple_mode; /* undocumented instructions or //e mode */
extern int sound_volume;
extern bool is_headless;
extern color_mode_t color_mode;
extern a2_video_mode_t a2_video_mode;

View File

@ -49,6 +49,10 @@
snprintf(msgbuf, MSG_SIZE, MSG_FLAGS0, regA, val, result, buf0, cpu65_current.a, buf1); \
ASSERTm(msgbuf, cpu65_current.f == flags);
void testing_video_sync() {
// user input and video output not simulated in this test
}
static void testcpu_setup(void *arg) {
//reinitialize();
@ -130,6 +134,30 @@ static void flags_to_string(uint8_t flags, char *buf) {
(flags & C_Flag_6502) ? 'C' : '-' );
}
// ----------------------------------------------------------------------------
// Stub functions because I've reached diminishing returns with the build system ...
//
// NOTE: You'd think the commandline CFLAGS set specifically for this test program would pass down to the sources in
// subdirectories, but it apparently isn't. GNU buildsystem bug? Also see HACK FIXME TODO NOTE in Makefile.am
//
uint8_t c_MB_Read(uint16_t addr) {
return 0x0;
}
void c_MB_Write(uint16_t addr, uint8_t byte) {
}
uint8_t c_PhasorIO(uint16_t addr) {
return 0x0;
}
void SpkrToggle() {
}
void c_interface_print(int x, int y, const int cs, const char *s) {
}
// ----------------------------------------------------------------------------
// ADC instructions

View File

@ -23,6 +23,9 @@ static unsigned int input_length = 0;
static unsigned int input_counter = 0;
static bool test_do_reboot = true;
static struct timespec t0 = { 0 };
static struct timespec ti = { 0 };
extern unsigned char joy_button0;
static void testdisplay_setup(void *arg) {
@ -45,6 +48,11 @@ static void testdisplay_teardown(void *arg) {
static void testdisplay_breakpoint(void *arg) {
fprintf(GREATEST_STDOUT, "set breakpoint on testdisplay_breakpoint to check for problems...\n");
#if !HEADLESS
if (!is_headless) {
video_sync(0);
}
#endif
}
static void sha1_to_str(const uint8_t * const md, char *buf) {
@ -58,7 +66,18 @@ static void sha1_to_str(const uint8_t * const md, char *buf) {
// ----------------------------------------------------------------------------
// test video functions and stubs
void video_sync(int ignored) {
void testing_video_sync(int ignored) {
#if !HEADLESS
if (!is_headless) {
clock_gettime(CLOCK_MONOTONIC, &ti);
struct timespec deltat = timespec_diff(t0, ti, NULL);
if (deltat.tv_sec || (deltat.tv_nsec >= NANOSECONDS/15) ) {
video_sync(0);
ti = t0;
}
}
#endif
if (input_counter >= input_length) {
return;
@ -434,7 +453,11 @@ GREATEST_SUITE(test_suite_display) {
pthread_mutex_lock(&interface_mutex);
c_debugger_set_watchpoint(WATCHPOINT_ADDR);
c_debugger_set_timeout(5);
if (is_headless) {
c_debugger_set_timeout(5);
} else {
c_debugger_set_timeout(0);
}
// TESTS --------------------------

View File

@ -12,40 +12,49 @@
#include "greatest.h"
#include "testcommon.h"
#define RESET_INPUT() \
input_counter = 0; \
input_length = 0; \
input_str[0] = '\0'
#ifdef HAVE_OPENSSL
#include <openssl/sha.h>
#else
#error "these tests require OpenSSL libraries (SHA)"
#endif
static char *input_str = NULL; // ASCII
static char input_str[TESTBUF_SZ]; // ASCII
static unsigned int input_length = 0;
static unsigned int input_counter = 0;
static bool test_do_reboot = true;
static struct timespec t0 = { 0 };
static struct timespec ti = { 0 };
extern unsigned char joy_button0;
static void testvm_setup(void *arg) {
apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00;
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
apple_ii_64k[0][TESTOUT_ADDR] = 0x00;
input_counter = 0;
input_length = 0;
RESET_INPUT();
joy_button0 = 0xff; // OpenApple
if (test_do_reboot) {
cpu65_interrupt(ResetSig);
}
clock_gettime(CLOCK_MONOTONIC, &t0);
}
static void testvm_teardown(void *arg) {
if (input_str) {
free(input_str);
}
input_str = NULL;
}
static void testvm_breakpoint(void *arg) {
fprintf(GREATEST_STDOUT, "set breakpoint on testvm_breakpoint to check for problems...\n");
#if !HEADLESS
if (!is_headless) {
video_sync(0);
}
#endif
}
static void sha1_to_str(const uint8_t * const md, char *buf) {
@ -59,7 +68,22 @@ static void sha1_to_str(const uint8_t * const md, char *buf) {
// ----------------------------------------------------------------------------
// test video functions and stubs
void video_sync(int ignored) {
void testing_video_sync() {
#if !HEADLESS
if (!is_headless) {
clock_gettime(CLOCK_MONOTONIC, &ti);
struct timespec deltat = timespec_diff(t0, ti, NULL);
if (deltat.tv_sec || (deltat.tv_nsec >= NANOSECONDS/15) ) {
video_sync(0);
ti = t0;
}
}
#endif
if (!input_length) {
input_length = strlen(input_str);
}
if (input_counter >= input_length) {
return;
@ -67,7 +91,6 @@ void video_sync(int ignored) {
uint8_t ch = (uint8_t)input_str[input_counter];
if (ch == '\n') {
fprintf(stderr, "converting '\\n' to '\\r' in test input string...");
ch = '\r';
}
@ -124,7 +147,7 @@ TEST test_read_keyboard() {
ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED);
ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00);
input_str = strdup("RUN TESTGETKEY\rZ");
strcpy(input_str, "RUN TESTGETKEY\rZ");
input_length = strlen(input_str);
c_debugger_go();
@ -140,8 +163,7 @@ TEST test_clear_keyboard() {
ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED);
ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00);
input_str = strdup("RUN TESTCLEARKEY\rZA");
input_length = strlen(input_str);
strcpy(input_str, "RUN TESTCLEARKEY\rZA");
c_debugger_go();
ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED);
@ -151,15 +173,14 @@ TEST test_clear_keyboard() {
}
TEST test_read_random() {
SKIPm("random numbers current b0rken...");
SKIPm("random numbers currently b0rken...");
BOOT_TO_DOS();
ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED);
ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00);
input_str = strdup("RUN TESTRND\r");
input_length = strlen(input_str);
strcpy(input_str, "RUN TESTRND\r");
c_debugger_go();
ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED);
@ -201,7 +222,11 @@ GREATEST_SUITE(test_suite_vm) {
pthread_mutex_lock(&interface_mutex);
c_debugger_set_watchpoint(WATCHPOINT_ADDR);
c_debugger_set_timeout(5);
if (is_headless) {
c_debugger_set_timeout(5);
} else {
c_debugger_set_timeout(0);
}
// TESTS --------------------------

View File

@ -312,6 +312,7 @@ static void c_initialize_colors() {
//XStoreColors(display, cmap, colors, 256);
}
#if !defined(TESTING)
// Map X keysyms into Apple//ix internal-representation scancodes.
static int keysym_to_scancode(void) {
int rc = XkbKeycodeToKeysym(display, xevent.xkey.keycode, 0, 0);
@ -452,6 +453,7 @@ static int keysym_to_scancode(void) {
assert(rc < 0x80);
return rc;
}
#endif
static void post_image() {
// copy Apple //e video memory into XImage uint32_t buffer
@ -558,11 +560,18 @@ extern void c_handle_input(int scancode, int pressed);
/* FIXME: blocking not implemented... */
void video_sync(int block) {
if (is_headless) {
return;
}
static int flash_count = 0;
// post the image and loop waiting for it to finish and
// also process other input events
post_image();
#ifdef TESTING
// no input processing if test-driven ...
#else
bool keyevent = true;
do {
#ifdef HAVE_X11_SHM
@ -595,6 +604,7 @@ void video_sync(int block) {
c_handle_input(scancode, pressed);
} while (keyevent);
#endif
switch (++flash_count)
{
@ -786,7 +796,7 @@ void video_set_mode(a2_video_mode_t mode) {
_size_hints_set_fixed();
}
void X11_video_init() {
void video_driver_init() {
XSetWindowAttributes attribs;
unsigned long attribmask;
int x, y; /* window position */
@ -797,18 +807,15 @@ void X11_video_init() {
char *window_name = "Apple //ix";
char *icon_name = window_name;
//GC gc;
char *progname; /* name this program was invoked by */
char *displayname = NULL;
if (argv == NULL) {
LOG("No command line arguments, won't initialize xvideo ...");
return;
LOG("No command line arguments ...");
argc = 0;
} else {
parseArgs();
}
progname = argv[0];
parseArgs();
if (!(size_hints = XAllocSizeHints()))
{
fprintf(stderr, "cannot allocate memory for SizeHints\n");
@ -977,7 +984,7 @@ void X11_video_init() {
wm_hints->input = True;
wm_hints->flags = StateHint | IconPixmapHint /* | InputHint*/;
class_hints->res_name = progname;
class_hints->res_name = "apple2ix";
class_hints->res_class = "Apple2";
_size_hints_set_fixed();
@ -1024,7 +1031,7 @@ void X11_video_init() {
#endif
}
void X11_video_shutdown(void)
void video_driver_shutdown(void)
{
_destroy_image();
exit(0);