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:
parent
efc9c2abff
commit
d19a528554
@ -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
312
scp.c
@ -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;
|
||||
}
|
||||
|
||||
15
sim_defs.h
15
sim_defs.h
@ -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))
|
||||
|
||||
47
sim_timer.c
47
sim_timer.c
@ -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;
|
||||
/*
|
||||
|
||||
49
sim_tmxr.c
49
sim_tmxr.c
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
32
sim_video.c
32
sim_video.c
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user