diff --git a/SDS/sds_cp.c b/SDS/sds_cp.c
new file mode 100644
index 00000000..4ec439fd
--- /dev/null
+++ b/SDS/sds_cp.c
@@ -0,0 +1,318 @@
+/* sds_cp.c - SDS-930 Card Punch
+
+ Copyright (c) 2020, Ken Rector
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ KEN RECTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of Ken Rector shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from Ken Rector.
+
+ 03-Mar-20 kenr Initial Version
+
+*/
+
+/*
+ This card punch simulator uses sim_card.c to write output records
+ in CBN format. Data is passed directly to sim_card.c when binary
+ mode is specified by the buffer control EOM. When BCD mode is
+ specified by the EOM, output data is translated into Hollerith code
+ from SDS Internal Code as defined by the SDS 930 Computer Reference Manual
+
+ The SDS card punch protocol defined by the 930 Computer Reference manual
+ specifies that the output image be sent to the buffer 12 times, once
+ for each row. In this simulator the card image is only written after
+ termination (TOP) of the twelfth image output.
+
+ The Symbol assembler punch routine uses the PBT (Punch Buffer Test)
+ before issueing a connect EOM to determine if it needs to write 12 rows
+ per card, or just 1. To make Symbol work right we always return TRUE,
+ (skip) for this test.
+
+ I can't find anything in the computer reference manuals that describes
+ how this should work. Why did Symbol do this?
+
+ */
+
+
+#include "sds_defs.h"
+#include "sim_card.h"
+
+#define CARD_IN_PUNCH 00004000 /* Card ready to punch */
+
+#define STATUS u3
+
+extern uint32 xfr_req;
+extern int32 stop_invins, stop_invdev, stop_inviop;
+
+uint16 cp_buffer[80]; /* card output image */
+int32 cp_bptr = 0; /* buf ptr */
+int32 cp_blnt = 0; /* buf length */
+int32 cp_row = 0; /* row counter */
+int32 cp_chr = 0;
+int32 cp_eor;
+int32 cp_inst; /* saved instr */
+
+t_stat cp_devio(uint32 fnc, uint32 inst, uint32 *dat);
+t_stat cp_svc(UNIT *);
+t_stat cp_attach(UNIT * uptr, CONST char *file);
+t_stat cp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
+t_stat cp_detach(UNIT * uptr);
+t_stat cp_wrend(UNIT * uptr);
+t_stat cp_show_cap (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
+void cp_set_err (UNIT *uptr);
+
+
+
+DSPT cp_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */
+
+DIB cp_dib = { CHAN_W, DEV_CP, XFR_CP, cp_tplt, &cp_devio };
+
+UNIT cp_unit = {UDATA(&cp_svc, UNIT_ATTABLE , 0), 2000 };
+
+MTAB cp_mod[] = {
+ {MTAB_XTD | MTAB_VDV, 0, "CHANNEL", "CHANNEL",
+ &set_chan, &show_chan,
+ NULL, "Device Channel"},
+ {MTAB_XTD | MTAB_VDV, 0, "FORMAT", "FORMAT",
+ &sim_card_set_fmt, &sim_card_show_fmt,
+ NULL,"Card Format"},
+ { MTAB_XTD|MTAB_VDV, 0, "CAPACITY", NULL,
+ NULL, &cp_show_cap, NULL, "Stacker Count" },
+ {0}
+};
+
+REG cp_reg[] = {
+ { BRDATA (BUFF, cp_buffer, 16, 16, sizeof(cp_buffer)/sizeof(*cp_buffer)), REG_HRO},
+ { DRDATA (BPTR, cp_bptr, 18), PV_LEFT },
+ { DRDATA (BLNT, cp_blnt, 18), PV_LEFT },
+ { FLDATA (XFR, xfr_req, XFR_V_CP) },
+ { ORDATA (INST, cp_inst, 24) },
+ { DRDATA (POS, cp_unit.pos, T_ADDR_W), PV_LEFT },
+ { NULL }
+};
+
+DEVICE cp_dev = {
+ "CP", &cp_unit, cp_reg, cp_mod,
+ 1, 8, 15, 1, 8, 8,
+ NULL, NULL, NULL, NULL, &cp_attach, &cp_detach,
+ &cp_dib, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* Convert SDS BCD character into hollerith code */
+
+uint16 sdsbcd_to_hol(uint8 bcd) {
+ uint16 hol;
+
+ /* Handle space correctly */
+ if (bcd == 0) /* 0 to row 10 */
+ return 0x200;
+ if (bcd == 060) /* 60 no punch */
+ return 0;
+
+ /* Convert to top column */
+ switch (bcd & 060) {
+ default:
+ case 000:
+ hol = 0x000; /* no zone */
+ break;
+ case 020:
+ hol = 0x800; /* 0x200 row 12 */
+ break;
+ case 040:
+ hol = 0x400; /* row 11 */
+ break;
+ case 060:
+ hol = 0x200; /* row 10 */
+ break;
+ }
+
+ /* Convert to 0-9 row */
+ bcd &= 017;
+ if (bcd > 9) {
+ hol |= 0x2; /* row 8 */
+ bcd -= 8;
+ }
+ if (bcd != 0)
+ hol |= 1 << (9 - bcd);
+ return hol;
+}
+
+t_stat cp_devio(uint32 fnc, uint32 inst, uint32 *dat) {
+ UNIT *uptr = &cp_unit;
+ int32 new_ch;
+ uint8 chr;
+ t_stat r;
+ uint32 t;
+
+ switch (fnc) {
+ case IO_CONN:
+ new_ch = I_GETEOCH (inst); /* get new chan */
+ if (new_ch != cp_dib.chan) /* wrong chan? err */
+ return SCPE_IERR;
+ if (sim_is_active(uptr))
+ CRETIOP;
+ if (uptr->flags & UNIT_ATT) {
+ cp_inst = inst;
+ cp_blnt = 0;
+ cp_bptr = 0;
+ xfr_req = xfr_req & ~XFR_CP; /* clr xfr flag */
+ sim_activate (uptr, uptr->wait); /* start timer */
+ }
+ else {
+ cp_set_err (uptr); /* no, err, disc */
+ CRETIOP;
+ }
+ break;
+ case IO_EOM1: /* I/O Control EOM */
+ break;
+ case IO_DISC: /* disconnect TOP */
+ xfr_req = xfr_req & ~XFR_CP; /* clr xfr flag */
+ cp_row++;
+ if (cp_row >= 12) {
+ if ((r = cp_wrend(uptr)) != SCPE_OK)
+ return r;
+ uptr->STATUS &= ~CARD_IN_PUNCH;
+ }
+ sim_cancel (uptr); /* deactivate unit */
+ break;
+ case IO_WREOR: /* write eor */
+ break;
+ case IO_SKS:
+ new_ch = I_GETSKCH (inst); /* get chan # */
+ if (new_ch != cp_dib.chan) /* wrong chan? */
+ return SCPE_IERR;
+ t = I_GETSKCND (inst); /* get skip cond */
+ switch (t) { /* case sks cond */
+ case 010: /* sks 12046 */
+ // PBT
+ // /* skip if punch buffer empty */
+ *dat = 1;
+ break;
+ case 020: /* sks 14046 */
+ // CPT
+ /* skip if punch is ready to accept connection */
+ if ((uptr->flags & UNIT_ATT) &&
+ !(uptr->STATUS & CARD_IN_PUNCH))
+ *dat = 1;
+ break;
+ }
+ break;
+ case IO_WRITE:
+ if (!(uptr->STATUS & CARD_IN_PUNCH))
+ break;
+ chr = (*dat) & 077;
+ xfr_req = xfr_req & ~XFR_CP; /* clr xfr flag */
+ if (cp_bptr < cp_blnt) {
+ if (cp_inst & 01000) {
+ if (cp_chr & 1) /* column binary */
+ cp_buffer[cp_bptr++] |= chr;
+ else
+ cp_buffer[cp_bptr] = (chr << 6);
+ cp_chr++;
+ }
+ else {
+ cp_buffer[cp_bptr++] = sdsbcd_to_hol(chr); /* bcd */
+ }
+ chan_set_ordy (cp_dib.chan);
+ }
+ break;
+ case IO_READ:
+ CRETINS;
+ }
+
+ return SCPE_OK;
+}
+
+
+/* punch service */
+t_stat cp_svc(UNIT *uptr) {
+
+ uptr->STATUS |= CARD_IN_PUNCH;
+ cp_bptr = 0;
+ cp_blnt = 80;
+ cp_chr = 0;
+ chan_set_ordy (cp_dib.chan);
+ return SCPE_OK;
+}
+
+t_stat cp_wrend(UNIT * uptr) {
+ t_stat st;
+
+ st = sim_punch_card(uptr, cp_buffer);
+ cp_row = 0;
+ if (st != CDSE_OK) {
+ cp_set_err(uptr);
+ return SCPE_IOERR;
+ }
+ uptr->STATUS = 0;
+ return SCPE_OK;
+}
+
+/* Fatal error */
+void cp_set_err (UNIT *uptr)
+{
+ chan_set_flag (cp_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
+ chan_disc (cp_dib.chan); /* disconnect */
+ xfr_req = xfr_req & ~XFR_CP; /* clear xfr */
+ sim_cancel (uptr); /* stop */
+ cp_bptr = 0; /* buf empty */
+ return;
+}
+
+t_stat cp_attach(UNIT * uptr, CONST char *cptr) {
+ t_stat r;
+
+ sim_card_set_fmt (uptr,0,"CBN",NULL);
+ if ((r = sim_card_attach(uptr, cptr)) != SCPE_OK)
+ return r;
+ cp_row = 0;
+ return SCPE_OK;
+}
+
+t_stat cp_detach(UNIT * uptr) {
+
+ if (uptr->STATUS & CARD_IN_PUNCH)
+ sim_punch_card(uptr, cp_buffer);
+ return sim_card_detach(uptr);
+}
+
+/* Channel assignment routines */
+
+t_stat cp_set_chan (UNIT *uptr, int32 val, CONST char *sptr, void *desc)
+{
+ t_stat r;
+ r = set_chan (uptr, val, sptr, desc);
+ return r;
+}
+
+t_stat cp_show_cap (FILE *st, UNIT *uptr, int32 val, CONST void *desc) {
+ int n;
+
+ if ((n = sim_card_output_hopper_count(uptr)) == 0)
+ fprintf(st,"stacker empty");
+ else {
+ if (n == 1)
+ fprintf(st,"1 card");
+ else
+ fprintf(st,"%d cards",n);
+ fprintf(st," in stacker");
+ }
+ return SCPE_OK;
+}
diff --git a/SDS/sds_cr.c b/SDS/sds_cr.c
new file mode 100644
index 00000000..06ea3483
--- /dev/null
+++ b/SDS/sds_cr.c
@@ -0,0 +1,381 @@
+/* sds_cr.c: SDS-930 card reader simulator
+
+ Copyright (c) 2020, Ken Rector
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ KEN RECTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of Ken Rector shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from Ken Rector.
+
+ 03-Mar-20 kenr Initial Version
+
+ */
+
+/*
+ This card reader simulator uses sim_card.c to attach and read input records
+ in CBN format. When BCD mode is specified by the buffer control EOM, input data
+ is translated from the Hollerith encoded data in the card columns to the
+ SDS Internal Code as defined by the SDS 930 Computer Reference Manual. The
+ translation function was modified from the sim_card.c code to provide SDS
+ Internal BCD codes.
+
+ The card reader delays the disconnect after the last character until the trailing
+ edge of the card is detected. In this simulator, this delay is accomplished
+ by scheduling a final service request after the last characters have been
+ delivered too the channel. The timing for this service has been adjusted to
+ handle some example SDS programs. Too long a delay causes errors in some, too short
+ a delay affects others.
+ */
+
+#include "sds_defs.h"
+#include "sim_card.h"
+
+#define FEEDING 00001000 /* feeding card to read station */
+#define READING 00004000 /* Card at read station */
+
+#define STATUS u3 /* status */
+
+#define CARD_RDY(u) (sim_card_input_hopper_count(u) > 0 || \
+sim_card_eof(u) == 1)
+
+extern uint32 xfr_req;
+extern int32 stop_invins, stop_invdev, stop_inviop;
+extern uint8 chan_cpw[NUM_CHAN]; /* char per word */
+extern uint8 chan_cnt[NUM_CHAN]; /* char count */
+
+int32 cr_bptr = 0; /* buf ptr */
+int32 cr_blnt = 0; /* buf length */
+int32 cr_chr = 0; /* char no.*/
+int32 cr_inst = 0; /* saved instr */
+int32 cr_eor = 0; /* end of record */
+uint16 cr_buffer[80]; /* card record */
+
+DSPT cr_tplt[] = {{1,0},{0,0}}; /* template */
+
+t_stat cr_svc(UNIT *);
+t_stat cr_boot(int32, DEVICE *);
+t_stat cr_reset(DEVICE *);
+t_stat cr_attach(UNIT *, CONST char *);
+t_stat cr_detach(UNIT *);
+t_stat cr_devio(uint32 fnc, uint32 inst, uint32 *dat);
+t_stat cr_show_cap (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
+t_stat cr_readrec (UNIT *uptr);
+void cr_set_err (UNIT *uptr);
+
+DIB cr_dib = { CHAN_W, DEV_CR, XFR_CR, cr_tplt, &cr_devio };
+
+UNIT cr_unit = {
+ UDATA(&cr_svc, UNIT_ATTABLE | UNIT_RO | UNIT_DISABLE | MODE_029 | MODE_CBN,0),
+ 60
+};
+
+REG cr_reg[] = {
+ { DRDATA (BPTR, cr_bptr, 18), PV_LEFT },
+ { DRDATA (BLNT, cr_blnt, 18), PV_LEFT },
+ { FLDATA (XFR, xfr_req, XFR_V_CR) },
+ { ORDATA (INST, cr_inst, 24) },
+ { DRDATA (POS, cr_unit.pos, T_ADDR_W), PV_LEFT },
+ { NULL }
+};
+
+MTAB cr_mod[] = {
+ {MTAB_XTD | MTAB_VDV, 0, "CHANNEL", "CHANNEL",
+ &set_chan,&show_chan,NULL, "Device Channel"},
+ {MTAB_XTD | MTAB_VDV, 0, "FORMAT", "FORMAT",
+ &sim_card_set_fmt, &sim_card_show_fmt,
+ NULL,"Card Format"},
+ { MTAB_XTD|MTAB_VDV, 0, "CAPACITY", NULL,
+ NULL, &cr_show_cap, NULL, "Card Input Status" },
+ {0}
+};
+
+DEVICE cr_dev = {
+ "CR", &cr_unit, cr_reg, cr_mod,
+ 1, 10, 31, 1, 8, 8,
+ NULL, NULL, &cr_reset, &cr_boot, &cr_attach,NULL,
+ &cr_dib, DEV_DISABLE | DEV_CARD, 0, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* Returns the SDS Internal style BCD of the
+ hollerith code or 0x7f if error
+ */
+uint8 hol_to_sdsbcd(uint16 hol) {
+ uint8 bcd;
+
+ /* Convert 10,11,12 rows */
+ switch (hol & 0xe00) {
+ case 0x000:
+ if ((hol & 0x1ff) == 0)
+ return 060;
+ bcd = 000; // digits 1-9
+ break;
+ case 0x200: /* 0 */
+ if ((hol & 0x1ff) == 0)
+ return 00; // digit 0
+ bcd = 060; // /,S-Z
+ break;
+ case 0x400: /* 11 */
+ bcd = 040; // -,J-R
+ break;
+ case 0x600: /* 11-10 Punch */
+ bcd = 052;
+ break;
+ case 0x800: /* 12 */
+ bcd = 020; // +,A-I
+ break;
+ case 0xA00: /* 12-10 Punch */
+ bcd = 032;
+ break;
+ default: /* Double punch in 10,11,12 rows */
+ return 0x7f;
+ }
+
+ hol &= 0x1ff; /* Mask rows 0-9 */
+ /* Check row 8 punched */
+ if (hol & 0x2) {
+ bcd += 8;
+ hol &= ~0x2;
+ }
+
+ /* Convert rows 0-9 */
+ while (hol != 0 && (hol & 0x200) == 0) {
+ bcd++;
+ hol <<= 1;
+ }
+
+ /* Any more columns punched? */
+ if ((hol & 0x1ff) != 0)
+ return 0x7f;
+ return bcd;
+}
+
+/* device i/o routine */
+t_stat cr_devio (uint32 fnc, uint32 inst, uint32 *dat) {
+ UNIT *uptr = &cr_unit; /* get unit ptr */
+ int32 new_ch;
+ int32 t;
+ t_stat r;
+ unsigned char chr;
+
+ switch (fnc) { /* case function */
+ case IO_CONN: /* bufer control EOM */
+ new_ch = I_GETEOCH (inst); /* get new chan */
+ if (new_ch != cr_dib.chan) /* wrong chan? */
+ return SCPE_IERR;
+ if (sim_is_active(uptr)) /* busy ?*/
+ CRETIOP;
+ /* if not reading and no card in reader and hopper has cards */
+ if ((uptr->STATUS & (FEEDING|READING)) == 0 &&
+ (sim_card_input_hopper_count(uptr) > 0)) {
+ uptr->STATUS = FEEDING;
+ cr_inst = inst;
+ cr_blnt = 0;
+ cr_bptr = 0;
+ xfr_req = xfr_req & ~XFR_CR; /* clr xfr flag */
+ sim_activate (uptr,2*uptr->wait); /* start timer */
+ }
+ else {
+ /* if feeding or reading in different mode */
+ if ((inst & 01000) != (cr_inst & 01000)) {
+ if (cr_inst & 01000) {
+ if (cr_chr & 1) { /* was binary - at 2nd 6 bits
+ */
+ cr_bptr++; /* skip to next column*/
+ }
+ }
+ cr_chr = 0;
+ }
+ }
+ cr_inst = inst; /* save EOM with mode */
+ break;
+ case IO_EOM1: /* I/O Control EOM */
+ new_ch = I_GETEOCH (inst); /* get new chan */
+ if (new_ch != cr_dib.chan) /* wrong chan? err */
+ return SCPE_IERR;
+ if ((inst & 07700) == 02000) { /* skip remainder of card*/
+ sim_cancel (uptr); /* stop timer */
+ chan_set_flag (cr_dib.chan, CHF_EOR); /* end record */
+ uptr->STATUS = 0;
+ chan_disc (cr_dib.chan);
+ xfr_req = xfr_req & ~XFR_CR; /* clr xfr flag */
+ }
+ break;
+ case IO_DISC: /* disconnect */
+ xfr_req = xfr_req & ~XFR_CR; /* clr xfr flag */
+ sim_cancel (uptr); /* deactivate unit */
+ break;
+ case IO_SKS: /* SKS */
+ new_ch = I_GETSKCH (inst); /* get chan # */
+ if (new_ch != cr_dib.chan) /* wrong chan? */
+ return SCPE_IERR;
+ t = I_GETSKCND (inst); /* get skip cond */
+ switch (t) { /* case sks cond */
+ case 004: /* sks 1100n */
+ // CFT
+ if ((uptr->STATUS & (FEEDING|READING)) == 0 &&
+ (sim_card_input_hopper_count(uptr) > 0))
+ *dat = 1; /* skip if not EOF */
+ break;
+ case 010: /* sks 1200n */
+ // CRT
+ // hopper not empty
+ // no feed or read cycle is in progress
+ if ((uptr->STATUS & (FEEDING|READING)) == 0 &&
+ (sim_card_input_hopper_count(uptr) > 0))
+ *dat = 1; /* skip if reader ready */
+ break;
+ case 020: /* sks 1400n */
+ if ((uptr->STATUS & READING) && /* first column test */
+ (((cr_inst & 01000) && (cr_chr < 2)) ||
+ (cr_chr < 1)))
+ *dat = 1; /* skip if first column*/
+ break;
+ }
+ break;
+ case IO_READ:
+ xfr_req = xfr_req & ~XFR_CR;
+ if (cr_blnt == 0) { /* first read? */
+ r = cr_readrec (uptr); /* get data */
+ if ((r != SCPE_OK) || (cr_blnt == 0)) /* err, inv reclnt? */
+ return r;
+ }
+ if (cr_blnt) {
+ if (cr_inst & 01000) {
+ if (cr_chr & 1) /* binary */
+ chr =cr_buffer[cr_bptr++] & 077;
+ else
+ chr = (cr_buffer[cr_bptr] >> 6) & 077;
+ cr_chr++;
+ *dat = chr & 077;
+ }
+ else {
+ chr = hol_to_sdsbcd(cr_buffer[cr_bptr++]); /* bcd */
+ *dat = chr & 077;
+ }
+ }
+ if (cr_bptr >= cr_blnt) {
+ /* The card reader doesn't disconnect from the channel until the
+ trailing edge of the card passes the read station so we need to
+ schedule another service event here. But if it disconnects too
+ soon some programs (Fortran and 850647 (unencode) don't work right
+ and if it takes too long Symbol will try to connect to the LP
+ before it's disconnected.
+ */
+ cr_eor = 1;
+ sim_cancel(uptr);
+ sim_activate (uptr, 50);
+ }
+ break;
+ case IO_WREOR:
+ case IO_WRITE:
+ CRETINS;
+ }
+ return SCPE_OK;
+}
+
+
+/* Service routine */
+t_stat cr_svc(UNIT * uptr) {
+ xfr_req = xfr_req & ~XFR_CR;
+ if (cr_eor) {
+ cr_eor = 0;
+ sim_cancel (uptr);
+ chan_set_flag (cr_dib.chan, CHF_EOR);
+ uptr->STATUS = 0;
+ return SCPE_OK;
+ }
+ xfr_req = xfr_req | XFR_CR;
+ sim_activate (uptr, 50);
+ return SCPE_OK;
+}
+
+
+/* Read start - get next record */
+t_stat cr_readrec (UNIT *uptr) {
+ int r;
+
+ switch(r = sim_read_card(uptr, cr_buffer)) {
+ case CDSE_EOF: /* parser found tape mark attach */
+ case CDSE_EMPTY: /* not attached or hopper empty */
+ case CDSE_ERROR: /* parser found error during attach */
+ default:
+ uptr->STATUS = 0; /* read failed, no card in reader */
+ cr_set_err(uptr);
+ return r;
+ case CDSE_OK:
+ uptr->STATUS = READING;
+ cr_bptr = 0;
+ cr_blnt = 80;
+ cr_chr = 0;
+ break;
+ }
+ return SCPE_OK;
+}
+
+/* Fatal error */
+void cr_set_err (UNIT *uptr) {
+ chan_set_flag (cr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
+ chan_disc (cr_dib.chan); /* disconnect */
+ xfr_req = xfr_req & ~XFR_CR; /* clear xfr */
+ sim_cancel (uptr); /* stop */
+ cr_bptr = 0; /* buf empty */
+ return;
+}
+
+t_stat cr_reset (DEVICE *dptr) {
+ chan_disc (cr_dib.chan); /* disconnect */
+ cr_bptr = cr_blnt = 0;
+ xfr_req = xfr_req & ~XFR_CR; /* clr xfr flag */
+ sim_cancel (&cr_unit); /* deactivate unit */
+ return SCPE_OK;
+}
+
+t_stat cr_attach (UNIT *uptr, CONST char *cptr) {
+ return sim_card_attach(uptr, cptr);
+}
+
+/* Boot routine - simulate FILL console command */
+t_stat cr_boot (int32 unitno, DEVICE *dptr) {
+ extern uint32 P, M[];
+
+ cr_reset(dptr);
+ M[0] = 077777771; /* -7B */
+ M[1] = 007100000; /* LDX 0 */
+ M[2] = 000203606; /* EOM 3606 read card binary */
+ M[3] = 003200002; /* WIM 2 */
+ M[4] = 000100002; /* BRU 2 */
+ P = 1; /* start at 1 */
+ return SCPE_OK;
+}
+
+t_stat cr_show_cap (FILE *st, UNIT *uptr, int32 val, CONST void *desc) {
+ int n;
+
+ if ((n = sim_card_input_hopper_count(uptr)) == 0)
+ fprintf(st,"hopper empty");
+ else {
+ if (n == 1)
+ fprintf(st,"1 card");
+ else
+ fprintf(st,"%d cards",n);
+ fprintf(st," in hopper");
+ }
+ return SCPE_OK;
+}
diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h
index 1202e5cb..32e2e617 100644
--- a/SDS/sds_defs.h
+++ b/SDS/sds_defs.h
@@ -1,6 +1,6 @@
/* sds_defs.h: SDS 940 simulator definitions
- Copyright (c) 2001-2010, Robert M. Supnik
+ Copyright (c) 2001-2020, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
+ 09-Nov-20 RMS Added definitions for card reader/punch (Ken Rector)
22-May-10 RMS Added check for 64b definitions
25-Apr-03 RMS Revised for extended file support
*/
@@ -350,11 +351,13 @@ typedef struct sdsdib DIB;
#define DEV_MASK 077 /* device mask */
#define DEV_TTI 001 /* teletype */
#define DEV_PTR 004 /* paper tape rdr */
+#define DEV_CR 006 /* card punch */
#define DEV_MT 010 /* magtape */
#define DEV_RAD 026 /* fixed head disk */
#define DEV_DSK 026 /* moving head disk */
#define DEV_TTO 041 /* teletype */
#define DEV_PTP 044 /* paper tape punch */
+#define DEV_CP 046 /* card punch */
#define DEV_LPT 060 /* line printer */
#define DEV_MTS 020 /* MT scan/erase */
#define DEV_OUT 040 /* output flag */
@@ -375,6 +378,8 @@ typedef struct sdsdib DIB;
#define XFR_V_RAD 6 /* fixed hd disk */
#define XFR_V_DSK 7 /* mving hd disk */
#define XFR_V_MT0 8 /* magtape */
+#define XFR_V_CR 9 /* card reader */
+#define XFR_V_CP 10 /* card punch */
#define XFR_TTI (1 << XFR_V_TTI)
#define XFR_TTO (1 << XFR_V_TTO)
@@ -384,6 +389,8 @@ typedef struct sdsdib DIB;
#define XFR_RAD (1 << XFR_V_RAD)
#define XFR_DSK (1 << XFR_V_DSK)
#define XFR_MT0 (1 << XFR_V_MT0)
+#define XFR_CR (1 << XFR_V_CR)
+#define XFR_CP (1 << XFR_V_CP)
/* PIN/POT ordinals (0 is reserved) */
diff --git a/SDS/sds_diag.txt b/SDS/sds_diag.txt
index 6f095a7f..eb0144b6 100644
--- a/SDS/sds_diag.txt
+++ b/SDS/sds_diag.txt
@@ -111,3 +111,6 @@ Bugs
36. CPU: EOD 20000 used by diagnostic (EM change is NOP)
37. CPU: SKD sets all 24b of X, not just exponent
38. CPU: reset should not clear A, B, X
+39. LPT: carriage control position lost on spacing operation
+40. IO: TOP disconnects the channel rather than setting CHF_EOR
+41. TTY: TTO was outputing spurious extra character, even if no leader set
diff --git a/SDS/sds_io.c b/SDS/sds_io.c
index d2489b1e..a59723a7 100644
--- a/SDS/sds_io.c
+++ b/SDS/sds_io.c
@@ -1,6 +1,6 @@
/* sds_io.c: SDS 940 I/O simulator
- Copyright (c) 2001-2012, Robert M. Supnik
+ Copyright (c) 2001-2020, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
+ 01-Nov-2020 RMS Fixed overrun/underrun handling in single-word IO
+ 23-Oct-2020 RMS TOP disconnects the channel rather than setting CHF_EOR
19-Mar-2012 RMS Fixed various declarations (Mark Pizzolato)
*/
@@ -389,7 +391,7 @@ switch (mod) {
if (ch_dev & DEV_OUT) { /* to output dev? */
if (chan_cnt[ch] || (chan_flag[ch] & CHF_ILCE)) /* busy, DMA? */
chan_flag[ch] = chan_flag[ch] | CHF_TOP; /* TOP pending */
- else return dev_wreor (ch, ch_dev); /* idle, write EOR */
+ else return dev_disc (ch, ch_dev); /* idle, disconnect */
} /* end else TOP */
else if (ch_dev & DEV_MT) { /* change to scan? */
chan_uar[ch] = chan_uar[ch] | DEV_MTS; /* change dev addr */
@@ -577,7 +579,7 @@ return SCPE_OK;
IORD, IORP, IOSP: ZWC interrupt
IOSD: ZWC interrupt, EOR interrupt, disconnect
- Note that the channel can be disconnected if CHN_EOR is set, but must
+ Note that the channel can be disconnected if CHF_EOR is set, but must
not be if XFR_REQ is set */
t_stat chan_read (int32 ch)
@@ -587,20 +589,23 @@ uint32 dev = chan_uar[ch] & DEV_MASK;
uint32 tfnc = CHM_GETFNC (chan_mode[ch]);
t_stat r = SCPE_OK;
-if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */
- if (INV_DEV (dev, ch)) CRETIOP; /* can't read? */
+if ((dev != 0) && TST_XFR (dev, ch)) { /* ready to xfr? */
+ if (INV_DEV (dev, ch)) /* can't read? */
+ CRETIOP;
r = dev_dsp[dev][ch] (IO_READ, dev, &dat); /* read data */
- if (r) /* error? */
+ if ((r != 0) || (chan_cnt[ch] > chan_cpw[ch])) /* error or overrun? */
chan_flag[ch] = chan_flag[ch] | CHF_ERR;
- if (chan_flag[ch] & CHF_24B) /* 24B? */
- chan_war[ch] = dat;
- else if (chan_flag[ch] & CHF_12B) /* 12B? */
- chan_war[ch] = ((chan_war[ch] << 12) | (dat & 07777)) & DMASK;
- else chan_war[ch] = ((chan_war[ch] << 6) | (dat & 077)) & DMASK;
+ else { /* no, precess data */
+ if (chan_flag[ch] & CHF_24B) /* 24B? */
+ chan_war[ch] = dat;
+ else if (chan_flag[ch] & CHF_12B) /* 12B? */
+ chan_war[ch] = ((chan_war[ch] << 12) | (dat & 07777)) & DMASK;
+ else chan_war[ch] = ((chan_war[ch] << 6) | (dat & 077)) & DMASK;
+ }
if (chan_flag[ch] & CHF_SCAN) /* scanning? */
chan_cnt[ch] = chan_cpw[ch]; /* never full */
else chan_cnt[ch] = chan_cnt[ch] + 1; /* insert char */
- if (chan_cnt[ch] > chan_cpw[ch]) { /* full? */
+ if (chan_cnt[ch] > chan_cpw[ch]) { /* full now? */
if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */
chan_write_mem (ch); /* write to mem */
if (chan_wcr[ch] == 0) { /* wc zero? */
@@ -697,26 +702,26 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */
chan_cnt[ch] = chan_cpw[ch] + 1; /* set cnt */
}
else { /* ilce off */
- CLR_XFR (dev, ch); /* cant xfr */
- if (TST_EOR (dev)) /* EOR? */
+ if (TST_EOR (dev)) /* EOR? */
return chan_eor (ch);
chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* rate err */
- return SCPE_OK;
} /* end else ilce */
} /* end if cnt */
- chan_cnt[ch] = chan_cnt[ch] - 1; /* decr cnt */
- if (chan_flag[ch] & CHF_24B) /* 24B? */
- dat = chan_war[ch];
- else if (chan_flag[ch] & CHF_12B) { /* 12B? */
- dat = (chan_war[ch] >> 12) & 07777; /* get halfword */
- chan_war[ch] = (chan_war[ch] << 12) & DMASK; /* remove from war */
- }
- else { /* 6B */
- dat = (chan_war[ch] >> 18) & 077; /* get char */
- chan_war[ch] = (chan_war[ch] << 6) & DMASK; /* remove from war */
- }
+ if (chan_cnt[ch] != 0) { /* if not underrun */
+ chan_cnt[ch] = chan_cnt[ch] - 1; /* decr cnt */
+ if (chan_flag[ch] & CHF_24B) /* 24B? */
+ dat = chan_war[ch];
+ else if (chan_flag[ch] & CHF_12B) { /* 12B? */
+ dat = (chan_war[ch] >> 12) & 07777; /* get halfword */
+ chan_war[ch] = (chan_war[ch] << 12) & DMASK;/* remove from war */
+ }
+ else { /* 6B */
+ dat = (chan_war[ch] >> 18) & 077; /* get char */
+ chan_war[ch] = (chan_war[ch] << 6) & DMASK; /* remove from war */
+ }
+ } /* end no underrun */
r = dev_dsp[dev][ch] (IO_WRITE, dev, &dat); /* write */
- if (r) /* error? */
+ if (r != 0) /* error? */
chan_flag[ch] = chan_flag[ch] | CHF_ERR;
if (chan_cnt[ch] == 0) { /* buf empty? */
if (chan_flag[ch] & CHF_ILCE) { /* ilce on? */
@@ -737,14 +742,14 @@ if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */
} /* end if SD */
else if (!(tfnc && CHM_SGNL) || /* IORx or IOSP TOP? */
(chan_flag[ch] & CHF_TOP))
- dev_wreor (ch, dev); /* R: write EOR */
+ dev_disc (ch, dev); /* R: disconnect */
chan_flag[ch] = chan_flag[ch] & ~CHF_TOP;
} /* end else comp */
} /* end if wcr */
} /* end if ilce */
else if (chan_flag[ch] & CHF_TOP) { /* off, TOP pending? */
chan_flag[ch] = chan_flag[ch] & ~CHF_TOP; /* clear TOP */
- dev_wreor (ch, dev); /* write EOR */
+ dev_disc (ch, dev); /* disconnect */
}
else if (ion) /* no TOP, EOW intr */
int_req = int_req | int_zc[ch];
diff --git a/SDS/sds_lp.c b/SDS/sds_lp.c
index c42cbe9f..b06bdca9 100644
--- a/SDS/sds_lp.c
+++ b/SDS/sds_lp.c
@@ -244,7 +244,7 @@ if (uptr->flags & UNIT_ATT) { /* attached? */
uptr->pos = ftell (uptr->fileref); /* update position */
if (ferror (uptr->fileref)) { /* I/O error? */
lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */
- sim_perror ("LPT I/O error"); /* print msg */
+ sim_perror ("LPT I/O error"); /* print msg */
clearerr (uptr->fileref);
return SCPE_IOERR; /* ret error */
}
diff --git a/SDS/sds_mux.c b/SDS/sds_mux.c
index 189013bb..88e590c1 100644
--- a/SDS/sds_mux.c
+++ b/SDS/sds_mux.c
@@ -122,8 +122,8 @@ t_stat muxo_svc (UNIT *uptr);
t_stat mux_reset (DEVICE *dptr);
t_stat mux_attach (UNIT *uptr, CONST char *cptr);
t_stat mux_detach (UNIT *uptr);
-t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, const void *desc);
-t_stat mux_show (FILE *st, UNIT *uptr, int32 val, const void *desc);
+t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
+t_stat mux_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat mux_vlines (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
void mux_reset_ln (int32 ln);
void mux_scan_next (void);
diff --git a/SDS/sds_stddev.c b/SDS/sds_stddev.c
index 0931fc42..2d153dc8 100644
--- a/SDS/sds_stddev.c
+++ b/SDS/sds_stddev.c
@@ -1,6 +1,6 @@
/* sds_stddev.c: SDS 940 standard devices
- Copyright (c) 2001-2008, Robert M. Supnik
+ Copyright (c) 2001-2020, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -28,6 +28,7 @@
tti keyboard
tto teleprinter
+ 23-Oct-20 RMS TTO recognizes no leader flag (Ken Rector)
29-Dec-03 RMS Added console backpressure support
25-Apr-03 RMS Revised for extended file support
*/
@@ -45,6 +46,8 @@ int32 ptr_sor = 0; /* start of rec */
int32 ptr_stopioe = 0; /* no stop on err */
int32 ptp_ldr = 0; /* no leader */
int32 ptp_stopioe = 1;
+int32 tto_ldr = 0; /* no leader */
+int32 tto_retry = 0; /* retry due to stall */
DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */
t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat);
@@ -63,6 +66,7 @@ t_stat tti_reset (DEVICE *dptr);
t_stat tto (uint32 fnc, uint32 inst, uint32 *dat);
t_stat tto_svc (UNIT *uptr);
t_stat tto_reset (DEVICE *dptr);
+t_stat tto_out (int32 dat);
int8 ascii_to_sds(int8 ch);
int8 sds_to_ascii(int8 ch);
@@ -188,6 +192,8 @@ UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 6) },
{ FLDATA (XFR, xfr_req, XFR_V_TTO) },
+ { FLDATA (LDR, tto_ldr, 0) },
+ { FLDATA (RETRY, tto_retry, 0), REG_HRO },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL }
@@ -278,7 +284,7 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
sim_printf ("PTR end of file\n");
else return SCPE_OK;
}
- else sim_perror ("PTR I/O error"); /* I/O error */
+ else sim_perror ("PTR I/O error"); /* I/O error */
clearerr (ptr_unit.fileref);
return SCPE_IOERR;
}
@@ -412,7 +418,7 @@ if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */
}
if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */
ptp_set_err (); /* yes, disc, err */
- sim_perror ("PTP I/O error"); /* print msg */
+ sim_perror ("PTP I/O error"); /* print msg */
clearerr (ptp_unit.fileref);
return SCPE_IOERR;
}
@@ -503,7 +509,7 @@ if (temp & SCPE_BREAK) /* ignore break */
return SCPE_OK;
temp = temp & 0177;
tti_unit.pos = tti_unit.pos + 1;
-if (ascii_to_sds(temp) >= 0) {
+if (ascii_to_sds (temp) >= 0) {
tti_unit.buf = ascii_to_sds(temp); /* internal rep */
sim_putchar (temp); /* echo */
if (temp == '\r') /* lf after cr */
@@ -536,6 +542,9 @@ return SCPE_OK;
The typewriter output is an asynchronous streaming output device. That is,
it can never cause a channel rate error; if no data is available, it waits.
+
+ Typewriter output may be stalled, if the device is connected to a Telnet
+ connection, so the output routine must be able to try output repeatedly.
*/
t_stat tto (uint32 fnc, uint32 inst, uint32 *dat)
@@ -548,11 +557,15 @@ switch (fnc) { /* case function */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != tto_dib.chan) /* inv conn? err */
return SCPE_IERR;
+ tto_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */
+ tto_retry = 0; /* no retry */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
break;
case IO_DISC: /* disconnect */
+ tto_ldr = 0; /* clr state */
+ tto_retry = 0;
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
break;
@@ -561,7 +574,7 @@ switch (fnc) { /* case function */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
tto_unit.buf = (*dat) & 077; /* save data */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
- break;
+ return tto_out (tto_unit.buf); /* write the data */
case IO_WREOR: /* write eor */
break;
@@ -574,29 +587,47 @@ switch (fnc) { /* case function */
return SCPE_OK;
}
-/* Unit service */
+/* Unit service - handle leader, retry */
t_stat tto_svc (UNIT *uptr)
{
+if (tto_ldr != 0) { /* need leader? */
+ sim_putchar (0); /* output, no stall */
+ tto_ldr = 0; /* no more leader */
+ }
+if (tto_retry != 0) /* retry? */
+ tto_out (uptr->buf); /* try again, could stall */
+if (tto_retry == 0) /* now no retry? */
+ chan_set_ordy (tto_dib.chan); /* tto ready */
+return SCPE_OK;
+}
+
+t_stat tto_out (int32 dat)
+{
int32 asc;
t_stat r;
-if (uptr->buf == TT_CR) /* control chars? */
+tto_retry = 0; /* assume no retry */
+if (dat == TT_CR) /* control chars? */
asc = '\r';
-else if (uptr->buf == TT_BS)
+else if (dat == TT_BS)
asc = '\b';
-else if (uptr->buf == TT_TB)
+else if (dat == TT_TB)
asc = '\t';
-else asc = sds_to_ascii(uptr->buf); /* translate */
-if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */
- sim_activate (uptr, uptr->wait); /* retry */
- return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
+else asc = sds_to_ascii (dat); /* translate */
+r = sim_putchar_s (asc); /* output */
+if (r == SCPE_STALL) { /* stall? */
+ tto_retry = 1;
+ sim_activate (&tto_unit, tto_unit.wait); /* retry */
+ return SCPE_OK;
}
-uptr->pos = uptr->pos + 1; /* inc position */
+if (r != SCPE_OK) /* error? */
+ return r;
+tto_unit.pos = tto_unit.pos + 1; /* inc position */
chan_set_ordy (tto_dib.chan); /* tto rdy */
if (asc == '\r') { /* CR? */
- sim_putchar ('\n'); /* add lf */
- uptr->pos = uptr->pos + 1; /* inc position */
+ sim_putchar ('\n'); /* add lf, no stall */
+ tto_unit.pos = tto_unit.pos + 1; /* inc position */
}
return SCPE_OK;
}
@@ -607,6 +638,8 @@ t_stat tto_reset (DEVICE *dptr)
{
chan_disc (tto_dib.chan); /* disconnect */
tto_unit.buf = 0; /* clear state */
+tto_ldr = 0;
+tto_retry = 0;
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
return SCPE_OK;
diff --git a/SDS/sds_sys.c b/SDS/sds_sys.c
index 41a4f6fb..89288985 100644
--- a/SDS/sds_sys.c
+++ b/SDS/sds_sys.c
@@ -1,6 +1,6 @@
/* sds_sys.c: SDS 940 simulator interface
- Copyright (c) 2001-2016, Robert M Supnik
+ Copyright (c) 2001-2020, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
+ 01-Nov-20 RMS Fixed sds930-to-ascii entry 060 (Ken Rector)
05-May-16 RMS Fixed ascii-to-sds940 data (Mark Pizzolato)
19-Mar-12 RMS Fixed declarations of CCT arrays (Mark Pizzolato)
*/
@@ -35,6 +36,8 @@ extern DEVICE cpu_dev;
extern DEVICE chan_dev;
extern DEVICE ptr_dev;
extern DEVICE ptp_dev;
+extern DEVICE cr_dev;
+extern DEVICE cp_dev;
extern DEVICE tti_dev;
extern DEVICE tto_dev;
extern DEVICE lpt_dev;
@@ -73,6 +76,8 @@ DEVICE *sim_devices[] = {
&tti_dev,
&tto_dev,
&lpt_dev,
+ &cr_dev,
+ &cp_dev,
&rtc_dev,
&drm_dev,
&rad_dev,
@@ -114,7 +119,7 @@ const int8 sds930_to_ascii[64] = {
'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */
- '_', '/', 'S', 'T', 'U', 'V', 'W', 'X',
+ ' ', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '?', ',', '(', '~', '\\', '#' /* 72 = rec mark */
}; /* 75 = squiggle, 77 = del */
@@ -492,7 +497,8 @@ return;
}
/* Convert from SDS internal character code to ASCII depending upon cpu mode. */
-int8 sds_to_ascii(int8 ch)
+
+int8 sds_to_ascii (int8 ch)
{
ch &= 077;
if (cpu_mode == NML_MODE)
@@ -502,7 +508,8 @@ int8 sds_to_ascii(int8 ch)
}
/* Convert from ASCII to SDS internal character code depending upon cpu mode. */
-int8 ascii_to_sds(int8 ch)
+
+int8 ascii_to_sds (int8 ch)
{
ch &= 0177;
if (cpu_mode == NML_MODE)
diff --git a/Visual Studio Projects/SDS.vcproj b/Visual Studio Projects/SDS.vcproj
index 9f5fb3c8..911b860a 100644
--- a/Visual Studio Projects/SDS.vcproj
+++ b/Visual Studio Projects/SDS.vcproj
@@ -41,7 +41,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../SDS/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
+ PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_SIM_CARD"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
@@ -125,7 +125,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../SDS/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
+ PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;USE_SIM_CARD"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -195,10 +195,18 @@
RelativePath="..\scp.c"
>
+
+
+
+
@@ -235,6 +243,10 @@
RelativePath="..\SDS\sds_sys.c"
>
+
+
@@ -288,6 +300,10 @@
RelativePath="..\SDS\sds_defs.h"
>
+
+
diff --git a/descrip.mms b/descrip.mms
index d40a4ace..977814ba 100644
--- a/descrip.mms
+++ b/descrip.mms
@@ -719,7 +719,7 @@ SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB
SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\
$(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\
$(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\
- $(SDS_DIR)SDS_SYS.C
+ $(SDS_DIR)SDS_SYS.C,$(SDS_DIR)SDS_CR.C,$(SDS_DIR)SDS_CP.C
SDS_OPTIONS = /INCL=($(SIMH_DIR),$(SDS_DIR))/DEF=($(CC_DEFS))
#
diff --git a/makefile b/makefile
index 084c26d8..676d7885 100644
--- a/makefile
+++ b/makefile
@@ -1777,8 +1777,8 @@ LGP_OPT = -I ${LGPD}
SDSD = ${SIMHD}/SDS
SDS = ${SDSD}/sds_cpu.c ${SDSD}/sds_drm.c ${SDSD}/sds_dsk.c ${SDSD}/sds_io.c \
${SDSD}/sds_lp.c ${SDSD}/sds_mt.c ${SDSD}/sds_mux.c ${SDSD}/sds_rad.c \
- ${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c
-SDS_OPT = -I ${SDSD}
+ ${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c ${SDSD}/sds_cp.c ${SDSD}/sds_cr.c
+SDS_OPT = -I ${SDSD} -DUSE_SIM_CARD
SWTP6800D = ${SIMHD}/swtp6800/swtp6800