1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-11 23:52:48 +00:00

SCP: Updated to current version.

This commit is contained in:
Richard Cornwell 2018-07-18 13:53:05 -04:00
parent efc9c2abff
commit d19a528554
7 changed files with 411 additions and 51 deletions

View File

@ -272,6 +272,10 @@ ws_init(const char *crtname, /* crt type name */
xpixels = xp; /* save screen size */
ypixels = yp;
if (getenv ("DISPLAY") == NULL) {
return 0;
}
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
argc = 0;

312
scp.c
View File

@ -223,6 +223,7 @@
#include "sim_disk.h"
#include "sim_tape.h"
#include "sim_ether.h"
#include "sim_card.h"
#include "sim_serial.h"
#include "sim_video.h"
#include "sim_sock.h"
@ -326,6 +327,7 @@
#if defined (SIM_ASYNCH_IO)
pthread_mutex_t sim_asynch_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sim_asynch_wake = PTHREAD_COND_INITIALIZER;
pthread_mutex_t sim_idle_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t sim_timer_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sim_timer_wake = PTHREAD_COND_INITIALIZER;
@ -520,6 +522,7 @@ void int_handler (int signal);
t_stat set_prompt (int32 flag, CONST char *cptr);
t_stat sim_set_asynch (int32 flag, CONST char *cptr);
static const char *get_dbg_verb (uint32 dbits, DEVICE* dptr, UNIT *uptr);
static t_stat sim_library_unit_tests (void);
/* Global data */
@ -1535,7 +1538,27 @@ static const char simh_help[] =
"+then looked up as an environment variable. If found it the value is\n"
"+supstituted for the original string before expanding everything else. If\n"
"+it is not found, then the original beginning token on the line is left\n"
"+untouched.\n"
"+untouched.\n\n"
"+Environment variable string substitution:\n\n"
"++%%XYZ:str1=str2%%\n\n"
"+would expand the XYZ environment variable, substituting each occurrence\n"
"+of \"str1\" in the expanded result with \"str2\". \"str2\" can be the empty\n"
"+string to effectively delete all occurrences of \"str1\" from the expanded\n"
"+output. \"str1\" can begin with an asterisk, in which case it will match\n"
"+everything from the beginning of the expanded output to the first\n"
"+occurrence of the remaining portion of str1.\n\n"
"+May also specify substrings for an expansion.\n\n"
"++%%XYZ:~10,5%%\n\n"
"+would expand the XYZ environment variable, and then use only the 5\n"
"+characters that begin at the 11th (offset 10) character of the expanded\n"
"+result. If the length is not specified, then it defaults to the\n"
"+remainder of the variable value. If either number (offset or length) is\n"
"+negative, then the number used is the length of the environment variable\n"
"+value added to the offset or length specified.\n\n"
"++%%XYZ:~-10%%\n\n"
"+would extract the last 10 characters of the XYZ variable.\n\n"
"++%%XYZ:~0,-2%%\n\n"
"+would extract all but the last 2 characters of the XYZ variable.\n"
#define HLP_GOTO "*Commands Executing_Command_Files GOTO"
"3GOTO\n"
" Commands in a command file execute in sequence until either an error\n"
@ -1761,7 +1784,10 @@ static const char simh_help[] =
" followed by a newline:\n\n"
/***************** 80 character line width template *************************/
"++ECHOF {-n} \"<string>\"|<string> output string to console\n\n"
" If there is no argument, ECHOF prints a blank line on the console.\n"
" The ECHOF command can also print output on a specified multiplexer line\n"
" (and log) followed by a newline:\n\n"
"++ECHOF {-n} dev:line \"<string>\"|<string> output string to specified line\n\n"
" If there is no argument, ECHOF prints a blank line.\n"
" The string argument may be delimited by quote characters. Quotes may\n"
" be either single or double but the opening and closing quote characters\n"
" must match. If the string is enclosed in quotes, the string may\n"
@ -2413,17 +2439,23 @@ sim_is_running = FALSE;
sim_log = NULL;
if (sim_emax <= 0)
sim_emax = 1;
sim_timer_init ();
if (sim_timer_init ()) {
fprintf (stderr, "Fatal timer initialization error\n");
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return 0;
}
sim_register_internal_device (&sim_expect_dev);
sim_register_internal_device (&sim_step_dev);
if ((stat = sim_ttinit ()) != SCPE_OK) {
fprintf (stderr, "Fatal terminal initialization error\n%s\n",
sim_error_text (stat));
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return 0;
}
if ((sim_eval = (t_value *) calloc (sim_emax, sizeof (t_value))) == NULL) {
fprintf (stderr, "Unable to allocate examine buffer\n");
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return 0;
};
if (sim_dflt_dev == NULL) /* if no default */
@ -2431,11 +2463,13 @@ if (sim_dflt_dev == NULL) /* if no default */
if ((stat = reset_all_p (0)) != SCPE_OK) {
fprintf (stderr, "Fatal simulator initialization error\n%s\n",
sim_error_text (stat));
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return 0;
}
if ((stat = sim_brk_init ()) != SCPE_OK) {
fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n",
sim_error_text (stat));
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return 0;
}
signal (SIGINT, int_handler);
@ -2501,6 +2535,9 @@ else if (*argv[0]) { /* sim name arg? */
}
}
if (sim_switches & SWMASK ('T')) /* Command Line -T switch */
sim_library_unit_tests (); /* run library unit tests */
stat = process_stdin_commands (SCPE_BARE_STATUS(stat), argv);
detach_all (0, TRUE); /* close files */
@ -2785,6 +2822,11 @@ if (DEV_TYPE(dptr) == DEV_ETHER) {
eth_attach_help (st, dptr, NULL, 0, NULL);
return;
}
if (DEV_TYPE(dptr) == DEV_CARD) {
fprintf (st, "\n%s device attach commands:\n\n", dptr->name);
sim_card_attach_help (st, dptr, NULL, 0, NULL);
return;
}
if (!silent) {
fprintf (st, "No ATTACH help is available for the %s device\n", dptr->name);
if (dptr->help)
@ -3238,12 +3280,21 @@ return SCPE_OK;
t_stat echof_cmd (int32 flag, CONST char *cptr)
{
char gbuf[CBUFSIZE];
uint8 dbuf[CBUFSIZE];
CONST char *tptr;
TMLN *lp = NULL;
uint8 dbuf[4*CBUFSIZE];
uint32 dsize = 0;
t_stat r;
GET_SWITCHES (cptr);
if (!*cptr)
return SCPE_2FARG;
tptr = get_glyph (cptr, gbuf, ',');
if (sim_isalpha(gbuf[0]) && (strchr (gbuf, ':'))) {
r = tmxr_locate_line (gbuf, &lp);
if (r != SCPE_OK)
return r;
cptr = tptr;
}
GET_SWITCHES (cptr);
if ((*cptr == '"') || (*cptr == '\'')) {
cptr = get_glyph_quoted (cptr, gbuf, 0);
if (*cptr != '\0')
@ -3253,7 +3304,12 @@ if ((*cptr == '"') || (*cptr == '\'')) {
dbuf[dsize] = 0;
cptr = (char *)dbuf;
}
sim_printf ("%s%s", cptr, (sim_switches & SWMASK('N')) ? "" : "\n");
if (lp) {
tmxr_linemsgf (lp, "%s%s", cptr, (sim_switches & SWMASK('N')) ? "" : "\r\n");
tmxr_send_buffered_data (lp);
}
else
sim_printf ("%s%s", cptr, (sim_switches & SWMASK('N')) ? "" : "\n");
return SCPE_OK;
}
@ -3593,11 +3649,127 @@ if (ap) { /* environment variable found? */
return ap;
}
/*
Environment variable substitution:
%XYZ:str1=str2%
would expand the XYZ environment variable, substituting each occurrence
of "str1" in the expanded result with "str2". "str2" can be the empty
string to effectively delete all occurrences of "str1" from the expanded
output. "str1" can begin with an asterisk, in which case it will match
everything from the beginning of the expanded output to the first
occurrence of the remaining portion of str1.
May also specify substrings for an expansion.
%XYZ:~10,5%
would expand the XYZ environment variable, and then use only the 5
characters that begin at the 11th (offset 10) character of the expanded
result. If the length is not specified, then it defaults to the
remainder of the variable value. If either number (offset or length) is
negative, then the number used is the length of the environment variable
value added to the offset or length specified.
%XYZ:~-10%
would extract the last 10 characters of the XYZ variable.
%XYZ:~0,-2%
would extract all but the last 2 characters of the XYZ variable.
*/
static void _sim_subststr_substr (const char *ops, char *rbuf, size_t rbuf_size)
{
int rbuf_len = (int)strlen (rbuf);
char *tstr = (char *)malloc (1 + rbuf_len);
strcpy (tstr, rbuf);
if (*ops == '~') { /* Substring? */
int offset, length;
int o, l;
switch (sscanf (ops + 1, "%d,%d", &o, &l)) {
case 2:
if (l < 0)
length = rbuf_len - MIN(-l, rbuf_len);
else
length = l;
/* fall through */
case 1:
if (o < 0)
offset = rbuf_len - MIN(-o, rbuf_len);
else
offset = MIN(o, rbuf_len);
break;
case 0:
offset = 0;
length = rbuf_len;
break;
}
if (offset + length > rbuf_len)
length = rbuf_len - offset;
memcpy (rbuf, tstr + offset, length);
rbuf[length] = '\0';
}
else {
const char *eq;
if ((eq = strchr (ops, '='))) { /* Substitute? */
const char *last = tstr;
const char *curr = tstr;
char *match = (char *)malloc (1 + (eq - ops));
size_t move_size;
t_bool asterisk_match;
strlcpy (match, ops, 1 + (eq - ops));
asterisk_match = (*ops == '*');
if (asterisk_match)
memmove (match, match + 1, 1 + strlen (match + 1));
while ((curr = strstr (last, match))) {
if (!asterisk_match) {
move_size = MIN((size_t)(curr - last), rbuf_size);
memcpy (rbuf, last, move_size);
rbuf_size -= move_size;
rbuf += move_size;
}
else
asterisk_match = FALSE;
move_size = MIN(strlen (eq + 1), rbuf_size);
memcpy (rbuf, eq + 1, move_size);
rbuf_size -= move_size;
rbuf += move_size;
curr += strlen (match);
last = curr;
}
move_size = MIN(strlen (last), rbuf_size);
memcpy (rbuf, last, move_size);
rbuf_size -= move_size;
rbuf += move_size;
if (rbuf_size)
*rbuf = '\0';
}
}
free (tstr);
}
static const char *
_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size)
{
const char *ap;
const char *fixup_needed = strchr (gbuf, ':');
char *tgbuf = NULL;
size_t tgbuf_size = MAX(rbuf_size, 1 + (size_t)(fixup_needed - gbuf));
if (fixup_needed) {
tgbuf = (char *)calloc (tgbuf_size, 1);
memcpy (tgbuf, gbuf, (fixup_needed - gbuf));
gbuf = tgbuf;
}
ap = _sim_gen_env_uplowcase (gbuf, rbuf, rbuf_size);/* Look for environment variable */
if (!ap) { /* no environment variable found? */
time_t now = (time_t)cmd_time.tv_sec;
@ -3762,6 +3934,12 @@ if (!ap) { /* no environment variable found? */
ap = rbuf;
}
}
if (ap && fixup_needed) { /* substring/substituted needed? */
strlcpy (tgbuf, ap, tgbuf_size);
_sim_subststr_substr (fixup_needed + 1, tgbuf, tgbuf_size);
strlcpy (rbuf, tgbuf, rbuf_size);
}
free (tgbuf);
return ap;
}
@ -12277,7 +12455,7 @@ if (sim_deb && (((sim_deb != stdout) && (sim_deb != sim_log)) || inhibit_message
if (buf != stackbuf)
free (buf);
return stat | SCPE_NOMESSAGE;
return stat | ((stat != SCPE_OK) ? SCPE_NOMESSAGE : 0);
}
/* Inline debugging - will print debug message if debug file is
@ -14076,3 +14254,121 @@ if (*stat != SCPE_OK) {
delete_Stack (postfix);
return cptr;
}
/*
Compiled in unit tests for the various device oriented library
modules: sim_card, sim_disk, sim_tape, sim_ether, sim_tmxr, etc.
*/
static t_stat create_card_file (const char *filename, int cards)
{
FILE *f;
int i;
f = fopen (filename, "w");
if (f == NULL)
return SCPE_OPENERR;
for (i=0; i<cards; i++)
fprintf (f, "%05d ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n", i);
fclose (f);
return SCPE_OK;
}
#define TST(_stat) do { if (SCPE_OK != (stat = (_stat))) {sim_printf ("Error: %d - '%s' processing: " #_stat "\n", stat, sim_error_text(stat)); goto done; }} while (0)
static t_stat test_card (DEVICE *dptr)
{
t_stat stat = SCPE_OK;
#if defined(USE_SIM_CARD) && defined(SIM_CARD_API)
char cmd[CBUFSIZE];
char saved_filename[4*CBUFSIZE];
uint16 card_image[80];
if ((dptr->units->flags & UNIT_RO) == 0) /* Punch device? */
return SCPE_OK;
sim_printf ("Testing %s device sim_card APIs\n", dptr->name);
remove("file1.deck");
remove("file2.deck");
remove("file3.deck");
remove("file4.deck");
TST(create_card_file ("File10.deck", 10));
TST(create_card_file ("File20.deck", 20));
TST(create_card_file ("File30.deck", 30));
TST(create_card_file ("File40.deck", 40));
sprintf (cmd, "%s File10.deck", dptr->name);
TST(attach_cmd (0, cmd));
sprintf (cmd, "%s File20.deck", dptr->name);
TST(attach_cmd (0, cmd));
sprintf (cmd, "%s -S File30.deck", dptr->name);
TST(attach_cmd (0, cmd));
sprintf (cmd, "%s -S -E File40.deck", dptr->name);
TST(attach_cmd (0, cmd));
sprintf (saved_filename, "%s %s", dptr->name, dptr->units->filename);
show_cmd (0, dptr->name);
sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units));
sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units));
while (!sim_card_eof (dptr->units))
TST(sim_read_card (dptr->units, card_image));
sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units));
sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units));
sim_printf ("Detaching %s\n", dptr->name);
TST(detach_cmd (0, dptr->name));
show_cmd (0, dptr->name);
sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units));
sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units));
sim_printf ("Attaching Saved Filenames: %s\n", saved_filename + strlen(dptr->name));
TST(attach_cmd (0, saved_filename));
show_cmd (0, dptr->name);
sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units));
sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units));
TST(detach_cmd (0, dptr->name));
done:
remove ("file10.deck");
remove ("file20.deck");
remove ("file30.deck");
remove ("file40.deck");
#endif /* defined(USE_SIM_CARD) && defined(SIM_CARD_API) */
return stat;
}
static t_stat test_tape (DEVICE *dptr)
{
return SCPE_OK;
}
static t_stat test_disk (DEVICE *dptr)
{
return SCPE_OK;
}
static t_stat test_ether (DEVICE *dptr)
{
return SCPE_OK;
}
static t_stat sim_library_unit_tests (void)
{
int i;
DEVICE *dptr;
t_stat stat = SCPE_OK;
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
if (DEV_TYPE(dptr) == DEV_CARD)
stat = test_card (dptr);
else
if (DEV_TYPE(dptr) == DEV_TAPE)
stat = test_tape (dptr);
else
if (DEV_TYPE(dptr) == DEV_DISK)
stat = test_disk (dptr);
else
if (DEV_TYPE(dptr) == DEV_ETHER)
stat = test_ether (dptr);
}
return stat;
}

