diff --git a/I1620/i1620_cd.c b/I1620/i1620_cd.c index 3faa69dc..5d93dcf7 100644 --- a/I1620/i1620_cd.c +++ b/I1620/i1620_cd.c @@ -1,6 +1,6 @@ /* i1620_cd.c: IBM 1622 card reader/punch - Copyright (c) 2002-2012, Robert M. Supnik + Copyright (c) 2002-2013, 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"), @@ -26,6 +26,8 @@ cdr 1622 card reader cdp 1622 card punch + 10-Dec-13 RMS Fixed WA card punch translations (Bob Armstrong) + Fixed card reader EOL processing (Bob Armstrong) 19-Mar-12 RMS Fixed declarations of saved_pc, io_stop (Mark Pizzolato) 19-Jan-07 RMS Set UNIT_TEXT flag 13-Jul-06 RMS Fixed card reader fgets call (Tom McBride) @@ -112,7 +114,7 @@ DEVICE cdp_dev = { */ /* Card reader (ASCII) to numeric (one digit) */ -const char cdr_to_num[128] = { +const int8 cdr_to_num[128] = { 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ -1, 0x00, 0x00, -1, -1, 0x00, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ @@ -184,11 +186,21 @@ const int8 cdr_to_alp[128] = { There is no way to punch 0-5-8 (~), 0-6-8 (\), 11-5-8 (]), 11-6-8 (;), 11-7-8 (_), 12-5-8 ([), or 12-6-8 (<) + +According to Bob Armstrong, + the FORTRAN compiler is sneaky and actually punches numeric + data (i.e. data that it knows will be read back using RNCD) + in alphameric mode with WACD. Because of that there are some + alpha to ASCII translations that absolutely MUST work out right + or otherwise we won't be able to load FORTRAN object decks. + + 50 - must "punch" as ] (flagged zero) (used to be "_") + 0A - must "punch" as | (record mark) (used to be "'") */ const int8 alp_to_cdp[256] = { ' ', -1, '?', '.', ')', -1, -1, '}', /* 00 */ - -1, -1, '\'', -1, -1, -1, -1, '"', + -1, -1, '|', -1, -1, -1, -1, '"', '+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, '-', '/', '|', ',', '(', -1, -1, -1, /* 20 */ @@ -197,7 +209,7 @@ const int8 alp_to_cdp[256] = { -1, -1, '|', -1, -1, -1, -1, '"', -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ 'H', 'I', -1, -1, -1, -1, -1, -1, - '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ + ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ 'Q', 'R', '?', '=', -1, -1, -1, '}', -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ 'Y', 'Z', '|', ',', -1, -1, -1, -1, @@ -279,7 +291,12 @@ switch (op) { /* case on op */ return sta; } -/* Fill card reader buffer - all errors are hard errors */ +/* Fill card reader buffer - all errors are hard errors + + As Bob Armstrong pointed out, this routines needs to account + for variants in text file formats, which may terminate lines + with cr-lf (Windows), lf (UNIX), or cr (Mac). +*/ t_stat cdr_read (void) { @@ -302,6 +319,22 @@ if (ferror (cdr_unit.fileref)) { /* error? */ clearerr (cdr_unit.fileref); return SCPE_IOERR; } +if ((i = strlen (cdr_buf)) > 0) { /* anything at all? */ + if (cdr_buf[i-1] == '\n') { /* line end in \n? */ + cdr_buf[i-1] = 0; /* remove it */ + } + else if (cdr_buf[i-1] == '\r') { /* line end in \r? */ + cdr_buf[i-1] = 0; /* remove it */ + cdr_unit.pos = ftell (cdr_unit.fileref); /* save position */ + if (fgetc (cdr_unit.fileref) != '\n') /* next char not \n? */ + fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); /* then rewind */ + } + else { /* line too long */ + ind[IN_RDCHK] = 1; + perror ("CDR line too long"); + return SCPE_IOERR; + } + } cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ getc (cdr_unit.fileref); /* see if more */ if (feof (cdr_unit.fileref)) /* eof? set last */ @@ -362,7 +395,7 @@ uint8 z, d; switch (op) { /* decode op */ case OP_DN: - return cdp_num (pa, 20000 - (pa % 20000), TRUE); /* dump numeric */ + return cdp_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */ case OP_WN: return cdp_num (pa, CD_LEN, FALSE); /* write numeric */ @@ -404,7 +437,8 @@ while (ncd-- >= 0) { /* until done */ break; for (i = 0; i < len; i++) { /* one card */ d = M[pa] & (FLAG | DIGIT); /* get char */ - if (dump && (d == FLAG)) cdc = '-'; /* dump? F+0 is diff */ + if (dump && (d == FLAG)) /* dump? F+0 is diff */ + cdc = '-'; else cdc = num_to_cdp[d]; /* translate */ if (cdc < 0) { /* bad char? */ ind[IN_WRCHK] = 1; /* set write check */ diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index 5ef99843..343ddc02 100644 --- a/I1620/i1620_cpu.c +++ b/I1620/i1620_cpu.c @@ -1,6 +1,6 @@ /* i1620_cpu.c: IBM 1620 CPU simulator - Copyright (c) 2002-2008, Robert M. Supnik + Copyright (c) 2002-2013, 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"), @@ -26,7 +26,9 @@ This CPU module incorporates code and comments from the 1620 simulator by Geoff Kuenning, with his permission. - 28-May-06 RMS Fixed bug in cpu history Peter Schorn) + 10-Dec-13 RMS Fixed several bugs in add and compare (Bob Armstrong) + Fixed handling of P field in K instruction (Bob Armstrong) + 28-May-06 RMS Fixed bug in cpu history (Peter Schorn) 22-Sep-05 RMS Fixed declarations (Sterling Garwood) 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Nov-04 RMS Added instruction history @@ -291,7 +293,7 @@ const int32 op_table[100] = { IF_VPA + IF_VQA, /* TR */ IF_VPA, /* SF */ IF_VPA, /* CF */ - IF_VPA, /* K */ + 0, /* K */ IF_VPA, /* DN */ IF_VPA, /* RN */ IF_VPA, /* RA */ @@ -384,6 +386,21 @@ t_stat (*iodisp[NUM_IO])(uint32 op, uint32 pa, uint32 f0, uint32 f1) = { NULL, NULL, NULL, NULL, NULL }; +/* K instruction validate P field table */ + +const uint8 k_valid_p[NUM_IO] = { + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + /* Indicator table: -1 = illegal, +1 = resets when tested */ const int32 ind_table[NUM_IND] = { @@ -687,11 +704,12 @@ while (reason == 0) { /* loop until halted */ reason = STOP_OVERFL; break; +/* IBM's diagnostics try a compare that generates a carry out; it does not + generate overflow. Therefore, do not set overflow on a carry out status. */ + case OP_C: case OP_CM: reason = add_field (PAR, QAR, TRUE, FALSE, 0, &sta); /* sub, nostore */ - if (sta == ADD_CARRY) /* cout => ovflo */ - ind[IN_OVF] = 1; if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; break; @@ -703,7 +721,7 @@ while (reason == 0) { /* loop until halted */ reason = mul_field (PAR, QAR); /* multiply */ break; -/* IO instructions - P is valid */ +/* IO instructions - P is valid, except for K */ case OP_RA: case OP_WA: @@ -711,7 +729,6 @@ while (reason == 0) { /* loop until halted */ reason = STOP_INVEAD; /* stop */ break; } - case OP_K: case OP_DN: case OP_RN: case OP_WN: @@ -723,6 +740,21 @@ while (reason == 0) { /* loop until halted */ else reason = iodisp[dev] (op, PAR, f0, f1); /* call device */ break; + case OP_K: + dev = get_2d (ADDR_A (saved_PC, I_IO)); /* get IO dev */ + if (k_valid_p[dev]) { /* validate P? */ + reason = get_addr (pla, 5, TRUE, &PAR); /* get P addr */ + if (reason != SCPE_OK) /* stop if error */ + break; + } + else PAR = 0; + f0 = M[ADDR_A (saved_PC, I_CTL)] & DIGIT; /* get function */ + f1 = M[ADDR_A (saved_PC, I_CTL + 1)] & DIGIT; + if ((dev < 0) || (iodisp[dev] == NULL)) /* undefined dev? */ + reason = STOP_INVIO; /* stop */ + else reason = iodisp[dev] (op, PAR, f0, f1); /* call device */ + break; + /* Divide special feature instructions */ case OP_LD: @@ -1296,7 +1328,8 @@ return SCPE_OK; Reference Manual: "When the sum is zero, the sign of the P field is retained." -*/ + + Bob Armstrong: record marks are treated by add as though they were zero */ t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 *sta) { @@ -1312,6 +1345,10 @@ ind[IN_EZ] = 1; /* assume zero */ dst = M[d] & DIGIT; /* 1st digits */ src = M[s] & DIGIT; +if (dst == REC_MARK) /* chk for rec mark */ + dst = 0; +if (src == REC_MARK) + src = 0; if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ return STOP_INVDIG; if (comp) /* complement? */ @@ -1322,11 +1359,15 @@ if (sto) /* store */ MM (d); MM (s); /* decr mem addrs */ do { dst = M[d] & DIGIT; /* get dst digit */ + if (dst == REC_MARK) + dst = 0; dst_f = M[d] & FLAG; /* get dst flag */ if (src_f) /* src done? src = 0 */ src = 0; else { src = M[s] & DIGIT; /* get src digit */ + if (src == REC_MARK) + src = 0; if (cnt >= skp) /* get src flag */ src_f = M[s] & FLAG; MM (s); /* decr src addr */ @@ -1344,12 +1385,18 @@ do { } while (dst_f == 0); /* until dst done */ if (!src_f) /* !src done? ovf */ ind[IN_OVF] = 1; + +/* Because recomplement is done (model 1) with table lookup, the first digit + must be explicitly 10s complemented, and not 9s complemented with a carry + in of 1. (Bob Armstrong) */ + if (comp && !cry && !ind[IN_EZ]) { /* recomp needed? */ ind[IN_HP] = ind[IN_HP] ^ 1; /* flip indicator */ if (sto) { /* storing? */ - for (cry = 1, dp = dsv; dp != d; ) { /* rescan */ + for (cry = 0, dp = dsv; dp != d; ) { /* rescan */ dst = M[dp] & DIGIT; /* get dst digit */ - res = add_one_digit (9 - dst, 0, &cry); /* "add" */ + dst = (dp == dsv)? (10 - dst): (9 - dst); /* 10 or 9s comp */ + res = add_one_digit (0, dst, &cry); /* "add" */ M[dp] = (M[dp] & FLAG) | res; /* store */ MM (dp); /* decr dst addr */ } @@ -1371,7 +1418,8 @@ uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry) { uint32 res; -if (*cry) src = src + 1; /* cry in? incr src */ +if (*cry) /* cry in? incr src */ + src = src + 1; if (src >= 10) { /* src > 10? */ src = src - 10; /* src -= 10 */ *cry = 1; /* carry out */ diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c index 4254bf09..147b8e8e 100644 --- a/I1620/i1620_lp.c +++ b/I1620/i1620_lp.c @@ -1,6 +1,6 @@ /* i1620_lp.c: IBM 1443 line printer simulator - Copyright (c) 2002-2008, Robert M. Supnik + Copyright (c) 2002-2013, 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"), @@ -25,6 +25,8 @@ lpt 1443 line printer + 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) + Fixed test on VFU 10 (Bob Armstrong) 19-Jan-07 RMS Added UNIT_TEXT flag 21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility 29-Dec-03 RMS Fixed bug in scheduling @@ -56,7 +58,7 @@ t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); t_stat lpt_attach (UNIT *uptr, char *cptr); void lpt_buf_init (void); -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1); +t_stat lpt_num (uint32 pa, uint32 len, uint32 f1, t_bool dump); t_stat lpt_print (void); t_stat lpt_space (int32 lines, int32 lflag); @@ -169,10 +171,10 @@ switch (op) { /* decode op */ break; case OP_DN: - return lpt_num (pa, 20000 - (pa % 20000), f1); /* dump numeric */ + return lpt_num (pa, 20000 - (pa % 20000), f1, TRUE); /* dump numeric */ case OP_WN: - return lpt_num (pa, 0, f1); /* write numeric */ + return lpt_num (pa, 0, f1, FALSE); /* write numeric */ case OP_WA: for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ @@ -205,18 +207,16 @@ return SCPE_OK; /* Print numeric */ -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1) +t_stat lpt_num (uint32 pa, uint32 len, uint32 f1, t_bool dump) { -uint32 end; uint8 d; int8 lpc; t_stat r, sta; sta = SCPE_OK; -end = pa + len; for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ d = M[pa]; /* get digit */ - if (len? (pa >= end): /* end reached? */ + if (dump? (len-- == 0): /* end reached? */ ((d & REC_MARK) == REC_MARK)) break; lpc = num_to_lpt[d]; /* translate */ @@ -270,7 +270,7 @@ lpt_savctrl = 0x61; /* reset ctrl */ if ((ctrl & K_LIN) == ((ctrl & K_IMM)? 0: K_LIN)) /* space lines? */ return lpt_space (ctrl & K_LCNT, FALSE); chan = lpt_savctrl & K_CHAN; /* basic chan */ -if (lpt_savctrl & K_CH10) { /* chan 10-12? */ +if ((lpt_savctrl & K_CH10) == 0) { /* chan 10-12? */ if (chan == 0) chan = 10; else if (chan == 3) diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c index 88323ade..a16dacfd 100644 --- a/I1620/i1620_pt.c +++ b/I1620/i1620_pt.c @@ -1,6 +1,6 @@ /* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator - Copyright (c) 2002-2012, Robert M Supnik + Copyright (c) 2002-2013, 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"), @@ -26,6 +26,8 @@ ptr 1621 paper tape reader ptp 1624 paper tape punch + 21-Dec-13 RMS Fixed translation of paper tape code X0C + 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) 19-Mar-12 RMS Fixed declaration of io_stop (Mark Pizzolato) 21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility 25-Apr-03 RMS Revised for extended file support @@ -49,7 +51,7 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr); t_stat ptr_read (uint8 *c, t_bool ignfeed); t_stat ptp_reset (DEVICE *dptr); t_stat ptp_write (uint32 c); -t_stat ptp_num (uint32 pa, uint32 len); +t_stat ptp_num (uint32 pa, uint32 len, t_bool dump); /* PTR data structures @@ -129,7 +131,7 @@ const int8 ptr_to_num[128] = { 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XO */ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XOC */ + 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XOC */ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F }; @@ -212,7 +214,7 @@ const int8 alp_to_ptp[256] = { t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1) { -uint32 i; +uint32 i, q = 0; int8 mc; uint8 ptc; t_stat r, sta; @@ -229,6 +231,8 @@ switch (op) { /* case on op */ M[pa] = REC_MARK; /* store rec mark */ return sta; /* done */ } + if (pa == 18976) + q++; if (bad_par[ptc]) { /* bad parity? */ ind[IN_RDCHK] = 1; /* set read check */ if (io_stop) /* set return status */ @@ -389,10 +393,10 @@ t_stat r; switch (op) { /* decode op */ case OP_DN: - return ptp_num (pa, 20000 - (pa % 20000)); /* dump numeric */ + return ptp_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */ case OP_WN: - return ptp_num (pa, 0); /* punch numeric */ + return ptp_num (pa, 0, FALSE); /* punch numeric */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ @@ -456,16 +460,15 @@ return STOP_RWRAP; /* Punch tape numeric - cannot generate parity errors */ -t_stat ptp_num (uint32 pa, uint32 len) +t_stat ptp_num (uint32 pa, uint32 len, t_bool dump) { t_stat r; uint8 d; -uint32 i, end; +uint32 i; -end = pa + len; for (i = 0; i < MEMSIZE; i++) { /* stop runaway */ d = M[pa] & (FLAG | DIGIT); /* get char */ - if (len? (pa >= end): /* dump: end reached? */ + if (dump? (len-- == 0): /* dump: end reached? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ return ptp_write (PT_EL); /* end record */ r = ptp_write (num_to_ptp[d]); /* write */ diff --git a/I1620/i1620_sys.c b/I1620/i1620_sys.c index e9c501b0..c25e9052 100644 --- a/I1620/i1620_sys.c +++ b/I1620/i1620_sys.c @@ -394,7 +394,7 @@ if (opcode[i].str == NULL) if (I_GETQP (opfl) == I_M_QNP) /* Q no print? */ qmp = 0; -fprintf (of, "%s", opcode[i].str); /* print opcode */ +fprintf (of, "%s", opcode[i].str); /* print opcode */ if (I_GETPP (opfl) == I_M_PP) /* P required? */ fprint_addr (of, ' ', &val[I_P], I_M_QX); else if ((I_GETPP (opfl) == I_M_PCP) && (pmp || qmp)) /* P opt & needed? */ diff --git a/I1620/i1620_tty.c b/I1620/i1620_tty.c index ac4a1021..aefa0ba5 100644 --- a/I1620/i1620_tty.c +++ b/I1620/i1620_tty.c @@ -1,6 +1,6 @@ /* i1620_tty.c: IBM 1620 typewriter - Copyright (c) 2002-2008, Robert M. Supnik + Copyright (c) 2002-2014, 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"), @@ -25,6 +25,8 @@ tty console typewriter + 02-Jan-14 RMS Added variable tab stops + 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) 21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility 22-Dec-02 RMS Added break test */ @@ -34,6 +36,19 @@ #define TTO_COLMAX 80 int32 tto_col = 0; +uint8 tto_tabs[TTO_COLMAX + 1] = { + 0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1 +}; extern uint8 M[MAXMEMSIZE]; extern uint8 ind[NUM_IND]; @@ -44,10 +59,11 @@ void tti_unlock (void); t_stat tti_rnum (int8 *c); t_stat tti_ralp (int8 *c); t_stat tti_read (int8 *c); -t_stat tto_num (uint32 pa, uint32 len); +t_stat tto_num (uint32 pa, uint32 len, t_bool dump); t_stat tto_write (uint32 c); t_stat tty_svc (UNIT *uptr); t_stat tty_reset (DEVICE *dptr); +t_stat tty_set_fixtabs (UNIT *uptr, int32 val, char *cptr, void *desc); /* TTY data structures @@ -64,8 +80,20 @@ REG tty_reg[] = { { NULL } }; +MTAB tty_mod[] = { + { MTAB_XTD|MTAB_VDV, TTO_COLMAX, NULL, "TABS", + &sim_tt_settabs, NULL, (void *) tto_tabs }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, TTO_COLMAX, "TABS", NULL, + NULL, &sim_tt_showtabs, (void *) tto_tabs }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOTABS", + &tty_set_fixtabs, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 8, NULL, "DEFAULTTABS", + &tty_set_fixtabs, NULL, NULL }, + { 0 } + }; + DEVICE tty_dev = { - "TTY", &tty_unit, tty_reg, NULL, + "TTY", &tty_unit, tty_reg, tty_mod, 1, 10, 31, 1, 8, 7, NULL, NULL, &tty_reset, NULL, NULL, NULL @@ -214,10 +242,10 @@ switch (op) { /* case on op */ break; case OP_DN: - return tto_num (pa, 20000 - (pa % 20000)); /* dump numeric */ + return tto_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */ case OP_WN: - return tto_num (pa, 0); /* type numeric */ + return tto_num (pa, 0, FALSE); /* type numeric */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ @@ -307,16 +335,15 @@ return SCPE_OK; /* Write numerically - cannot generate parity errors */ -t_stat tto_num (uint32 pa, uint32 len) +t_stat tto_num (uint32 pa, uint32 len, t_bool dump) { t_stat r; uint8 d; -uint32 i, end; +uint32 i; -end = pa + len; for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ d = M[pa]; /* get char */ - if (len? (pa >= end): /* dump: end reached? */ + if (dump? (len-- == 0): /* dump: end reached? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ return SCPE_OK; /* end operation */ if (d & FLAG) /* flag? */ @@ -336,23 +363,23 @@ t_stat tto_write (uint32 c) int32 rpt; if (c == '\t') { /* tab? */ - rpt = 8 - (tto_col % 8); /* distance to next */ - tto_col = tto_col + rpt; /* tab over */ - while (rpt-- > 0) /* use spaces */ - sim_putchar (' '); - return SCPE_OK; + for (rpt = tto_col + 1; /* find tab stop */ + (tto_tabs[rpt] == 0) && (rpt <= TTO_COLMAX); + rpt++) ; + for ( ; tto_col < rpt; tto_col++) + sim_putchar (' '); /* use spaces */ } -if (c == '\r') { /* return? */ +else if (c == '\r') { /* return? */ sim_putchar ('\r'); /* crlf */ sim_putchar ('\n'); tto_col = 0; /* clear colcnt */ return SCPE_OK; } -if ((c == '\n') || (c == 007)) { /* non-spacing? */ +else if ((c == '\n') || (c == 007)) { /* non-spacing? */ sim_putchar (c); return SCPE_OK; } -if (c == '\b') /* backspace? */ +else if (c == '\b') /* backspace? */ tto_col = tto_col? tto_col - 1: 0; else tto_col++; /* normal */ if (tto_col > TTO_COLMAX) { /* line wrap? */ @@ -360,7 +387,8 @@ if (tto_col > TTO_COLMAX) { /* line wrap? */ sim_putchar ('\n'); tto_col = 0; } -sim_putchar (c); +if (c != '\t') + sim_putchar (c); return SCPE_OK; } @@ -382,6 +410,7 @@ t_stat tty_reset (DEVICE *dptr) { sim_activate (&tty_unit, tty_unit.wait); /* activate poll */ tto_col = 0; +tto_tabs[TTO_COLMAX] = 1; /* tab stop at limit */ return SCPE_OK; } @@ -392,3 +421,17 @@ void tti_unlock (void) tto_write ('>'); return; } + +/* Set tab stops at fixed modulus */ + +t_stat tty_set_fixtabs (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 i; + +for (i = 0; i < TTO_COLMAX; i++) { + if ((val != 0) && (i != 0) && ((i % val) == 0)) + tto_tabs[i] = 1; + else tto_tabs[i] = 0; + } +return SCPE_OK; +} diff --git a/doc/i1620_doc.doc b/doc/i1620_doc.doc index bdb40704..cee20c37 100644 Binary files a/doc/i1620_doc.doc and b/doc/i1620_doc.doc differ diff --git a/sim_console.c b/sim_console.c index f861ffdc..deff8c36 100644 --- a/sim_console.c +++ b/sim_console.c @@ -1,6 +1,6 @@ /* sim_console.c: simulator console I/O library - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2014, 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. + 02-Jan-14 RMS Added tab stop routines 18-Mar-12 RMS Removed unused reference to sim_switches (Dave Bryan) 07-Dec-11 MP Added sim_ttisatty to support reasonable behaviour (i.e. avoid in infinite loop) in the main command input @@ -75,7 +76,7 @@ 01-Feb-02 RMS Added VAX fix (Robert Alan Byer) 19-Sep-01 RMS More MacOS changes 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 20-Jul-01 RMS Added Macintosh support (Louis Chretien, Peter Schorn, Ben Supnik) + 20-Jul-01 RMS Added MacOS support (Louis Chretien, Peter Schorn, Ben Supnik) 15-May-01 RMS Added logging support 05-Mar-01 RMS Added clock calibration support 08-Dec-00 BKR Added OS/2 support (Bruce Ray) @@ -1599,6 +1600,59 @@ else c = c & 0377; return c; } +/* Tab stop array handling + + *desc points to a uint8 array of length val + + Columns with tabs set are non-zero; columns without tabs are 0 */ + +t_stat sim_tt_settabs (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +uint8 *temptabs, *tabs = (uint8 *) desc; +int32 i, d; +t_stat r; +char gbuf[CBUFSIZE]; + +if ((cptr == NULL) || (tabs == NULL) || (val <= 1)) + return SCPE_IERR; +if (*cptr == 0) + return SCPE_2FARG; +if ((temptabs = (uint8 *)malloc (val)) == NULL) + return SCPE_MEM; +for (i = 0; i < val; i++) + temptabs[i] = 0; +do { + cptr = get_glyph (cptr, gbuf, ';'); + d = get_uint (gbuf, 10, val, &r); + if ((r != SCPE_OK) || (d == 0)) { + free (temptabs); + return SCPE_ARG; + } + temptabs[d - 1] = 1; + } while (*cptr != 0); +for (i = 0; i < val; i++) + tabs[i] = temptabs[i]; +free (temptabs); +return SCPE_OK; +} + +t_stat sim_tt_showtabs (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +uint8 *tabs = (uint8 *) desc; +int32 i, any; + +if ((st == NULL) || (val == 0) || (desc == NULL)) + return SCPE_IERR; +for (i = any = 0; i < val; i++) { + if (tabs[i] != 0) { + fprintf (st, (any? ";%d": "%d"), i + 1); + any = 1; + } + } +fprintf (st, (any? "\n": "no tabs set\n")); +return SCPE_OK; +} + #if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) extern pthread_mutex_t sim_tmxr_poll_lock; diff --git a/sim_console.h b/sim_console.h index f33e31ec..a9d02290 100644 --- a/sim_console.h +++ b/sim_console.h @@ -1,6 +1,6 @@ /* sim_console.h: simulator console I/O library headers - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2014, 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. + 02-Jan-14 RMS Added tab stop routines 17-Jan-11 MP Added buffered line capabilities 22-Jun-06 RMS Implemented SET/SHOW PCHAR 22-Nov-05 RMS Added central input/output conversion support @@ -92,6 +93,8 @@ t_stat sim_ttclose (void); t_bool sim_ttisatty (void); int32 sim_tt_inpcvt (int32 c, uint32 mode); int32 sim_tt_outcvt (int32 c, uint32 mode); +t_stat sim_tt_settabs (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat sim_tt_showtabs (FILE *st, UNIT *uptr, int32 val, void *desc); extern int32 sim_int_char; /* interrupt character */ extern int32 sim_brk_char; /* break character */