I1401: Bob Supnik added options to read cards and print line printer output from the console terminal window.

This commit is contained in:
Mark Pizzolato 2015-04-03 17:33:24 -07:00
parent ef6528bf32
commit 7b3fdf5718
5 changed files with 222 additions and 67 deletions

View file

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

View file

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

View file

@ -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? */

View file

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

View file

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