View File

@ -517,11 +517,11 @@ struct DEVICE {
#define DEV_V_DYNM 2 /* mem size dynamic */
#define DEV_V_DEBUG 3 /* debug capability */
#define DEV_V_TYPE 4 /* Attach type */
#define DEV_S_TYPE 3 /* Width of Type Field */
#define DEV_V_SECTORS 7 /* Unit Capacity is in 512byte sectors */
#define DEV_V_DONTAUTO 8 /* Do not auto detach already attached units */
#define DEV_V_FLATHELP 9 /* Use traditional (unstructured) help */
#define DEV_V_NOSAVE 10 /* Don't save device state */
#define DEV_S_TYPE 4 /* Width of Type Field */
#define DEV_V_SECTORS 8 /* Unit Capacity is in 512byte sectors */
#define DEV_V_DONTAUTO 9 /* Do not auto detach already attached units */
#define DEV_V_FLATHELP 10 /* Use traditional (unstructured) help */
#define DEV_V_NOSAVE 11 /* Don't save device state */
#define DEV_V_UF_31 12 /* user flags, V3.1 */
#define DEV_V_UF 16 /* user flags */
#define DEV_V_RSV 31 /* reserved */
@ -541,8 +541,9 @@ struct DEVICE {
#define DEV_DISK (1 << DEV_V_TYPE) /* sim_disk Attach */
#define DEV_TAPE (2 << DEV_V_TYPE) /* sim_tape Attach */
#define DEV_MUX (3 << DEV_V_TYPE) /* sim_tmxr Attach */
#define DEV_ETHER (4 << DEV_V_TYPE) /* Ethernet Device */
#define DEV_DISPLAY (5 << DEV_V_TYPE) /* Display Device */
#define DEV_CARD (4 << DEV_V_TYPE) /* sim_card Attach */
#define DEV_ETHER (5 << DEV_V_TYPE) /* Ethernet Device */
#define DEV_DISPLAY (6 << DEV_V_TYPE) /* Display Device */
#define DEV_TYPE(dptr) ((dptr)->flags & DEV_TYPEMASK)
#define DEV_UFMASK_31 (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF_31) - 1))

View File

@ -243,16 +243,16 @@ t_bool timedout = FALSE;
clock_gettime(CLOCK_REALTIME, &done_time);
done_time.tv_sec += (msec/1000);
done_time.tv_nsec += 1000000*(msec%1000);
if (done_time.tv_nsec > 1000000000) {
if (done_time.tv_nsec >= 1000000000) {
done_time.tv_sec += done_time.tv_nsec/1000000000;
done_time.tv_nsec = done_time.tv_nsec%1000000000;
}
pthread_mutex_lock (&sim_asynch_lock);
sim_idle_wait = TRUE;
if (!pthread_cond_timedwait (&sim_asynch_wake, &sim_asynch_lock, &done_time))
sim_asynch_check = 0; /* force check of asynch queue now */
if (pthread_cond_timedwait (&sim_asynch_wake, &sim_asynch_lock, &done_time))
timedout = TRUE;
else
timedout = TRUE;
sim_asynch_check = 0; /* force check of asynch queue now */
sim_idle_wait = FALSE;
pthread_mutex_unlock (&sim_asynch_lock);
if (!timedout) {
@ -434,13 +434,22 @@ return;
uint32 sim_os_ms_sleep_init (void)
{
TIMECAPS timers;
MMRESULT mm_status;
if (timeGetDevCaps (&timers, sizeof (timers)) != TIMERR_NOERROR)
mm_status = timeGetDevCaps (&timers, sizeof (timers));
if (mm_status != TIMERR_NOERROR) {
fprintf (stderr, "timeGetDevCaps() returned: 0x%X, Last Error: 0x%X\n", mm_status, GetLastError());
return 0;
if (timers.wPeriodMin == 0)
}
if (timers.wPeriodMin == 0) {
fprintf (stderr, "Unreasonable MultiMedia timer minimum value of 0\n");
return 0;
if (timeBeginPeriod (timers.wPeriodMin) != TIMERR_NOERROR)
}
mm_status = timeBeginPeriod (timers.wPeriodMin);
if (mm_status != TIMERR_NOERROR) {
fprintf (stderr, "timeBeginPeriod() returned: 0x%X, Last Error: 0x%X\n", mm_status, GetLastError());
return 0;
}
atexit (sim_timer_exit);
/* return measured actual minimum sleep time */
return _compute_minimum_sleep ();
@ -684,7 +693,7 @@ while (sub->tv_nsec > diff->tv_nsec) {
diff->tv_nsec -= sub->tv_nsec;
diff->tv_sec -= sub->tv_sec;
/* Normalize the result */
while (diff->tv_nsec > 1000000000) {
while (diff->tv_nsec >= 1000000000) {
++diff->tv_sec;
diff->tv_nsec -= 1000000000;
}
@ -705,11 +714,11 @@ t_stat sim_timer_show_idle_mode (FILE* st, UNIT* uptr, int32 val, CONST void *
#if defined(SIM_ASYNCH_CLOCKS)
static int sim_timespec_compare (struct timespec *a, struct timespec *b)
{
while (a->tv_nsec > 1000000000) {
while (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000;
++a->tv_sec;
}
while (b->tv_nsec > 1000000000) {
while (b->tv_nsec >= 1000000000) {
b->tv_nsec -= 1000000000;
++b->tv_sec;
}
@ -1055,8 +1064,15 @@ do {
sim_os_clock_resoluton_ms = clock_diff;
clock_last = clock_now;
} while (clock_now < clock_start + 100);
sim_os_tick_hz = 1000/(sim_os_clock_resoluton_ms * (sim_idle_rate_ms/sim_os_clock_resoluton_ms));
return (sim_idle_rate_ms != 0);
if ((sim_idle_rate_ms != 0) && (sim_os_clock_resoluton_ms != 0))
sim_os_tick_hz = 1000/(sim_os_clock_resoluton_ms * (sim_idle_rate_ms/sim_os_clock_resoluton_ms));
else {
fprintf (stderr, "Can't properly determine host system clock capabilities.\n");
fprintf (stderr, "Minimum Host Sleep Time: %u ms\n", sim_os_sleep_min_ms);
fprintf (stderr, "Minimum Host Sleep Incr Time: %u ms\n", sim_os_sleep_inc_ms);
fprintf (stderr, "Host Clock Resolution: %u ms\n", sim_os_clock_resoluton_ms);
}
return ((sim_idle_rate_ms == 0) || (sim_os_clock_resoluton_ms == 0));
}
/* sim_timer_idle_capable - tell if the host is Idle capable and what the host OS tick size is */
@ -1255,6 +1271,7 @@ return SCPE_OK;
REG sim_timer_reg[] = {
{ DRDATAD (IDLE_CYC_MS, sim_idle_cyc_ms, 32, "Cycles Per Millisecond"), PV_RSPC|REG_RO},
{ DRDATAD (IDLE_STABLE, sim_idle_stable, 32, "IDLE stability delay"), PV_RSPC},
{ DRDATAD (ROM_DELAY, sim_rom_delay, 32, "ROM memory reference delay"), PV_RSPC|REG_RO},
{ DRDATAD (TICK_RATE_0, rtc_hz[0], 32, "Timer 0 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_0, rtc_currd[0], 32, "Timer 0 Tick Size") },
@ -2508,11 +2525,9 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++)
}
if (sim_is_active (uptr)) /* already active? */
return SCPE_OK;
if (usec_delay <= 0.0) {
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n",
if (usec_delay < 0.0) {
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - surprising usec value\n",
sim_uname(uptr), usec_delay);
uptr->usecs_remaining = 0.0;
return SCPE_ARG;
}
uptr->usecs_remaining = 0.0;
/*

View File

@ -721,6 +721,7 @@ else {
written = sim_write_sock (lp->sock, &(lp->txb[i]), length);
if (written == SOCKET_ERROR) { /* did an error occur? */
lp->txdone = TRUE;
if (lp->datagram)
return written; /* ignore errors on datagram sockets */
else
@ -736,8 +737,11 @@ else {
}
}
}
if ((written > 0) && (lp->txbps) && (sim_is_running))
lp->txnexttime = floor (sim_gtime () + ((written * lp->txdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
if (written > 0) {
lp->txdone = FALSE;
if ((lp->txbps) && (sim_is_running))
lp->txnexttime = floor (sim_gtime () + ((written * lp->txdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND));
}
return written;
}
@ -2372,6 +2376,22 @@ t_bool tmxr_tpbusyln (const TMLN *lp)
return (0 != (lp->txppsize - lp->txppoffset));
}
/* Return transmitted data complete status */
/* 0 - not done, 1 - just now done, -1 - previously done. */
int32 tmxr_txdone_ln (TMLN *lp)
{
if (lp->txdone)
return -1; /* previously done */
if ((lp->conn == 0) ||
(lp->txbps == 0) ||
(lp->txnexttime <= sim_gtime ())) {
lp->txdone = TRUE; /* done now */
return 1;
}
return 0; /* not done */
}
static void _mux_detach_line (TMLN *lp, t_bool close_listener, t_bool close_connecting)
{
if (close_listener && lp->master) {
@ -3755,7 +3775,7 @@ pthread_mutex_unlock (&sim_tmxr_poll_lock);
#endif
}
static t_stat _tmxr_locate_line_send_expect (const char *cptr, SEND **snd, EXPECT **exp)
static t_stat _tmxr_locate_line_send_expect (const char *cptr, TMLN **lp, SEND **snd, EXPECT **exp)
{
char gbuf[CBUFSIZE];
DEVICE *dptr;
@ -3776,6 +3796,8 @@ for (i=0; i<tmxr_open_device_count; ++i)
int line = (int)get_uint (cptr, 10, tmxr_open_devices[i]->lines, &r);
if (r != SCPE_OK)
return r;
if (lp)
*lp = &tmxr_open_devices[i]->ldsc[line];
if (snd)
*snd = &tmxr_open_devices[i]->ldsc[line].send;
if (exp)
@ -3787,12 +3809,17 @@ return SCPE_ARG;
t_stat tmxr_locate_line_send (const char *cptr, SEND **snd)
{
return _tmxr_locate_line_send_expect (cptr, snd, NULL);
return _tmxr_locate_line_send_expect (cptr, NULL, snd, NULL);
}
t_stat tmxr_locate_line_expect (const char *cptr, EXPECT **exp)
{
return _tmxr_locate_line_send_expect (cptr, NULL, exp);
return _tmxr_locate_line_send_expect (cptr, NULL, NULL, exp);
}
t_stat tmxr_locate_line (const char *cptr, TMLN **lp)
{
return _tmxr_locate_line_send_expect (cptr, lp, NULL, NULL);
}
static const char *_tmxr_send_expect_line_name (const SEND *snd, const EXPECT *exp)
@ -4191,11 +4218,11 @@ for (i=0; i<mp->lines; i++) {
if ((tmxr_tqln(lp)) && /* pending output data */
(lp->txnexttime < sim_gtime_now))/* that can be transmitted now? */
tmxr_send_buffered_data (lp);/* flush it */
if (tmxr_tqln(lp) == 0) /* no pending output data */
due = interval; /* No rush */
if (lp->txnexttime > sim_gtime_now)
due = (int32)(lp->txnexttime - sim_gtime_now);
else {
if (lp->txnexttime > sim_gtime_now)
due = (int32)(lp->txnexttime - sim_gtime_now);
if (tmxr_tqln(lp) == 0) /* no pending output data */
due = interval; /* No rush */
else
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
}
@ -5363,9 +5390,9 @@ if ((dptr) && (dbits & dptr->dctrl)) {
}
if ((lp->rxnexttime != 0.0) || (lp->txnexttime != 0.0)) {
if (lp->rxnexttime != 0.0)
sim_debug (dbits, dptr, " rxnexttime=%.0f", lp->rxnexttime);
sim_debug (dbits, dptr, " rxnexttime=%.0f (%.0f usecs)", lp->rxnexttime, ((lp->rxnexttime - sim_gtime ()) / sim_timer_inst_per_sec ()) * 1000000.0);
if (lp->txnexttime != 0.0)
sim_debug (dbits, dptr, " txnexttime=%.0f", lp->txnexttime);
sim_debug (dbits, dptr, " txnexttime=%.0f (%.0f usecs)", lp->txnexttime, ((lp->txnexttime - sim_gtime ()) / sim_timer_inst_per_sec ()) * 1000000.0);
sim_debug (dbits, dptr, "\n");
}
}

View File

@ -176,6 +176,7 @@ struct tmln {
uint32 txbps; /* xmt bps speed (0 - unlimited) */
uint32 txdeltausecs; /* xmt inter character min time (usecs) */
double txnexttime; /* min time for next transmit character */
t_bool txdone; /* sent data complete indicator - private */
uint8 *txpb; /* xmt packet buffer */
uint32 txpbsize; /* xmt packet buffer size */
uint32 txppsize; /* xmt packet packet size */
@ -277,6 +278,7 @@ t_stat tmxr_dscln (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
int32 tmxr_rqln (const TMLN *lp);
int32 tmxr_tqln (const TMLN *lp);
int32 tmxr_tpqln (const TMLN *lp);
int32 tmxr_txdone_ln (TMLN *lp);
t_bool tmxr_tpbusyln (const TMLN *lp);
t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
@ -295,6 +297,7 @@ t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks);
t_stat tmxr_change_async (void);
t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd);
t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp);
t_stat tmxr_locate_line (const char *dev_line, TMLN **lp);
const char *tmxr_send_line_name (const SEND *snd);
const char *tmxr_expect_line_name (const EXPECT *exp);
t_stat tmxr_startup (void);

View File

@ -406,17 +406,22 @@ main_argv = argv;
#if SDL_MAJOR_VERSION == 1
_XInitThreads();
SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE);
status = SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE);
vid_main_thread_handle = SDL_CreateThread (main_thread , NULL);
#else
SDL_SetHint (SDL_HINT_RENDER_DRIVER, "software");
SDL_Init (SDL_INIT_VIDEO);
status = SDL_Init (SDL_INIT_VIDEO);
vid_main_thread_handle = SDL_CreateThread (main_thread , "simh-main", NULL);
#endif
if (status) {
fprintf (stderr, "SDL Video subsystem can't initialize\n");
exit (1);
}
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
vid_beep_setup (400, 660);
@ -558,12 +563,12 @@ if (vid_active) {
while (SDL_PushEvent (&user_event) < 0)
sim_os_ms_sleep (10);
if (vid_thread_handle) {
SDL_WaitThread (vid_thread_handle, &status);
vid_thread_handle = NULL;
}
vid_dev = NULL;
}
if (vid_thread_handle) {
SDL_WaitThread (vid_thread_handle, &status);
vid_thread_handle = NULL;
}
while (vid_ready)
sim_os_ms_sleep (10);
if (vid_mouse_events.sem) {
@ -1800,14 +1805,20 @@ return 0;
int vid_thread (void *arg)
{
int stat;
#if SDL_MAJOR_VERSION == 1
_XInitThreads();
SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE);
stat = SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE);
#else
SDL_SetHint (SDL_HINT_RENDER_DRIVER, "software");
SDL_Init (SDL_INIT_VIDEO);
stat = SDL_Init (SDL_INIT_VIDEO);
#endif
if (stat) {
sim_printf ("SDL Video subsystem can't initialize\n");
return 0;
}
vid_beep_setup (400, 660);
vid_video_events ();
vid_beep_cleanup ();
@ -1864,7 +1875,10 @@ fprintf (st, " SDL Events being processed on the main process thread\n");
#endif
if (!vid_active) {
#if !defined (SDL_MAIN_AVAILABLE)
SDL_Init(SDL_INIT_VIDEO);
int stat = SDL_Init(SDL_INIT_VIDEO);
if (stat)
return sim_messagef (SCPE_OPENERR, "SDL_Init() failed. Video subsystem is unavailable.\n");
#endif
}
else {