I1401: Bob Supnik added options to read cards and print line printer output from the console terminal window.
This commit is contained in:
parent
ef6528bf32
commit
7b3fdf5718
5 changed files with 222 additions and 67 deletions
186
I1401/i1401_cd.c
186
I1401/i1401_cd.c
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_cd.c: IBM 1402 card reader/punch
|
/* i1401_cd.c: IBM 1402 card reader/punch
|
||||||
|
|
||||||
Copyright (c) 1993-2010, Robert M. Supnik
|
Copyright (c) 1993-2015, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
Cards are represented as ASCII text streams terminated by newlines.
|
Cards are represented as ASCII text streams terminated by newlines.
|
||||||
This allows cards to be created and edited as normal files.
|
This allows cards to be created and edited as normal files.
|
||||||
|
|
||||||
|
28-Feb-15 RMS Added read from console
|
||||||
24-Mar-09 RMS Fixed read stacker operation in column binary mode
|
24-Mar-09 RMS Fixed read stacker operation in column binary mode
|
||||||
Fixed punch stacker operation (Van Snyder)
|
Fixed punch stacker operation (Van Snyder)
|
||||||
28-Jun-07 RMS Added support for SS overlap modifiers
|
28-Jun-07 RMS Added support for SS overlap modifiers
|
||||||
|
@ -50,11 +51,47 @@
|
||||||
13-Apr-01 RMS Revised for register arrays
|
13-Apr-01 RMS Revised for register arrays
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Read from console was requested by the 1401 restoration team at the
|
||||||
|
Computer History Museum. It allows small programs to be entered
|
||||||
|
quickly, without creating card files. Unfortunately, if input is
|
||||||
|
coming from the keyboard, then the card reader is not attached,
|
||||||
|
and it won't boot.
|
||||||
|
|
||||||
|
To deal with this problem, the card reader must keep various
|
||||||
|
unit flags in a consistent state:
|
||||||
|
|
||||||
|
ATTABLE? ATT? DFLT? state
|
||||||
|
|
||||||
|
0 0 0 impossible
|
||||||
|
0 0 1 input from console
|
||||||
|
0 1 0 impossible
|
||||||
|
0 1 1 impossible
|
||||||
|
1 0 0 waiting for file
|
||||||
|
1 0 1 impossible
|
||||||
|
1 1 0 input from file
|
||||||
|
1 1 1 input from file,
|
||||||
|
default to console
|
||||||
|
after detach
|
||||||
|
|
||||||
|
To maintain this state, starting from 100, means the
|
||||||
|
following:
|
||||||
|
|
||||||
|
SET CDR DFLT set default flag
|
||||||
|
if !ATT, clear ATTABLE
|
||||||
|
SET CDR NODFLT clear default flag
|
||||||
|
ATTACH CDR set ATTABLE, attach
|
||||||
|
if error && DFLT, clear ATTABLE
|
||||||
|
DETACH CDR detach
|
||||||
|
if DFLT, clear ATTABLE
|
||||||
|
*/
|
||||||
|
|
||||||
#include "i1401_defs.h"
|
#include "i1401_defs.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#define UNIT_V_PCH (UNIT_V_UF + 0) /* output conv */
|
#define UNIT_V_PCH (UNIT_V_UF + 0) /* output conv */
|
||||||
#define UNIT_PCH (1 << UNIT_V_PCH)
|
#define UNIT_PCH (1 << UNIT_V_PCH)
|
||||||
|
#define UNIT_V_CONS (UNIT_V_UF + 1) /* input from console */
|
||||||
|
#define UNIT_CONS (1 << UNIT_V_CONS)
|
||||||
|
|
||||||
extern uint8 M[];
|
extern uint8 M[];
|
||||||
extern int32 ind[64], ssa, iochk;
|
extern int32 ind[64], ssa, iochk;
|
||||||
|
@ -68,13 +105,19 @@ int32 cdp_buf_full = 0; /* punch buf full? */
|
||||||
t_stat cdr_svc (UNIT *uptr);
|
t_stat cdr_svc (UNIT *uptr);
|
||||||
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat cdr_detach (UNIT *uptr);
|
||||||
t_stat cdp_attach (UNIT *uptr, char *cptr);
|
t_stat cdp_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat cdp_detach (UNIT *uptr);
|
t_stat cdp_detach (UNIT *uptr);
|
||||||
t_stat cdp_npr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cdp_npr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cd_reset (DEVICE *dptr);
|
t_stat cd_reset (DEVICE *dptr);
|
||||||
|
t_stat cdr_read_file (char *buf, int32 sz);
|
||||||
|
t_stat cdr_read_cons (char *buf, int32 sz);
|
||||||
|
t_stat cdr_chg_cons (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
int32 bcd2asc (int32 c, UNIT *uptr);
|
int32 bcd2asc (int32 c, UNIT *uptr);
|
||||||
char colbin_to_bcd (uint32 cb);
|
char colbin_to_bcd (uint32 cb);
|
||||||
|
|
||||||
|
extern void inq_puts (char *cptr);
|
||||||
|
|
||||||
/* Card reader data structures
|
/* Card reader data structures
|
||||||
|
|
||||||
cdr_dev CDR descriptor
|
cdr_dev CDR descriptor
|
||||||
|
@ -97,11 +140,17 @@ REG cdr_reg[] = {
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MTAB cdr_mod[] = {
|
||||||
|
{ UNIT_CONS, UNIT_CONS, "default to console", "DEFAULT", &cdr_chg_cons },
|
||||||
|
{ UNIT_CONS, 0 , "no default device", "NODEFAULT", &cdr_chg_cons },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
DEVICE cdr_dev = {
|
DEVICE cdr_dev = {
|
||||||
"CDR", &cdr_unit, cdr_reg, NULL,
|
"CDR", &cdr_unit, cdr_reg, cdr_mod,
|
||||||
1, 10, 31, 1, 8, 7,
|
1, 10, 31, 1, 8, 7,
|
||||||
NULL, NULL, &cd_reset,
|
NULL, NULL, &cd_reset,
|
||||||
&cdr_boot, &cdr_attach, NULL
|
&cdr_boot, &cdr_attach, &cdr_detach
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CDP data structures
|
/* CDP data structures
|
||||||
|
@ -130,7 +179,6 @@ MTAB cdp_mod[] = {
|
||||||
{ UNIT_PCH, UNIT_PCH, "Fortran set", "FORTRAN" },
|
{ UNIT_PCH, UNIT_PCH, "Fortran set", "FORTRAN" },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "NPR",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "NPR",
|
||||||
&cdp_npr, NULL },
|
&cdp_npr, NULL },
|
||||||
|
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,7 +227,7 @@ DEVICE stack_dev = {
|
||||||
|
|
||||||
t_stat read_card (int32 ilnt, int32 mod)
|
t_stat read_card (int32 ilnt, int32 mod)
|
||||||
{
|
{
|
||||||
int32 i, cbn, c1, c2;
|
int32 i, cbn, c1, c2, cbufsz;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
if (sim_is_active (&cdr_unit)) { /* busy? */
|
if (sim_is_active (&cdr_unit)) { /* busy? */
|
||||||
|
@ -187,32 +235,19 @@ if (sim_is_active (&cdr_unit)) { /* busy? */
|
||||||
if ((r = cdr_svc (&cdr_unit))) /* process */
|
if ((r = cdr_svc (&cdr_unit))) /* process */
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if ((cdr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
|
||||||
return SCPE_UNATT;
|
|
||||||
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
||||||
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
||||||
|
cbufsz = (cbn)? 2 * CBUFSIZE: CBUFSIZE; /* buffer size */
|
||||||
for (i = 0; i < (2 * CBUFSIZE) + 1; i++) /* clear extended buf */
|
for (i = 0; i < (2 * CBUFSIZE) + 1; i++) /* clear extended buf */
|
||||||
cdr_buf[i] = 0;
|
cdr_buf[i] = 0;
|
||||||
fgets (cdr_buf, (cbn)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */
|
if ((cdr_unit.flags & UNIT_ATT) != 0) /* attached? */
|
||||||
cdr_unit.fileref);
|
r = cdr_read_file (cdr_buf, cbufsz); /* read from file */
|
||||||
if (feof (cdr_unit.fileref)) /* eof? */
|
else if ((cdr_unit.flags & UNIT_CONS) != 0) /* default to console? */
|
||||||
return STOP_NOCD;
|
r = cdr_read_cons (cdr_buf, cbufsz); /* read from console */
|
||||||
if (ferror (cdr_unit.fileref)) { /* error? */
|
else return SCPE_UNATT; /* else can't read */
|
||||||
ind[IN_READ] = 1;
|
if (r != SCPE_OK) /* read error? */
|
||||||
perror ("Card reader I/O error");
|
return r; /* can't read */
|
||||||
clearerr (cdr_unit.fileref);
|
if (cbn) { /* column binary? */
|
||||||
if (iochk)
|
|
||||||
return SCPE_IOERR;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */
|
|
||||||
if (ssa) { /* if last cd on */
|
|
||||||
getc (cdr_unit.fileref); /* see if more */
|
|
||||||
if (feof (cdr_unit.fileref)) /* eof? set flag */
|
|
||||||
ind[IN_LST] = 1;
|
|
||||||
fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET);
|
|
||||||
}
|
|
||||||
if (cbn) { /* column binary */
|
|
||||||
for (i = 0; i < CDR_WIDTH; i++) {
|
for (i = 0; i < CDR_WIDTH; i++) {
|
||||||
if (conv_old) {
|
if (conv_old) {
|
||||||
c1 = ascii2bcd (cdr_buf[i]);
|
c1 = ascii2bcd (cdr_buf[i]);
|
||||||
|
@ -225,7 +260,7 @@ if (cbn) { /* column binary */
|
||||||
M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | c1;
|
M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | c1;
|
||||||
M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | c2;
|
M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | c2;
|
||||||
M[CDR_BUF + i] = colbin_to_bcd ((c1 << 6) | c2);
|
M[CDR_BUF + i] = colbin_to_bcd ((c1 << 6) | c2);
|
||||||
} /* end for i */
|
}
|
||||||
} /* end if col bin */
|
} /* end if col bin */
|
||||||
else { /* normal read */
|
else { /* normal read */
|
||||||
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
||||||
|
@ -369,6 +404,64 @@ else if (mod == BCD_EIGHT)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read card from file */
|
||||||
|
|
||||||
|
t_stat cdr_read_file (char *buf, int32 sz)
|
||||||
|
{
|
||||||
|
fgets (buf, sz, cdr_unit.fileref); /* rd bin/char card */
|
||||||
|
if (feof (cdr_unit.fileref)) /* eof? */
|
||||||
|
return STOP_NOCD;
|
||||||
|
if (ferror (cdr_unit.fileref)) { /* error? */
|
||||||
|
ind[IN_READ] = 1;
|
||||||
|
perror ("Card reader I/O error");
|
||||||
|
clearerr (cdr_unit.fileref);
|
||||||
|
if (iochk)
|
||||||
|
return SCPE_IOERR;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */
|
||||||
|
if (ssa) { /* if last cd on */
|
||||||
|
getc (cdr_unit.fileref); /* see if more */
|
||||||
|
if (feof (cdr_unit.fileref)) /* eof? set flag */
|
||||||
|
ind[IN_LST] = 1;
|
||||||
|
fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET);
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read card from console */
|
||||||
|
|
||||||
|
t_stat cdr_read_cons (char *buf, int32 sz)
|
||||||
|
{
|
||||||
|
int32 i, t;
|
||||||
|
|
||||||
|
inq_puts ("[Enter card]\r\n");
|
||||||
|
for (i = 0; i < sz; ) {
|
||||||
|
while (((t = sim_poll_kbd ()) == SCPE_OK) || /* wait for char */
|
||||||
|
(t & SCPE_BREAK)) {
|
||||||
|
if (stop_cpu) /* stop? */
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (t < SCPE_KFLAG) /* error? */
|
||||||
|
return t;
|
||||||
|
t = t & 0177;
|
||||||
|
if ((t == '\r') || (t == '\n')) /* eol? */
|
||||||
|
break;
|
||||||
|
if (t == 0177) { /* rubout? */
|
||||||
|
if (i != 0) { /* anything? */
|
||||||
|
buf[--i] = 0;
|
||||||
|
sim_putchar ('\\');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sim_putchar (t);
|
||||||
|
buf[i++] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inq_puts ("\r\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Card reader/punch reset */
|
/* Card reader/punch reset */
|
||||||
|
|
||||||
t_stat cd_reset (DEVICE *dptr)
|
t_stat cd_reset (DEVICE *dptr)
|
||||||
|
@ -379,12 +472,45 @@ sim_cancel (&cdr_unit); /* clear reader event */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set/clear default to console flag
|
||||||
|
|
||||||
|
Caller will do actual bit field update on successful return */
|
||||||
|
|
||||||
|
t_stat cdr_chg_cons (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (val == 0) /* clear? */
|
||||||
|
cdr_unit.flags |= UNIT_ATTABLE; /* attachable on */
|
||||||
|
else if ((cdr_unit.flags & UNIT_ATT) == 0) /* set, unattached? */
|
||||||
|
cdr_unit.flags &= ~UNIT_ATTABLE; /* attachable off */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Card reader attach */
|
/* Card reader attach */
|
||||||
|
|
||||||
t_stat cdr_attach (UNIT *uptr, char *cptr)
|
t_stat cdr_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */
|
ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */
|
||||||
return attach_unit (uptr, cptr);
|
cdr_unit.flags |= UNIT_ATTABLE; /* must be attachable */
|
||||||
|
r = attach_unit (uptr, cptr); /* do attach */
|
||||||
|
if ((r != SCPE_OK) && ((cdr_unit.flags & UNIT_CONS) != 0)) /* failed, default? */
|
||||||
|
cdr_unit.flags &= ~UNIT_ATTABLE; /* clear attachable */
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card reader detach */
|
||||||
|
|
||||||
|
t_stat cdr_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
cdr_unit.flags |= UNIT_ATTABLE; /* must be attachable */
|
||||||
|
r = detach_unit (uptr); /* detach */
|
||||||
|
if (((cdr_unit.flags & UNIT_ATT) == 0) && /* attached clear? */
|
||||||
|
((cdr_unit.flags & UNIT_CONS) != 0)) /* default on? */
|
||||||
|
cdr_unit.flags &= ~UNIT_ATTABLE; /* clear attachable */
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bootstrap routine */
|
/* Bootstrap routine */
|
||||||
|
@ -398,7 +524,7 @@ static const unsigned char boot_rom[] = {
|
||||||
|
|
||||||
t_stat cdr_boot (int32 unitno, DEVICE *dptr)
|
t_stat cdr_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
size_t i;
|
int32 i;
|
||||||
extern int32 saved_IS;
|
extern int32 saved_IS;
|
||||||
|
|
||||||
for (i = 0; i < CDR_WIDTH; i++) /* clear buffer */
|
for (i = 0; i < CDR_WIDTH; i++) /* clear buffer */
|
||||||
|
|
|
@ -207,7 +207,6 @@ InstHistory *hst = NULL; /* instruction history *
|
||||||
t_bool conv_old = 0; /* old conversions */
|
t_bool conv_old = 0; /* old conversions */
|
||||||
|
|
||||||
extern int32 sim_emax;
|
extern int32 sim_emax;
|
||||||
extern t_value *sim_eval;
|
|
||||||
|
|
||||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
|
|
|
@ -269,7 +269,7 @@ switch (fnc) { /* case on function */
|
||||||
for (;;) { /* loop */
|
for (;;) { /* loop */
|
||||||
qzr = (--cnt == 0); /* set zero latch */
|
qzr = (--cnt == 0); /* set zero latch */
|
||||||
dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */
|
dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */
|
||||||
if ((r = dp_rdsec (uptr, psec, flg, qwc))) /* read sector */
|
if ((r = dp_rdsec (uptr, psec, flg, qwc))) /* read sector */
|
||||||
break;
|
break;
|
||||||
cnt = dp_get_cnt (dcf); /* get new count */
|
cnt = dp_get_cnt (dcf); /* get new count */
|
||||||
if (cnt < 0) /* bad count? */
|
if (cnt < 0) /* bad count? */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_iq.c: IBM 1407 inquiry terminal
|
/* i1401_iq.c: IBM 1407 inquiry terminal
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M. Supnik
|
Copyright (c) 1993-2015, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
inq 1407 inquiry terminal
|
inq 1407 inquiry terminal
|
||||||
|
|
||||||
|
08-Mar-15 RMS Renamed puts_tty to inq_puts
|
||||||
20-Sep-05 RMS Revised for new code tables
|
20-Sep-05 RMS Revised for new code tables
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
07-Sep-01 RMS Moved function prototypes
|
07-Sep-01 RMS Moved function prototypes
|
||||||
|
@ -47,7 +48,7 @@ int32 inq_char = 033; /* request inq */
|
||||||
t_stat inq_svc (UNIT *uptr);
|
t_stat inq_svc (UNIT *uptr);
|
||||||
t_stat inq_reset (DEVICE *dptr);
|
t_stat inq_reset (DEVICE *dptr);
|
||||||
|
|
||||||
void puts_tty (char *cptr);
|
void inq_puts (char *cptr);
|
||||||
|
|
||||||
/* INQ data structures
|
/* INQ data structures
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ switch (mod) { /* case on mod */
|
||||||
/* if (ind[IN_INR] == 0) */
|
/* if (ind[IN_INR] == 0) */
|
||||||
/* return SCPE_OK; *//* return if no req */
|
/* return SCPE_OK; *//* return if no req */
|
||||||
ind[IN_INR] = 0; /* clear req */
|
ind[IN_INR] = 0; /* clear req */
|
||||||
puts_tty ("[Enter]\r\n"); /* prompt */
|
inq_puts ("[Enter]\r\n"); /* prompt */
|
||||||
for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */
|
for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */
|
||||||
while (((t = sim_poll_kbd ()) == SCPE_OK) ||
|
while (((t = sim_poll_kbd ()) == SCPE_OK) ||
|
||||||
(t & SCPE_BREAK)) {
|
(t & SCPE_BREAK)) {
|
||||||
|
@ -110,11 +111,11 @@ switch (mod) { /* case on mod */
|
||||||
break;
|
break;
|
||||||
if (t == inq_char) { /* cancel? */
|
if (t == inq_char) { /* cancel? */
|
||||||
ind[IN_INC] = 1; /* set indicator */
|
ind[IN_INC] = 1; /* set indicator */
|
||||||
puts_tty ("\r\n[Canceled]\r\n");
|
inq_puts ("\r\n[Canceled]\r\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
if (i && ((i % INQ_WIDTH) == 0))
|
if (i && ((i % INQ_WIDTH) == 0))
|
||||||
puts_tty ("\r\n");
|
inq_puts ("\r\n");
|
||||||
sim_putchar (t); /* echo */
|
sim_putchar (t); /* echo */
|
||||||
if (flag == MD_WM) { /* word mark mode? */
|
if (flag == MD_WM) { /* word mark mode? */
|
||||||
if ((t == '~') && (wm_seen == 0))
|
if ((t == '~') && (wm_seen == 0))
|
||||||
|
@ -132,7 +133,7 @@ switch (mod) { /* case on mod */
|
||||||
return STOP_NXM;
|
return STOP_NXM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts_tty ("\r\n");
|
inq_puts ("\r\n");
|
||||||
M[BS++] = BCD_GRPMRK + WM;
|
M[BS++] = BCD_GRPMRK + WM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -140,20 +141,20 @@ switch (mod) { /* case on mod */
|
||||||
for (i = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); i++) {
|
for (i = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); i++) {
|
||||||
if ((flag == MD_WM) && (t & WM)) {
|
if ((flag == MD_WM) && (t & WM)) {
|
||||||
if (i && ((i % INQ_WIDTH) == 0))
|
if (i && ((i % INQ_WIDTH) == 0))
|
||||||
puts_tty ("\r\n");
|
inq_puts ("\r\n");
|
||||||
if (conv_old)
|
if (conv_old)
|
||||||
sim_putchar ('~');
|
sim_putchar ('~');
|
||||||
else sim_putchar ('`');
|
else sim_putchar ('`');
|
||||||
}
|
}
|
||||||
if (i && ((i % INQ_WIDTH) == 0))
|
if (i && ((i % INQ_WIDTH) == 0))
|
||||||
puts_tty ("\r\n");
|
inq_puts ("\r\n");
|
||||||
sim_putchar (bcd2ascii (t & CHAR, use_h));
|
sim_putchar (bcd2ascii (t & CHAR, use_h));
|
||||||
if (ADDR_ERR (BS)) {
|
if (ADDR_ERR (BS)) {
|
||||||
BS = BA | (BS % MAXMEMSIZE);
|
BS = BA | (BS % MAXMEMSIZE);
|
||||||
return STOP_NXM;
|
return STOP_NXM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts_tty ("\r\n");
|
inq_puts ("\r\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* invalid mod */
|
default: /* invalid mod */
|
||||||
|
@ -179,7 +180,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Output multiple characters */
|
/* Output multiple characters */
|
||||||
|
|
||||||
void puts_tty (char *cptr)
|
void inq_puts (char *cptr)
|
||||||
{
|
{
|
||||||
if (cptr == NULL)
|
if (cptr == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_lp.c: IBM 1403 line printer simulator
|
/* i1401_lp.c: IBM 1403 line printer simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2013, Robert M. Supnik
|
Copyright (c) 1993-2015, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
lpt 1403 line printer
|
lpt 1403 line printer
|
||||||
|
|
||||||
|
08-Mar-15 RMS Added print to console option
|
||||||
16-Apr-13 RMS Fixed printer chain selection
|
16-Apr-13 RMS Fixed printer chain selection
|
||||||
19-Jan-07 RMS Added UNIT_TEXT flag
|
19-Jan-07 RMS Added UNIT_TEXT flag
|
||||||
07-Mar-05 RMS Fixed bug in write_line (Van Snyder)
|
07-Mar-05 RMS Fixed bug in write_line (Van Snyder)
|
||||||
|
@ -48,6 +49,9 @@ int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0;
|
||||||
t_stat lpt_reset (DEVICE *dptr);
|
t_stat lpt_reset (DEVICE *dptr);
|
||||||
t_stat lpt_attach (UNIT *uptr, char *cptr);
|
t_stat lpt_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat space (int32 lines, int32 lflag);
|
t_stat space (int32 lines, int32 lflag);
|
||||||
|
t_stat lpt_puts (char *buf);
|
||||||
|
|
||||||
|
extern void inq_puts (char *buf);
|
||||||
|
|
||||||
char *pch_table_old[4] = {
|
char *pch_table_old[4] = {
|
||||||
bcd_to_ascii_old, bcd_to_ascii_old, bcd_to_pca, bcd_to_pch
|
bcd_to_ascii_old, bcd_to_ascii_old, bcd_to_pca, bcd_to_pch
|
||||||
|
@ -58,8 +62,10 @@ char *pch_table[4] = {
|
||||||
|
|
||||||
#define UNIT_V_FT (UNIT_V_UF + 0)
|
#define UNIT_V_FT (UNIT_V_UF + 0)
|
||||||
#define UNIT_V_48 (UNIT_V_UF + 1)
|
#define UNIT_V_48 (UNIT_V_UF + 1)
|
||||||
|
#define UNIT_V_CONS (UNIT_V_UF + 2)
|
||||||
#define UNIT_FT (1 << UNIT_V_FT)
|
#define UNIT_FT (1 << UNIT_V_FT)
|
||||||
#define UNIT_48 (1 << UNIT_V_48)
|
#define UNIT_48 (1 << UNIT_V_48)
|
||||||
|
#define UNIT_CONS (1 << UNIT_V_CONS)
|
||||||
#define GET_PCHAIN(x) (((x) >> UNIT_V_FT) & 03)
|
#define GET_PCHAIN(x) (((x) >> UNIT_V_FT) & 03)
|
||||||
#define CHP(ch,val) ((val) & (1 << (ch)))
|
#define CHP(ch,val) ((val) & (1 << (ch)))
|
||||||
|
|
||||||
|
@ -89,6 +95,8 @@ MTAB lpt_mod[] = {
|
||||||
{ UNIT_48, 0, "64 character chain", "64" },
|
{ UNIT_48, 0, "64 character chain", "64" },
|
||||||
{ UNIT_FT, UNIT_FT, "Fortran set", "FORTRAN" },
|
{ UNIT_FT, UNIT_FT, "Fortran set", "FORTRAN" },
|
||||||
{ UNIT_FT, 0, "business set", "BUSINESS" },
|
{ UNIT_FT, 0, "business set", "BUSINESS" },
|
||||||
|
{ UNIT_CONS, UNIT_CONS, "default to console", "DEFAULT" },
|
||||||
|
{ UNIT_CONS, 0 , "no default device", "NODEFAULT" },
|
||||||
{ UNIT_FT|UNIT_48, 0, NULL, "PCF" }, /* obsolete */
|
{ UNIT_FT|UNIT_48, 0, NULL, "PCF" }, /* obsolete */
|
||||||
{ UNIT_FT|UNIT_48, UNIT_48, NULL, "PCA" },
|
{ UNIT_FT|UNIT_48, UNIT_48, NULL, "PCA" },
|
||||||
{ UNIT_FT|UNIT_48, UNIT_FT|UNIT_48, NULL, "PCH" },
|
{ UNIT_FT|UNIT_48, UNIT_FT|UNIT_48, NULL, "PCH" },
|
||||||
|
@ -113,10 +121,9 @@ t_stat write_line (int32 ilnt, int32 mod)
|
||||||
{
|
{
|
||||||
int32 i, t, wm, sup;
|
int32 i, t, wm, sup;
|
||||||
char *bcd2asc;
|
char *bcd2asc;
|
||||||
|
t_stat r;
|
||||||
static char lbuf[LPT_WIDTH + 1]; /* + null */
|
static char lbuf[LPT_WIDTH + 1]; /* + null */
|
||||||
|
|
||||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
|
||||||
return SCPE_UNATT;
|
|
||||||
wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE);
|
wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE);
|
||||||
sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S);
|
sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S);
|
||||||
ind[IN_LPT] = 0; /* clear error */
|
ind[IN_LPT] = 0; /* clear error */
|
||||||
|
@ -133,24 +140,15 @@ for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */
|
||||||
lbuf[LPT_WIDTH] = 0; /* trailing null */
|
lbuf[LPT_WIDTH] = 0; /* trailing null */
|
||||||
for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--)
|
for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--)
|
||||||
lbuf[i] = 0;
|
lbuf[i] = 0;
|
||||||
fputs (lbuf, lpt_unit.fileref); /* write line */
|
if ((r = lpt_puts (lbuf)) != SCPE_OK) /* write line */
|
||||||
|
return r; /* error? */
|
||||||
if (lines) /* cc action? do it */
|
if (lines) /* cc action? do it */
|
||||||
space (lines, lflag);
|
r = space (lines, lflag);
|
||||||
else if (sup == 0) /* default? 1 line */
|
else if (sup == 0) /* default? 1 line */
|
||||||
space (1, FALSE);
|
r = space (1, FALSE);
|
||||||
else {
|
else r = lpt_puts ("\r"); /* sup -> overprint */
|
||||||
fputc ('\r', lpt_unit.fileref); /* sup -> overprint */
|
|
||||||
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
|
||||||
}
|
|
||||||
lines = lflag = 0; /* clear cc action */
|
lines = lflag = 0; /* clear cc action */
|
||||||
if (ferror (lpt_unit.fileref)) { /* error? */
|
return r;
|
||||||
ind[IN_LPT] = 1;
|
|
||||||
perror ("Line printer I/O error");
|
|
||||||
clearerr (lpt_unit.fileref);
|
|
||||||
if (iochk)
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Carriage control routine
|
/* Carriage control routine
|
||||||
|
@ -221,20 +219,51 @@ return SCPE_OK;
|
||||||
t_stat space (int32 count, int32 sflag)
|
t_stat space (int32 count, int32 sflag)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
if ((lpt_unit.flags & UNIT_ATT) == 0)
|
|
||||||
return SCPE_UNATT;
|
|
||||||
cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */
|
cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */
|
||||||
if (sflag && CHP (0, cct[cctptr])) /* skip, top of form? */
|
if (sflag && CHP (0, cct[cctptr])) /* skip, top of form? */
|
||||||
fputs ("\n\f", lpt_unit.fileref); /* nl, ff */
|
r = lpt_puts ("\n\f"); /* nl, ff */
|
||||||
else {
|
else {
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; (i < count); i++)
|
||||||
fputc ('\n', lpt_unit.fileref);
|
if ((r = lpt_puts ("\n")) != SCPE_OK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
|
||||||
ind[IN_CC9] = CHP (9, cct[cctptr]) != 0; /* set indicators */
|
ind[IN_CC9] = CHP (9, cct[cctptr]) != 0; /* set indicators */
|
||||||
ind[IN_CC12] = CHP (12, cct[cctptr]) != 0;
|
ind[IN_CC12] = CHP (12, cct[cctptr]) != 0;
|
||||||
return SCPE_OK;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Centralized string print routine
|
||||||
|
Prints to either a file or the console
|
||||||
|
|
||||||
|
Note that if printing to the console, newline must be converted to crlf */
|
||||||
|
|
||||||
|
t_stat lpt_puts (char *buf)
|
||||||
|
{
|
||||||
|
if ((lpt_unit.flags & UNIT_ATT) != 0) { /* attached? */
|
||||||
|
fputs (buf, lpt_unit.fileref); /* print string */
|
||||||
|
if (ferror (lpt_unit.fileref)) { /* error? */
|
||||||
|
ind[IN_LPT] = 1;
|
||||||
|
perror ("Line printer I/O error");
|
||||||
|
clearerr (lpt_unit.fileref);
|
||||||
|
if (iochk)
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
||||||
|
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if ((lpt_unit.flags & UNIT_CONS) != 0) { /* default to cons? */
|
||||||
|
if (buf[0] == '\n') { /* bare lf? */
|
||||||
|
inq_puts ("\r"); /* cvt to crlf */
|
||||||
|
lpt_unit.pos = lpt_unit.pos + 1;
|
||||||
|
}
|
||||||
|
inq_puts (buf);
|
||||||
|
lpt_unit.pos = lpt_unit.pos + strlen (buf);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
return SCPE_UNATT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
Loading…
Add table
Reference in a new issue