- Integration with updated sim_card API - Addition of MT (Mag Tape) device - Addition of DSK (Disk) device - Build time simulator test
1555 lines
65 KiB
C
1555 lines
65 KiB
C
/* i650_cdp.c: IBM 650 Card punch.
|
|
|
|
Copyright (c) 2018, Roberto Sancho
|
|
|
|
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
|
|
ROBERTO SANCHO 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.
|
|
|
|
This is the standard card punch.
|
|
|
|
These units each buffer one record in local memory and signal
|
|
ready when the buffer is full or empty. The channel must be
|
|
ready to recieve/transmit data when they are activated since
|
|
they will transfer their block during chan_cmd. All data is
|
|
transmitted as BCD characters.
|
|
|
|
*/
|
|
|
|
#include "i650_defs.h"
|
|
#include "sim_card.h"
|
|
|
|
#define UNIT_CDP UNIT_ATTABLE | MODE_026 | MODE_LOWER
|
|
|
|
/* std devices. data structures
|
|
|
|
cdp_dev Card Punch device descriptor
|
|
cdp_unit Card Punch unit descriptor
|
|
cdp_reg Card Punch register list
|
|
cdp_mod Card Punch modifiers list
|
|
*/
|
|
|
|
uint32 cdp_cmd(UNIT *, uint16, uint16);
|
|
t_stat cdp_srv(UNIT *);
|
|
t_stat cdp_reset(DEVICE *);
|
|
t_stat cdp_attach(UNIT *, CONST char *);
|
|
t_stat cdp_detach(UNIT *);
|
|
t_stat cdp_help(FILE *, DEVICE *, UNIT *, int32, const char *);
|
|
const char *cdp_description(DEVICE *dptr);
|
|
t_stat cdp_set_wiring (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat cdp_show_wiring (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
t_stat cdp_set_echo (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat cdp_show_echo (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
|
|
UNIT cdp_unit[4] = {
|
|
{UDATA(cdp_srv, UNIT_CDP, 0), 600}, // unit 0 is the printing mechanism of 407
|
|
{UDATA(cdp_srv, UNIT_CDP, 0), 600},
|
|
{UDATA(cdp_srv, UNIT_CDP, 0), 600},
|
|
{UDATA(cdp_srv, UNIT_CDP, 0), 600},
|
|
};
|
|
|
|
MTAB cdp_mod[] = {
|
|
{MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", &sim_card_set_fmt, &sim_card_show_fmt, NULL, "Set card format"},
|
|
{MTAB_XTD | MTAB_VUN, 0, "WIRING", "WIRING", &cdp_set_wiring, &cdp_show_wiring, NULL, "Set card punch/print control panel Wiring"},
|
|
{MTAB_XTD | MTAB_VUN, 0, "ECHO", "ECHO", &cdp_set_echo, &cdp_show_echo, NULL, "Set console printout for punched cards"},
|
|
{MTAB_XTD | MTAB_VUN, 1, "PRINT", "PRINT", &cdp_set_echo, &cdp_show_echo, NULL, "Set printout on CDP0 unit for punched cards"},
|
|
{0}
|
|
};
|
|
|
|
DEVICE cdp_dev = {
|
|
"CDP", cdp_unit, NULL, cdp_mod,
|
|
4, 8, 15, 1, 8, 8,
|
|
NULL, NULL, NULL, NULL, &cdp_attach, &cdp_detach,
|
|
&cdp_dib, DEV_DISABLE | DEV_DEBUG, 0, crd_debug,
|
|
NULL, NULL, &cdp_help, NULL, NULL, &cdp_description
|
|
};
|
|
|
|
// vars where card is encoded for punching
|
|
char card_buf[120];
|
|
int card_nbuf;
|
|
|
|
// vars where card is encoded for printing
|
|
char card_lpt[120];
|
|
int card_nlpt;
|
|
|
|
void encode_char(int cPunch, int cLpt)
|
|
{
|
|
if ((cPunch) && (card_nbuf < 80)) {
|
|
card_buf[card_nbuf++] = cPunch;
|
|
}
|
|
if ((cLpt) && (card_nlpt < 120)) {
|
|
card_lpt[card_nlpt++] = cLpt;
|
|
}
|
|
}
|
|
|
|
void encode_lpt_spc(int nSpaces)
|
|
{
|
|
while (nSpaces-- >0) encode_char(0, 32);
|
|
}
|
|
|
|
void encode_lpt_str(const char * buf)
|
|
{
|
|
while (*buf) encode_char(0, *buf++);
|
|
}
|
|
|
|
void encode_lpt_num(t_int64 d, int l)
|
|
{
|
|
char s[20];
|
|
int i,n;
|
|
char pad;
|
|
|
|
if (l < 0) {
|
|
l=-l; pad = ' '; // if l < 0 pad with space
|
|
} else {
|
|
pad = '0'; // if l > 0 pag with zero
|
|
}
|
|
d=AbsWord(d);
|
|
for (i=9;i>=0;i--) {
|
|
n = (int) (d % 10);
|
|
d = d / 10;
|
|
s[i] = '0' + n;
|
|
}
|
|
s[10] = 0;
|
|
if (pad == ' ') {
|
|
for(i=0;i<9;i++) {
|
|
if (s[i] != '0') break;
|
|
s[i] = ' ';
|
|
}
|
|
}
|
|
encode_lpt_str(&s[10-l]);
|
|
}
|
|
|
|
#define wf_NNNNNNNNNNs 0
|
|
#define wf_NN_NNNN_NNNNs 1
|
|
#define wf_sN_NNNNNNN_NN 3
|
|
#define wf_sN_NNN_NNN_NNN 4
|
|
#define wf_nnnnnnnnnNs 5
|
|
#define wf_nnnnnnnnnH 6
|
|
#define wf_NNNNNNNNNN 7
|
|
#define wf_sNNNNNNNNNN 8
|
|
|
|
void encode_lpt_word(t_int64 d, int NegZero, int wFormat)
|
|
{
|
|
int n;
|
|
int neg=0;
|
|
|
|
if (d < 0) {d=-d; neg=1;} else if ((d==0) && (NegZero)) neg=1;
|
|
if (wFormat == wf_NN_NNNN_NNNNs) {
|
|
n = Shift_Digits(&d, 2); encode_lpt_num(n, 2); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 4); encode_lpt_num(n, 4); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 4); encode_lpt_num(n, 4);
|
|
encode_char(0, neg ? '-':' ');
|
|
} else if (wFormat == wf_sN_NNNNNNN_NN) {
|
|
encode_char(0, neg ? '-':'+');
|
|
n = Shift_Digits(&d, 1); encode_lpt_num(n, 1); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 7); encode_lpt_num(n, 7); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 2); encode_lpt_num(n, 2);
|
|
} else if (wFormat == wf_sN_NNN_NNN_NNN) {
|
|
encode_char(0, neg ? '-':'+');
|
|
n = Shift_Digits(&d, 1); encode_lpt_num(n, 1); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 3); encode_lpt_num(n, 3); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 3); encode_lpt_num(n, 3); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 3); encode_lpt_num(n, 3);
|
|
} else if (wFormat == wf_nnnnnnnnnNs) {
|
|
encode_lpt_num(d,-10); // replace leading zeroes by spaces
|
|
encode_char(0, neg ? '-':' ');
|
|
} else if (wFormat == wf_nnnnnnnnnH) {
|
|
if (d < 10) {
|
|
encode_lpt_spc(9);
|
|
} else {
|
|
encode_lpt_num(d / 10, -9); // print 9 digits, replacing leading zeroes by spaces
|
|
}
|
|
n = d % 10;
|
|
encode_char(0, (n==0) ? '+':'A'+n-1); // hi punch on last digit
|
|
} else if (wFormat == wf_NNNNNNNNNN) {
|
|
encode_lpt_num(d,10);
|
|
} else if (wFormat == wf_sNNNNNNNNNN) {
|
|
encode_char(0, neg ? '-':'+');
|
|
encode_lpt_num(d,10);
|
|
} else { // default: wFormat == wf_NNNNNNNNNNs
|
|
encode_lpt_num(d,10);
|
|
encode_char(0, neg ? '-':' ');
|
|
}
|
|
}
|
|
|
|
// set pch_word[10] with encoded word d.
|
|
// if d negative, sign on last digit (units digit)
|
|
// if bSetHiPuch=1, set HiPunch on last digit.
|
|
// if bSetHiPuch=2, set HiPunch on last digit and on second digit.
|
|
// if bSetHiPuch=3, set HiPunch on third digit
|
|
// if last digit is negative, never set HiPunch even if asked for (a card column cannot have both X(11) and Y(12) punched)
|
|
void sprintf_word(char * pch_word, t_int64 d, int NegZero, int bSetHiPuch)
|
|
{
|
|
int i,n,neg, hi;
|
|
|
|
if (d < 0) {
|
|
neg = 1;
|
|
d = -d;
|
|
} else if ((d == 0) && (NegZero)) {
|
|
neg = 1; // Negative Zero -> also puncho X(11) on last 0 digit
|
|
} else {
|
|
neg = 0;
|
|
}
|
|
for (i=9;i>=0;i--) {
|
|
hi = 0;
|
|
if ((i==1) && (bSetHiPuch == 2)) hi = 1; // Set Hi Punch on second digit
|
|
if ((i==2) && (bSetHiPuch == 3)) hi = 1; // Set Hi Punch on third digit
|
|
if ((i==9) && ( (bSetHiPuch == 1) || (bSetHiPuch == 2) ) && (neg == 0)) hi = 1; // Set Hi Punch on last digit (units digit)
|
|
n = (int) (d % 10);
|
|
d = d / 10;
|
|
n = n + hi * 10;
|
|
if ((neg == 1) && (i==9)) n = n + 20; // Set negative punch X(11) on last digit
|
|
pch_word[i] = digits_ascii[n];
|
|
}
|
|
pch_word[10] = 0;
|
|
}
|
|
|
|
void encode_pch_str(const char * buf)
|
|
{
|
|
while (*buf) {
|
|
encode_char(*buf++, 0);
|
|
}
|
|
}
|
|
|
|
|
|
void encode_8word_wiring(void)
|
|
{
|
|
// encode 8 numerical words per card
|
|
// get the decoded data from IOSync
|
|
int i, NegZero;
|
|
t_int64 d;
|
|
char pch_word[20];
|
|
|
|
// punch card
|
|
for(i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
sprintf_word(pch_word, d, NegZero, 0);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
|
|
// print out card contents
|
|
// 8 words in format NN NNNN NNNN+
|
|
for(i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
encode_lpt_word(d, NegZero, wf_NN_NNNN_NNNNs);
|
|
encode_lpt_spc(1);
|
|
}
|
|
}
|
|
|
|
void encode_soap_wiring(int bMultiPass)
|
|
{
|
|
// encode soap card simulating soap control panel wiring for 533
|
|
// from SOAP II manual at http://www.bitsavers.org/pdf/ibm/650/24-4000-0_SOAPII.pdf
|
|
// storage in output block
|
|
// +-------------------+
|
|
// Word 1977: | <- Location -> | Alphabetic
|
|
// 1978: | <- Data Addr -> | Alphabetic
|
|
// 1979: | <- Inst Addr -> | Alphabetic
|
|
// +-+-+-|-+-+-|-+-|-+-|
|
|
// 1980: | Op Code |DTg|ITg| Alphabetic
|
|
// +-+-+-|-+-+-|-+-|-+-|
|
|
// 1981: | <- Remarks -> | Alphabetic
|
|
// 1982: | <- Remarks -> | Alphabetic
|
|
// 1983: |<-Assembled Instr->|
|
|
// +-+-|-+-+-+-|-+-+-|-|
|
|
// 1984: | |N N N N| |T| N N N N=Location, T=Type (0 if Blank)
|
|
// 1985: | |N N N N| N N N N=Card Number
|
|
// 1986: |a|b|c|d|e|f|g|h|i|j| punch control word
|
|
// a = 0/8 (for non blank type) =0 -> bank LOC,OP etc
|
|
// b = 0/8 (negative)
|
|
// c = 0/8 (bypass)
|
|
// d = 0/8 (punch a) =8 -> do not print Loc op da ir
|
|
// e = 0/8 (punch b) =8 -> punch availability table
|
|
// f = 0/8 (800X instruction)
|
|
// g = 0/8 (blank out L)
|
|
// h = 0/8 (blank out D)
|
|
// i = 0/8 (blank out I)
|
|
// j = 0/8 (blank out OP)
|
|
//
|
|
// SOAP printout format
|
|
// | Sg | Location | OpCode | Data Addr | Tg | Instr Addr | Tg | Remarks | Drum Addr | NN NNNN NNNN[-] (signed word value at this drum addr)
|
|
// SOAP punch format (load card, 1 word per card)
|
|
// simulates punching over prepunched 1-word load card
|
|
// | word1 | nnnn | 24 addr 800? | NNNNNNNNNN | source soap line
|
|
// nnnn=card number
|
|
// addr=drum address where the word is loaded
|
|
// NNNNNNNNNN=word to be loaded at addr, with sign in last digit
|
|
//
|
|
// If MultiPass flag set,
|
|
// e = 0/8 (punch b) =8 -> punch availability table OR punch 5/CD card
|
|
// if word1 start by 01 is 5/CD card
|
|
// if word1 start by 00 is an availability card
|
|
//
|
|
// SOAPIIA 5 word per card (5/CD) punch format
|
|
// | word 1 | word 2 | word 3 | word 4 | word 5 | word 6 | word 7 | word 8 |
|
|
// | 01 AAAA NNNN | first | second | third | fourth | fifth | location of intructions |
|
|
// | instruction | instruction | instruction | instruction | instruction | 1 2 3 | 4 5 |
|
|
// AAAA=ident | NNNN NNNN NN|NN NNNN NNNN |
|
|
// NNNN=card num
|
|
//
|
|
// SOAPIIA 5 word per card printout format
|
|
// | 01 | AAAA | NNNN | word 1 | word 2 | word 3 | word 4 | word 5 | NNNN | NNNN | NNNN | NNNN | NNNN |
|
|
// word1 word2 word3 word4 word5 location
|
|
//
|
|
|
|
char loc[6], data_addr[6], inst_addr[6], OpCode[6], Data_Tag[6], Instr_Tag[6], rem1[6], rem2[6];
|
|
char pch_word[20];
|
|
t_int64 d, instr;
|
|
int location, CardNum, ty;
|
|
int b_non_blank, neg, b_blk_op, b_blk_i, b_blk_d, b_blk_l, b_800X, b_pch_b, b_pch_a, b_bypass, b_5cd; // punch control flags
|
|
int i, sv_card_nbuf, n, NegZero;
|
|
int pat1, pat2;
|
|
|
|
word_to_ascii(loc, 1, 5, IOSync[0]);
|
|
word_to_ascii(data_addr, 1, 5, IOSync[1]);
|
|
word_to_ascii(inst_addr, 1, 5, IOSync[2]);
|
|
word_to_ascii(OpCode, 1, 3, IOSync[3]);
|
|
word_to_ascii(Data_Tag, 4, 1, IOSync[3]);
|
|
word_to_ascii(Instr_Tag, 5, 1, IOSync[3]);
|
|
word_to_ascii(rem1, 1, 5, IOSync[4]);
|
|
word_to_ascii(rem2, 1, 5, IOSync[5]);
|
|
instr = IOSync[6];
|
|
location = (int) ((IOSync[7] / D4) % D4);
|
|
ty = (int) ( IOSync[7] % 10);
|
|
CardNum = (int) ( IOSync[8] % D4);
|
|
d = IOSync[9];
|
|
b_blk_op = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_blk_i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_blk_d = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_blk_l = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_800X = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_pch_b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_pch_a = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_bypass = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
neg = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_non_blank = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
|
|
// printf("bits %06d%04d%c ", printfw(IOSync[9])); // to echo the control word of punched card
|
|
|
|
if ((bMultiPass) && (b_pch_b) && (IOSync[0] / D8 == 01)) {
|
|
b_5cd = 1;
|
|
} else {
|
|
b_5cd = 0;
|
|
}
|
|
|
|
if ((ty==1) || (ty==2)) b_pch_a=1; // card types 1 or 2 punch non generating code card
|
|
|
|
// generate card
|
|
if (b_pch_b) {
|
|
// punch 5 words per card format or
|
|
// punch availability table (pat pseudo-op output)
|
|
for(i=0;i<8;i++) {
|
|
sprintf_word(pch_word, IOSync[i], 0, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else {
|
|
if (b_pch_a) {
|
|
// punch non generating code card
|
|
encode_pch_str("0?0000800?"); // load card
|
|
sprintf(pch_word, " %04d", CardNum); // card number
|
|
encode_pch_str(pch_word);
|
|
encode_pch_str(" "); // two blank words
|
|
encode_pch_str(" ");
|
|
} else {
|
|
// punch generating code card
|
|
if (b_800X) {
|
|
encode_pch_str("6I1954800?"); // load card for word to be stored in 800X addr
|
|
} else {
|
|
encode_pch_str("6I1954195C"); // load card for word to be stored in drum
|
|
}
|
|
sprintf(pch_word, " %04d", CardNum); // card number
|
|
encode_pch_str(pch_word);
|
|
sprintf(pch_word, "24%04d800?", location);// addr to place the loaded word
|
|
encode_pch_str(pch_word);
|
|
sprintf_word(pch_word, AbsWord(instr) * (neg ? -1:1), ((neg) && (instr == 0)) ? 1:0, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
encode_char(ty == 0 ? ' ' : '0'+ty, 0);
|
|
encode_char(neg ? '-' : ' ', 0);
|
|
sv_card_nbuf = card_nbuf; // save pch bufer current pos
|
|
encode_pch_str(loc); encode_pch_str(OpCode);
|
|
encode_pch_str(data_addr); encode_pch_str(Data_Tag);
|
|
encode_pch_str(inst_addr); encode_pch_str(Instr_Tag);
|
|
encode_pch_str(rem1); encode_pch_str(rem2);
|
|
// convert to lowercase for punching
|
|
for (i=sv_card_nbuf;i<card_nbuf;i++)
|
|
if ((card_buf[i] >= 'A') && (card_buf[i] <= 'Z'))
|
|
card_buf[i] = card_buf[i] - 'A' + 'a';
|
|
card_buf[card_nbuf] = 0;
|
|
}
|
|
|
|
// generate printout
|
|
if (b_pch_b) {
|
|
if (b_5cd) {
|
|
// print 5 words per card format or
|
|
d = IOSync[0];
|
|
pat1 = (int) ((d / D4) % D4);
|
|
pat2 = (int) ( d % D4);
|
|
encode_lpt_num(01, 2); // print 01
|
|
encode_lpt_spc(1);
|
|
encode_lpt_num(pat1, 4); // print AAAA
|
|
encode_lpt_spc(1);
|
|
encode_lpt_num(pat2, 4); // print NNNN
|
|
encode_lpt_spc(1);
|
|
for(i=1;i<=5;i++) { // print 5 words as NNNNNNNNNs
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
encode_lpt_word(d, NegZero, wf_NNNNNNNNNNs);
|
|
}
|
|
encode_lpt_spc(1); // print locations of words as NNNN NNNN NNNN NNNN NNNN
|
|
d = IOSync[6];
|
|
for(i=1;i<=5;i++) {
|
|
n = Shift_Digits(&d, 4);
|
|
if (i==3) {
|
|
d = IOSync[7];
|
|
n = n + Shift_Digits(&d, 2);
|
|
}
|
|
encode_lpt_num(n, 4);
|
|
encode_lpt_spc(1);
|
|
}
|
|
} else {
|
|
// print availability table (pat pseudo-op output)
|
|
for(i=0; i<4; i++) {
|
|
d = IOSync[i*2];
|
|
pat1 = (int) ((d / D4) % D4);
|
|
pat2 = (int) ( d % D4);
|
|
d = IOSync[i*2 + 1];
|
|
encode_lpt_num(pat1, 4);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(d, 10);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(pat2, 4);
|
|
encode_lpt_spc(5);
|
|
}
|
|
}
|
|
} else if ((ty == 1) || (ty == 5)) {
|
|
// print comment for card type 1 (SOAP II) or type 5 (SOAP modified for IT)
|
|
encode_char(0, '0' + ty);
|
|
encode_lpt_spc(14);
|
|
encode_lpt_str(loc); encode_lpt_str(OpCode);
|
|
encode_lpt_str(data_addr); encode_lpt_str(Data_Tag);
|
|
encode_lpt_str(inst_addr); encode_lpt_str(Instr_Tag);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2);
|
|
} else {
|
|
if (ty == 0) {
|
|
encode_lpt_spc(1);
|
|
} else {
|
|
encode_char(0, '0' + ty);
|
|
}
|
|
encode_lpt_str(loc);
|
|
encode_lpt_spc(2); encode_char(0, neg ? '-':' '); encode_lpt_spc(1);
|
|
encode_lpt_str(OpCode); encode_lpt_spc(3);
|
|
encode_lpt_str(data_addr); encode_lpt_str(Data_Tag); encode_lpt_spc(2);
|
|
encode_lpt_str(inst_addr); encode_lpt_str(Instr_Tag); encode_lpt_spc(5);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2);
|
|
if (b_pch_a) {
|
|
// blank op -> do not print location and intruction
|
|
if (b_bypass) {
|
|
encode_lpt_spc(4);
|
|
encode_lpt_str("BYPASS");
|
|
}
|
|
} else {
|
|
encode_lpt_spc(4);
|
|
if (b_blk_l) { encode_lpt_spc(4); } else encode_lpt_num(location, 4);
|
|
encode_lpt_spc(2); encode_char(0, neg ? '-':' '); encode_lpt_spc(1);
|
|
d = instr;
|
|
n = Shift_Digits(&d, 2); // operation code (2 digits)
|
|
if (b_blk_op) { encode_lpt_spc(2); } else encode_lpt_num(n, 2);
|
|
encode_lpt_spc(2);
|
|
n = Shift_Digits(&d, 4); // data addr (4 digits)
|
|
if (b_blk_d) { encode_lpt_spc(4); } else encode_lpt_num(n, 4);
|
|
encode_lpt_spc(2);
|
|
n = Shift_Digits(&d, 4); // instr addr (4 digits)
|
|
if (b_blk_i) { encode_lpt_spc(4); } else encode_lpt_num(n, 4);
|
|
encode_lpt_spc(1);
|
|
if (b_blk_l) encode_lpt_str("BLANK L"); else
|
|
if (b_blk_op) encode_lpt_str("BLANK OP"); else
|
|
if (b_blk_d) encode_lpt_str("BLANK D"); else
|
|
if (b_blk_i) encode_lpt_str("BLANK I");
|
|
}
|
|
}
|
|
}
|
|
|
|
void encode_supersoap_wiring()
|
|
{
|
|
// encode soap card simulating soap control panel wiring for 533
|
|
// storage in output block (one card format)
|
|
// +-------------------+
|
|
// Word 9040: | <- Location -> | Alphabetic
|
|
// 9041: | <- Data Addr -> | Alphabetic
|
|
// 9042: | <- Inst Addr -> | Alphabetic
|
|
// +-+-+-|-+-+-|-+-|-+-|
|
|
// 9043: | Op Code |DTg|ITg| Alphabetic
|
|
// +-+-+-|-+-+-|-+-|-+-|
|
|
// 9044: | <- Remarks -> | Alphabetic
|
|
// 9045: | <- Remarks -> | Alphabetic
|
|
// 9046: |<-Assembled Instr->|
|
|
// +-+-|-+-+-+-|-+-+-|-|
|
|
// 9047: | |N N N N| |T| N N N N=Location, T=Type (0 if Blank)
|
|
// 9048: | n n n n |N N N N| N N N N=Card Number, n n n n = location2
|
|
// 9049: |a| | |d|e| |g| | |j| punch control word
|
|
// a =8 -> bank LOC OP etc, =0 -> punch LOC2 LOC1 OP etc =7 -> PAT card
|
|
// b
|
|
// c =8 -> 8 words
|
|
// d =8 -> five words per card
|
|
// e =9 -> positive, =8 -> negative
|
|
// f
|
|
// g =8 -> ???
|
|
// h
|
|
// i
|
|
// j =4 -> punch 8004
|
|
//
|
|
// SOAP printout format
|
|
// | Sg | Location | OpCode | Data Addr | Tg | Instr Addr | Tg | Remarks | Drum Addr | NN NNNN NNNN[-] (signed word value at this drum addr)
|
|
// SOAP punch format (load card, 1 word per card)
|
|
// simulates punching over prepunched 1-word load card
|
|
// | word1 | nnnn | 24 addr 800? | NNNNNNNNNN | source soap line
|
|
// nnnn=card number
|
|
// addr=drum address where the word is loaded
|
|
// NNNNNNNNNN=word to be loaded at addr, with sign in last digit
|
|
//
|
|
// SuperSoap five word per card (FIV) punch format
|
|
// | word 1 | word 2 | word 3 | word 4 | word 5 | word 6 | word 7 | word 8 |
|
|
// | 888888 NNNN | fifth | fourth | third | second | first | location of intructions |
|
|
// | instruction | instruction | instruction | instruction | instruction | 5 4 3 | 2 1 |
|
|
// NNNN=card num | NNNN NNNN NN|NN NNNN NNNN |
|
|
//
|
|
//
|
|
// SuperSoap five word per card printout format
|
|
// | 88888 | NNNN | word 5 | word 4 | word 3 | word 2 | word 1 | NNNN | NNNN | NNNN | NNNN | NNNN |
|
|
// word5 word4 word3 word2 word1 location
|
|
//
|
|
|
|
char loc[6], data_addr[6], inst_addr[6], OpCode[6], Data_Tag[6], Instr_Tag[6], rem1[6], rem2[6];
|
|
char pch_word[20];
|
|
t_int64 d, instr;
|
|
int location, location2, CardNum, ty, opcodeNum;
|
|
int b_blank, neg, b4, fiv, b_8word; // punch control flags
|
|
int i, sv_card_nbuf, n, NegZero;
|
|
int pat1, pat2;
|
|
char cardtype;
|
|
|
|
word_to_ascii(loc, 1, 5, IOSync[0]);
|
|
word_to_ascii(data_addr, 1, 5, IOSync[1]);
|
|
word_to_ascii(inst_addr, 1, 5, IOSync[2]);
|
|
word_to_ascii(OpCode, 1, 3, IOSync[3]);
|
|
word_to_ascii(Data_Tag, 4, 1, IOSync[3]);
|
|
word_to_ascii(Instr_Tag, 5, 1, IOSync[3]);
|
|
word_to_ascii(rem1, 1, 5, IOSync[4]);
|
|
word_to_ascii(rem2, 1, 5, IOSync[5]);
|
|
instr = IOSync[6];
|
|
location = (int) ((IOSync[7] / D4) % D4);
|
|
ty = (int) ( IOSync[7] % 10);
|
|
CardNum = (int) ( IOSync[8] % D4);
|
|
location2 = (int) ( (IOSync[8] / (10*D4)) % D4);
|
|
d = IOSync[9];
|
|
|
|
b4 = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
neg = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
fiv = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_8word = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
i = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_blank = (int) (d % 10); d = d / 10;
|
|
|
|
opcodeNum = (int) (IOSync[3] / D4); // origina ibm650 char opcode
|
|
|
|
if (b_blank==7) {
|
|
cardtype = 'P'; // punch availability table card PAT
|
|
} else if (fiv) {
|
|
cardtype = '5'; // punch five words per card
|
|
} else if (b_8word) {
|
|
cardtype = '8'; // punch 8-words load binary card
|
|
} else if ((b_blank) || (ty==1) || (ty==3)) {
|
|
//XXX missing PAL output,
|
|
cardtype = 'A'; // comment card
|
|
} else if ((ty==2) || (ty==4) || ((location >= 8000) && (location <= 8009))) {
|
|
cardtype = 'B'; // 800X card
|
|
} else {
|
|
//XXX missing PLR, FIL in one-per-card form, FIL in five-per-card form, DEK
|
|
cardtype = 'C'; // regular code card
|
|
}
|
|
|
|
// generate card
|
|
if (cardtype=='P') {
|
|
// punch availability table (pat pseudo-op output)
|
|
for(i=0;i<8;i++) {
|
|
sprintf_word(pch_word, IOSync[i], 0, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else if (cardtype=='8') {
|
|
// punch 8-words load binary card
|
|
for(i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
sprintf_word(pch_word, d, NegZero, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else if (cardtype=='5') {
|
|
// punch five-per-card per card format
|
|
sprintf(pch_word, "888888%04d", (int)(IOSync[8] % D4)); // punch six 8's, then the card number
|
|
encode_pch_str(pch_word);
|
|
for(i=1;i<6;i++) {
|
|
sprintf_word(pch_word, IOSync[i], 0, 1); // sign on units
|
|
encode_pch_str(pch_word);
|
|
}
|
|
sprintf_word(pch_word, IOSync[6], 0, 0); // locations -> no sign
|
|
encode_pch_str(pch_word);
|
|
sprintf_word(pch_word, IOSync[7], 0, 0);
|
|
encode_pch_str(pch_word);
|
|
} else {
|
|
// cardtype A, B or C
|
|
if (cardtype=='A') {
|
|
encode_pch_str("?000008000"); // punch non generating code card
|
|
} else if (cardtype=='B') {
|
|
encode_pch_str("F919548000"); // punch for 800X locations
|
|
} else {
|
|
encode_pch_str("F919541953"); // punch for load card
|
|
}
|
|
if ((ty!=1) && (ty!=3) && ((opcodeNum==647963) || (opcodeNum==637664))) {
|
|
sprintf(pch_word, " %s%04d", loc, CardNum); // card DRC or COD
|
|
} else {
|
|
sprintf(pch_word, " %04d", CardNum); // consecutive card count
|
|
}
|
|
encode_pch_str(pch_word);
|
|
if (cardtype=='A') {
|
|
encode_pch_str(" ");
|
|
encode_pch_str(" ");
|
|
} else {
|
|
sprintf(pch_word, "24%04d800?", location);// addr to place the loaded word
|
|
encode_pch_str(pch_word);
|
|
sprintf_word(pch_word, AbsWord(instr) * (neg ? -1:1), ((neg) && (instr == 0)) ? 1:0, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
// input reproduced
|
|
encode_char(ty == 0 ? ' ' : '0'+ty, 0);
|
|
encode_char(neg ? '-' : ' ', 0);
|
|
sv_card_nbuf = card_nbuf; // save pch bufer current pos
|
|
encode_pch_str(loc); encode_pch_str(OpCode);
|
|
encode_pch_str(data_addr); encode_pch_str(Data_Tag);
|
|
encode_pch_str(inst_addr); encode_pch_str(Instr_Tag);
|
|
encode_pch_str(rem1); encode_pch_str(rem2);
|
|
// convert to lowercase for punching
|
|
for (i=sv_card_nbuf;i<card_nbuf;i++)
|
|
if ((card_buf[i] >= 'A') && (card_buf[i] <= 'Z'))
|
|
card_buf[i] = card_buf[i] - 'A' + 'a';
|
|
}
|
|
card_buf[card_nbuf] = 0;
|
|
|
|
// generate printout
|
|
if (cardtype=='5') {
|
|
// print five words per card format
|
|
encode_lpt_str("888888 ");
|
|
encode_lpt_num((int)(IOSync[8] % D4), 4); // card number
|
|
encode_lpt_spc(1);
|
|
for(i=1;i<=5;i++) { // print 5 words as NNNNNNNNNs
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
encode_lpt_word(d, NegZero, wf_NNNNNNNNNNs);
|
|
}
|
|
encode_lpt_spc(1); // print locations of words as NNNN NNNN NNNN NNNN NNNN
|
|
d = IOSync[6];
|
|
for(i=1;i<=5;i++) {
|
|
n = Shift_Digits(&d, 4);
|
|
if (i==3) {
|
|
d = IOSync[7];
|
|
n = n + Shift_Digits(&d, 2);
|
|
}
|
|
encode_lpt_num(n, 4);
|
|
encode_lpt_spc(1);
|
|
}
|
|
} else if (cardtype=='8') {
|
|
// punch 8-words load binary card
|
|
// print out card contents 8 words in format NN NNNN NNNN+
|
|
for(i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
encode_lpt_word(d, NegZero, wf_sNNNNNNNNNN);
|
|
encode_lpt_spc(2);
|
|
}
|
|
} else if (cardtype=='P') {
|
|
// print availability table (pat pseudo-op output)
|
|
for(i=0; i<4; i++) {
|
|
d = IOSync[i*2];
|
|
pat1 = (int) ((d / D4) % D4);
|
|
pat2 = (int) ( d % D4);
|
|
d = IOSync[i*2 + 1];
|
|
encode_lpt_num(pat1, 4);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(d, 10);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(pat2, 4);
|
|
encode_lpt_spc(5);
|
|
}
|
|
} else {
|
|
encode_lpt_num(CardNum, 4);
|
|
encode_lpt_spc(3);
|
|
if (ty == 1) {
|
|
// print comment card type 1
|
|
encode_lpt_str("1 ");
|
|
encode_lpt_str(loc); encode_lpt_str(OpCode);
|
|
encode_lpt_str(data_addr); encode_lpt_str(Data_Tag);
|
|
encode_lpt_str(inst_addr); encode_lpt_str(Instr_Tag);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2);
|
|
} else {
|
|
if (ty == 0) {
|
|
encode_lpt_spc(1);
|
|
} else {
|
|
encode_char(0, '0' + ty);
|
|
}
|
|
encode_lpt_spc(2); encode_char(0, neg ? '-':' '); encode_lpt_spc(1);
|
|
encode_lpt_str(loc); encode_lpt_spc(2);
|
|
encode_lpt_str(OpCode); encode_lpt_spc(2);
|
|
encode_lpt_str(data_addr); encode_lpt_str(Data_Tag); encode_lpt_spc(1);
|
|
encode_lpt_str(inst_addr); encode_lpt_str(Instr_Tag); encode_lpt_spc(3);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2); encode_lpt_spc(4);
|
|
if (b_blank) {
|
|
// blank loc opcode data_addr instr_addr
|
|
} else {
|
|
if (location2!=location) {
|
|
encode_lpt_num(location2, 4);
|
|
} else {
|
|
encode_lpt_spc(4);
|
|
}
|
|
encode_lpt_spc(1);
|
|
encode_lpt_num(location, 4); encode_lpt_spc(2);
|
|
encode_char(0, neg ? '-':'+');
|
|
d = instr;
|
|
n = Shift_Digits(&d, 2); // operation code (2 digits)
|
|
encode_lpt_num(n, 2); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 4); // data addr (4 digits)
|
|
encode_lpt_num(n, 4); encode_lpt_spc(1);
|
|
n = Shift_Digits(&d, 4); // instr addr (4 digits)
|
|
encode_lpt_num(n, 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void encode_is_wiring(void)
|
|
{
|
|
// encode Floationg Decimal Interpretive System (IS) card simulating control panel wiring for 533 as described
|
|
// in manual at http://www.bitsavers.org/pdf/ibm/650/28-4024_FltDecIntrpSys
|
|
// storage in output block
|
|
// +-+-+-+-+-+-|-+-+-+-|
|
|
// Word 1977: |Trc|N N N N| | Location
|
|
// 1978: | |N N N N| | Word Count
|
|
// +-------------------+
|
|
// 1979: | word1 |
|
|
// 1980: | word2 |
|
|
// 1981: | word3 |
|
|
// 1982: | word4 |
|
|
// 1983: | word5 |
|
|
// 1984: | word6 |
|
|
// +-------------------+
|
|
// 1985: | Problem Number |
|
|
// 1986: | |N N N N| | Card Number
|
|
// +-------------------+
|
|
//
|
|
// if word at 1977 is negative, a load card is punched, but no printout is generated
|
|
// if word at 1977 is positive, regular output card format is used on punch
|
|
// Column: 1 2 3 4 | 5 6 | 7 8 9 | 10 | 11 | 12 - 21 | 22 | 23 - 32 | 33 | 34 - 43 | 44 | 45 - 54 | 55 | 56 - 65 | 66 | 67 - 76 | 77 78 79 | 80
|
|
// Card | | | Location | wc | s1 | Word1 | s2 | Word2 | s3 | Word3 | s4 | Word4 | s5 | Word5 | s6 | Word6 | Problem |
|
|
// Num | if location is > 9999, will use column 6 Num
|
|
// wordN is printed as +N NNNNNNN NN (IT sci notation)
|
|
//
|
|
// IT printout format for non tracing cards:
|
|
// | Location | Word1 | Word2 | Word3 | Word4 | Word5 | Word6
|
|
// wordN is printed as +N NNNNNNN NN (IT sci notation)
|
|
//
|
|
// IT printout format for tracing cards (Trc digits in word 1977 are non-zero):
|
|
// | Location | Word1 | Word2 | Word3 | Word4 | Word5 | Word6
|
|
// word1 to 3 are printed as +N NNN NNN NNN (IT instruction format)
|
|
// word4 to 6 are printed as +N NNNNNNN NN (IT sci notation)
|
|
//
|
|
int i, NegZero;
|
|
t_int64 d;
|
|
int CardNum, loc, wc, PrNum, bTraceCard;
|
|
char pch_word[20];
|
|
int bSetHiPunch;
|
|
|
|
bSetHiPunch = (IOSync[0] < 0) ? 2 : 0; // first bSetHiPunch is 2 if word negative (signals a load card must be punched)
|
|
|
|
loc = (int) ((IOSync[0] / D4) % D4);
|
|
CardNum = (int) ((IOSync[9] / D4) % D4);
|
|
wc = (int) ((IOSync[1] / D4) % D4);
|
|
PrNum = (int) ( IOSync[8]);
|
|
bTraceCard = (IOSync[0] / D8) > 0 ? 1 : 0; // if to higher digits are nonzero -> is a trace card
|
|
|
|
if (bSetHiPunch) {
|
|
// punch a load card
|
|
for(i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
if ((i==0) && (d < 0)) d = -d; // get absolute value for IOSync[0]
|
|
sprintf_word(pch_word, d, NegZero, bSetHiPunch);
|
|
if (bSetHiPunch==2) bSetHiPunch = 1; // if bSetHiPunch is 2 change it to bSetHiPunch = 1
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else {
|
|
// punch a card using output format
|
|
if (loc < 1000) {
|
|
sprintf(pch_word, "%04d %03d%01d", CardNum, loc, wc);
|
|
} else {
|
|
sprintf(pch_word, "%04d %04d%01d", CardNum, loc, wc);
|
|
}
|
|
encode_pch_str(pch_word);
|
|
for(i=0;i<6;i++) {
|
|
if (i<wc) {
|
|
d = IOSync[i+2];
|
|
NegZero = IOSync_NegativeZeroFlag[i+2];
|
|
if ((d < 0) || ((d==0) && (NegZero))) {
|
|
encode_pch_str("-");
|
|
d = -d;
|
|
} else {
|
|
encode_pch_str("+");
|
|
}
|
|
sprintf_word(pch_word, d, 0, 0);
|
|
encode_pch_str(pch_word);
|
|
} else {
|
|
encode_pch_str(" "); // 11 spaces
|
|
}
|
|
}
|
|
if (PrNum < 0) PrNum = 0;
|
|
if (PrNum > 999) PrNum = 999;
|
|
sprintf(pch_word, "%03d", PrNum);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
|
|
if (bSetHiPunch) {
|
|
// load card, does not generate printout
|
|
// mark lpt output buffer to not print
|
|
if (card_nlpt == 0) {
|
|
card_lpt[card_nlpt++] = 0;
|
|
}
|
|
} else {
|
|
// not load card -> do normal printout for card
|
|
if (wc > 6) wc = 6;
|
|
if (loc < 1000) {
|
|
encode_lpt_spc(1);
|
|
encode_lpt_num(loc, 3);
|
|
} else {
|
|
encode_lpt_num(loc, 4);
|
|
}
|
|
for(i=2;i<2+wc;i++) {
|
|
encode_lpt_spc(2);
|
|
d = IOSync[i];
|
|
NegZero = IOSync_NegativeZeroFlag[i];
|
|
if ((bTraceCard) && (i<5)) {
|
|
// if printing a trace card, first three words are printed as intructions (+N NNN NNN NNN)
|
|
encode_lpt_word(d, NegZero, wf_sN_NNN_NNN_NNN);
|
|
} else {
|
|
// print numbers adding spaces to ease reading IT floating point format (+N NNNNNNN NN)
|
|
encode_lpt_word(d, NegZero, wf_sN_NNNNNNN_NN);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void encode_it_wiring(void)
|
|
{
|
|
// encode card for IT compiler modified soap
|
|
// from IT manual at http://www.bitsavers.org/pdf/ibm/650/CarnegieInternalTranslator.pdf
|
|
// storage in output block
|
|
// +-------------------+
|
|
// Word 1977: | <- Loc. Label -> | Alphabetic
|
|
// 1978: | <- Op Code -> | Alphabetic
|
|
// 1979: | <- Data Addr -> | Alphabetic
|
|
// 1980: | <- Inst Addr -> | Alphabetic
|
|
// 1981: | <- Remarks -> | Alphabetic
|
|
// 1982: | <- Remarks -> | Alphabetic
|
|
// +-------------------+
|
|
// 1983: | | Not Used
|
|
// 1984: | | Not Used
|
|
// +-------------------+
|
|
// 1985: | |N N N N| | N N N N=Card Number
|
|
// 1986: |a|b|c|d|e|f|g|h|i|j| a = 0/8 =8 -> reservation card
|
|
// b = 0/8 (regional setting) =0 -> card type 3, =8 -> card type 4
|
|
// c = 0/8
|
|
// d = 0/8 =8 -> negative value
|
|
// e = 0/8
|
|
// f = 0/8
|
|
// g = 0/8 =8 -> punching a PIT card
|
|
// h = 0/8 =8 -> type 1 data out format
|
|
// i = 0/8
|
|
// j = 0/8
|
|
//
|
|
// SIT printout format
|
|
// | Card Num | Ty | Location | Sg | OpCode | Data Addr | Instr Addr | Remarks
|
|
// SIT punch format is SOAP source card format
|
|
// Column: 41 | 42 | 43 44 45 46 47 | 48 49 50 | 51 52 53 54 55 | 56 | 57 58 59 60 61 | 62 | 63 64 65 66 67 68 69 70 71 72
|
|
// Ty | Sg | Location | OpCode | Data Addr | | Instr Addr | | Remarks
|
|
//
|
|
// Ty = Type = blank, 3 or 4 (regional setting)
|
|
// Sg = sign = blank or -
|
|
//
|
|
// If word 1986 contains 8 in digit h, it is a type 1 data out card format
|
|
// +----+------+-------+
|
|
// Word 1977: | VV | +NNN | SSSS | IT variable 1
|
|
// 1978: | Word |
|
|
// +-------------------+
|
|
// 1979: | | IT variable 2 (zero if none)
|
|
// 1980: | |
|
|
// +-------------------+
|
|
// 1981: | | IT variable 3
|
|
// 1982: | |
|
|
// +-------------------+
|
|
// 1983: | | IT variable 4
|
|
// 1984: | |
|
|
// +-------------------+
|
|
// 1985: | | Not used
|
|
// 1986: |8|0|0|0|0|0|8|8|0|0| control word for type 1 data out card
|
|
//
|
|
// VV = IT variable being punched: 01 -> I type, 02 -> Y type, 03 -> C type
|
|
// + N N N = variable number (I5 -> 01 0005). + means zoro with Y(12) overpunch
|
|
// S S S S = statement number of IT source program where TYPE command that generates the card is
|
|
// Word = value from IT variable. If type I, is an integer. If type C or Y
|
|
// type is word is float (M MMMMMMM EE -> M=mantisa, EE=exponent)
|
|
// can be is negative (X(11) overpunch in last digit)
|
|
// up to 4 pairs var-word per card
|
|
// leading zeroes of each word are replaced by spaces
|
|
|
|
char pch_word[20];
|
|
char loc[6], data_addr[6], inst_addr[6], OpCode[6], rem1[6], rem2[6];
|
|
t_int64 d;
|
|
int CardNum, ty;
|
|
int b, neg, b_pit, b_reg, b_resv, b_data; // punch control flags
|
|
int i;
|
|
|
|
word_to_ascii(loc, 1, 5, IOSync[0]);
|
|
word_to_ascii(OpCode, 1, 3, IOSync[1]);
|
|
word_to_ascii(data_addr, 1, 5, IOSync[2]);
|
|
word_to_ascii(inst_addr, 1, 5, IOSync[3]);
|
|
word_to_ascii(rem1, 1, 5, IOSync[4]);
|
|
word_to_ascii(rem2, 1, 5, IOSync[5]);
|
|
CardNum = (int) ((IOSync[8] / D4) % D4);
|
|
d = IOSync[9];
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_data = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_pit = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
neg = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_reg = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_resv = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
|
|
// printf("bits %06d%04d%c ", printfw(IOSync[9])); // to echo the control word of punched card
|
|
|
|
// generate card
|
|
if (b_data) {
|
|
// punch type 1 data out card
|
|
for (i=0;i<4;i++) {
|
|
sprintf_word(pch_word, IOSync[i*2+0], 0, (i==0) ? 3:0); // punch variable name
|
|
encode_pch_str(pch_word);
|
|
sprintf_word(pch_word, IOSync[i*2+1], 0, (i==0) ? 3:0); // punch variable value
|
|
encode_pch_str(pch_word);
|
|
if (IOSync[i*2+2] == 0) break; // if next word is zero, no more variables to punch
|
|
}
|
|
} else {
|
|
// punch SOAP source instruction
|
|
for(i=0;i<40;i++) encode_pch_str(" "); // leave 40 first columns blank
|
|
if (b_resv) {
|
|
if (b_reg) {
|
|
ty = 4;
|
|
} else {
|
|
ty = 3;
|
|
}
|
|
} else {
|
|
ty = 0;
|
|
}
|
|
encode_char(ty == 0 ? ' ' : '0'+ty, 0);
|
|
encode_char(neg == 0 ? ' ' : '-', 0);
|
|
encode_pch_str(loc);
|
|
encode_pch_str(OpCode);
|
|
encode_pch_str(data_addr);
|
|
encode_pch_str(" ");
|
|
encode_pch_str(inst_addr);
|
|
encode_pch_str(" ");
|
|
encode_pch_str(rem1);
|
|
encode_pch_str(rem2);
|
|
// convert to lowercase for punching
|
|
for (i=40;i<card_nbuf;i++)
|
|
if ((card_buf[i] >= 'A') && (card_buf[i] <= 'Z'))
|
|
card_buf[i] = card_buf[i] - 'A' + 'a';
|
|
card_buf[card_nbuf] = 0;
|
|
}
|
|
|
|
// generate printout
|
|
if (b_data) {
|
|
// print type 1 data out card. replace leading zeroes by spaces on each word
|
|
for (i=0;i<4;i++) {
|
|
encode_lpt_word(IOSync[i*2+0], 0, wf_nnnnnnnnnNs); // print variable name
|
|
encode_lpt_spc(1);
|
|
encode_lpt_word(IOSync[i*2+1], 0, wf_nnnnnnnnnNs); // print variable value
|
|
encode_lpt_spc(1);
|
|
if (IOSync[i*2+2] == 0) break; // if next word is zero, no more variables to punch
|
|
}
|
|
} else {
|
|
// print generated soap source listing
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(CardNum, -4);
|
|
encode_lpt_spc(2);
|
|
encode_char(0, ty == 0 ? ' ' : '0'+ty);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_str(loc);
|
|
encode_lpt_spc(2); encode_char(0, neg ? '-':' '); encode_lpt_spc(1);
|
|
encode_lpt_str(OpCode); encode_lpt_spc(3);
|
|
encode_lpt_str(data_addr); encode_lpt_spc(1); encode_lpt_spc(2);
|
|
encode_lpt_str(inst_addr); encode_lpt_spc(6);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2);
|
|
}
|
|
}
|
|
|
|
void encode_ra_wiring(void)
|
|
{
|
|
// encode card for Missile Systems Division, Lockheed Aircraft Corporation
|
|
// regional assembly card - five load cards
|
|
// storage in output block
|
|
// +-------------------+
|
|
// Word 0977: | XX AAAA XXXX | Address A1 (X=don't care)
|
|
// 0978: | NN NNNN NNNN | word 1
|
|
// 0979: | XX AAAA XXXX | Address A2
|
|
// 0980: | NN NNNN NNNN | word 2
|
|
// 0981: | XX AAAA XXXX | Address A3
|
|
// 0982: | NN NNNN NNNN | word 3
|
|
// 0983: | XX AAAA XXXX | Address A4
|
|
// 0984: | NN NNNN NNNN | word 4
|
|
// 0985: | XX AAAA XXXX | Address A5
|
|
// 0986: | NN NNNN NNNN | word 5
|
|
// +-------------------+
|
|
//
|
|
// punch card format
|
|
//
|
|
// Column: | 1 2 3 4 - 10 | 11 - 14 | 15 16 | 17 - 20 | 21 - 24 | 25 - 28 | 29 30 | 31 - 34 | 35 - 38 | 39 - 42 | 43 44 | 45 - 48 | 49 - 52 | 53 - 56 | 57 58 | 59 - 62 | 63 - 66 | 67 - 70 | 71 72 | 73 - 76 | 77 - 80 |
|
|
// | + | N N N N | N N | N N N N | N N N N | N N N N | N N | N N N N | N N N N | N N N N | N N | N N N N | N N N N | N N N N | N N | N N N N | N N N N | N N N N | N N | N N N N | N N N N |
|
|
// | Addr | Op | Data | Instr | Addr | Op | Data | Instr | Addr | Op | Data | Instr | Addr | Op | Data | Instr | Addr | Op | Data | Instr |
|
|
// | Location| Code | Addr | Addr | Location| Code | Addr | Addr | Location| Code | Addr | Addr | Location| Code | Addr | Addr | Location| Code | Addr | Addr |
|
|
// | (A1) (O1) (D1) (I1) | (A2) (O2) (D2) (I2) | (A3) (O3) (D3) (I3) | (A4) (O4) (D4) (I4) | (A5) (O5) (D5) (I5) |
|
|
// | Word 1 | Word 2 | Word 3 | Word 4 | Word 5 |
|
|
//
|
|
// printout of five load card (only prints words 1, 2 and 3)
|
|
//
|
|
// Column: | 1 2 | 3 - 6 | 7 8 | 9 10 | 11 | 12 - 15 | 16 | 17 - 20 | 21 | 22 - 25 | 26 - 29 | 30 31 | 32 33 | 34 | 35 - 38 | 39 | 40 - 43 | 44 | 45 - 48 | 49 - 52 | 53 54 | 55 56 | 57 | 58 - 61 | 62 | 63 - 66 | 67 |
|
|
// | | N N N N | | N N | | N N N N | | N N N N | s | | N N N N | | N N | | N N N N | | N N N N | s | | N N N N | | N N | | N N N N | | N N N N | s |
|
|
// | Addr | | Op | | Data | | Instr | sign | Addr | | Op | | Data | | Instr | sign | Addr | | Op | | Data | | Instr | sign
|
|
// | Location| | Code | | Addr | | Addr | | Location| | Code | | Addr | | Addr | | Location| | Code | | Addr | | Addr |
|
|
// | (A1) | (O1) | | (D1) | | (I1) | | (A2) | (O2) | | (D2) | | (I2) | | (A3) | (O3) | | (D3) | | (I3) |
|
|
// | Word 1 | | Word 2 | | Word 3 |
|
|
|
|
char pch_word[20];
|
|
t_int64 d;
|
|
int n;
|
|
|
|
encode_pch_str(" + ");
|
|
|
|
d = IOSync[0]; Shift_Digits(&d, 2); n=Shift_Digits(&d, 4);
|
|
sprintf_word(pch_word, n, 0, 0); // A1
|
|
encode_pch_str(&pch_word[6]);
|
|
sprintf_word(pch_word, IOSync[1], 0, 0); // word 1
|
|
encode_pch_str(pch_word);
|
|
|
|
d = IOSync[2]; Shift_Digits(&d, 2); n=Shift_Digits(&d, 4);
|
|
sprintf_word(pch_word, n, 0, 0); // A2
|
|
encode_pch_str(&pch_word[6]);
|
|
sprintf_word(pch_word, IOSync[3], 0, 0); // word 2
|
|
encode_pch_str(pch_word);
|
|
|
|
d = IOSync[4]; Shift_Digits(&d, 2); n=Shift_Digits(&d, 4);
|
|
sprintf_word(pch_word, n, 0, 0); // A3
|
|
encode_pch_str(&pch_word[6]);
|
|
sprintf_word(pch_word, IOSync[5], 0, 0); // word 3
|
|
encode_pch_str(pch_word);
|
|
|
|
d = IOSync[6]; Shift_Digits(&d, 2); n=Shift_Digits(&d, 4);
|
|
sprintf_word(pch_word, n, 0, 0); // A4
|
|
encode_pch_str(&pch_word[6]);
|
|
sprintf_word(pch_word, IOSync[7], 0, 0); // word 4
|
|
encode_pch_str(pch_word);
|
|
|
|
d = IOSync[8]; Shift_Digits(&d, 2); n=Shift_Digits(&d, 4);
|
|
sprintf_word(pch_word, n, 0, 0); // A5
|
|
encode_pch_str(&pch_word[6]);
|
|
sprintf_word(pch_word, IOSync[9], 0, 0); // word 5
|
|
encode_pch_str(pch_word);
|
|
|
|
encode_lpt_str(" ");
|
|
|
|
d = IOSync[0];
|
|
Shift_Digits(&d, 2); n = Shift_Digits(&d, 4);
|
|
encode_lpt_num(n, 4);
|
|
encode_lpt_spc(2);
|
|
d = IOSync[1];
|
|
encode_lpt_word(d, 0, wf_NN_NNNN_NNNNs);
|
|
encode_lpt_spc(4);
|
|
|
|
d = IOSync[2];
|
|
Shift_Digits(&d, 2); n = Shift_Digits(&d, 4);
|
|
d = IOSync[3];
|
|
if ((n==0) && (d==0)) {
|
|
encode_lpt_spc(4+2+13+4);
|
|
} else {
|
|
encode_lpt_num(n, 4);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_word(d, 0, wf_NN_NNNN_NNNNs);
|
|
encode_lpt_spc(4);
|
|
}
|
|
|
|
d = IOSync[4];
|
|
Shift_Digits(&d, 2); n = Shift_Digits(&d, 4);
|
|
d = IOSync[5];
|
|
if ((n==0) && (d==0)) {
|
|
encode_lpt_spc(4+2+13+4);
|
|
} else {
|
|
encode_lpt_num(n, 4);
|
|
encode_lpt_spc(2);
|
|
encode_lpt_word(d, 0, wf_NN_NNNN_NNNNs);
|
|
encode_lpt_spc(4);
|
|
}
|
|
}
|
|
|
|
void encode_fortransit_wiring(void)
|
|
{
|
|
// encode card for FORTRANSIT modified IT compiler
|
|
// from FORTRANSIT manual at http://bitsavers.org/pdf/ibm/650/28-4028_FOR_TRANSIT.pdf
|
|
// implemented Fortransit II (S)
|
|
// word 1986 (control word) specifies what is being punched)
|
|
// storage in output block
|
|
// +-------------------+
|
|
// Word 1977: | <- statement -> | Alphabetic
|
|
// 1978: | <- statement -> | Alphabetic
|
|
// 1979: | <- statement -> | Alphabetic
|
|
// 1980: | <- statement -> | Alphabetic
|
|
// 1981: | <- statement -> | Alphabetic
|
|
// 1982: | <- statement -> | Alphabetic
|
|
// +-------------------+
|
|
// 1983: | | Not Used
|
|
// 1984: | | Not Used
|
|
// +-----------+-------+
|
|
// 1985: | |N N N N| N N N N=Statement Number
|
|
// 1986: |a|b|c|d|e|f|g|h|i|j| Control Word
|
|
// a = 0/8 =8 -> punch a data card
|
|
// b = 0/8
|
|
// c = 0/8
|
|
// d = 0/8 =8 -> ???
|
|
// e = 0/8
|
|
// f = 0/8
|
|
// g = 0/8 =8 -> punching a IT source card, =0 -> punching SOAP card
|
|
// h = 0/8
|
|
// i = 0/8 =8 -> punching a FORTRANSIT card
|
|
// j = 0/8 =8 -> punching an IT header card (8 word load card format)
|
|
//
|
|
// IT card punch format
|
|
// Column: 1 2 3 4 | 5 | 6 - 42 | 43 - 70 | 71 72 | 73 - 80 |
|
|
// N N N N | + | | Statement | | Statement |
|
|
// Statement | Y(12) | | max 28 | | number as |
|
|
// Number | Punch | | chars | | comment |
|
|
//
|
|
//
|
|
// SOAP card storage in output block
|
|
// +-------------------+
|
|
// Word 1977: | <- Loc. Label -> | Alphabetic
|
|
// 1978: | <- Data Addr -> | Alphabetic
|
|
// 1979: | <- Inst Addr -> | Alphabetic
|
|
// 1980: | <- Op Code -> | Alphabetic
|
|
// 1981: | <- Remarks -> | Alphabetic
|
|
// 1982: | <- Remarks -> | Alphabetic
|
|
// +-------------------+
|
|
// 1983: | | Not Used
|
|
// 1984: | | Not Used
|
|
// +-------------------+
|
|
// 1985: | |N N N N| N N N N=Card Number as defined above
|
|
// 1986: | <- Control Word-> | As defined above
|
|
|
|
char pch_word[20];
|
|
char lin[31];
|
|
char loc[6], data_addr[6], inst_addr[6], OpCode[6], rem1[6], rem2[6];
|
|
t_int64 d;
|
|
int CardNum;
|
|
int b, neg, b_it_hdr, b_it_src, b_fort, b_soap, b_data; // punch control word flags
|
|
int i;
|
|
|
|
word_to_ascii(&lin[0], 1, 5, IOSync[0]);
|
|
word_to_ascii(&lin[5], 1, 5, IOSync[1]);
|
|
word_to_ascii(&lin[10], 1, 5, IOSync[2]);
|
|
word_to_ascii(&lin[15], 1, 5, IOSync[3]);
|
|
word_to_ascii(&lin[20], 1, 5, IOSync[4]);
|
|
word_to_ascii(&lin[25], 1, 5, IOSync[5]);
|
|
lin[30] = 0;
|
|
|
|
CardNum = (int) (IOSync[8] % D4);
|
|
|
|
word_to_ascii(loc, 1, 5, IOSync[0]);
|
|
word_to_ascii(data_addr, 1, 5, IOSync[1]);
|
|
word_to_ascii(inst_addr, 1, 5, IOSync[2]);
|
|
word_to_ascii(OpCode, 1, 3, IOSync[3]);
|
|
word_to_ascii(rem1, 1, 5, IOSync[4]);
|
|
word_to_ascii(rem2, 1, 5, IOSync[5]);
|
|
|
|
neg = 0;
|
|
|
|
d = IOSync[9];
|
|
b_it_hdr = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_fort = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_it_src = ((int) (d % 10) == 8) ? 1:0; d = d / 10; b_soap = ((b_fort == 1) && (b_it_src == 0));
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
b_data = ((int) (d % 10) == 8) ? 1:0; d = d / 10;
|
|
|
|
// printf("bits %06d%04d%c ", printfw(IOSync[9])); // to echo the control word of punched card
|
|
// generate card
|
|
if (b_data) {
|
|
// punch data card output for PUNCH fortransit command
|
|
for (i=0;i<8;i++) {
|
|
sprintf_word(pch_word, IOSync[i], 0, 0);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else if (b_it_hdr) {
|
|
// punch IT header card as 8 word per card load card format
|
|
for (i=0;i<8;i++) {
|
|
sprintf_word(pch_word, IOSync[i], 0, 1);
|
|
encode_pch_str(pch_word);
|
|
}
|
|
} else if (b_soap) {
|
|
// punch SOAP source instruction
|
|
for(i=0;i<40;i++) encode_pch_str(" "); // leave 40 first columns blank
|
|
encode_pch_str(" ");
|
|
encode_char(neg == 0 ? ' ' : '-', 0);
|
|
encode_pch_str(loc);
|
|
encode_pch_str(OpCode);
|
|
encode_pch_str(data_addr);
|
|
encode_pch_str(" ");
|
|
encode_pch_str(inst_addr);
|
|
encode_pch_str(" ");
|
|
encode_pch_str(rem1);
|
|
encode_pch_str(rem2);
|
|
// convert to lowercase for punching
|
|
for (i=40;i<card_nbuf;i++)
|
|
if ((card_buf[i] >= 'A') && (card_buf[i] <= 'Z'))
|
|
card_buf[i] = card_buf[i] - 'A' + 'a';
|
|
} else if (b_it_src) {
|
|
// punch IT source card
|
|
sprintf_word(pch_word, CardNum, 0, 0); // punch statement number
|
|
for (i=0;i<4;i++) pch_word[i] = pch_word[i+6];
|
|
pch_word[4] = '+';
|
|
for (i=5;i<10;i++) pch_word[i] = ' '; // punch separation spaces
|
|
encode_pch_str(pch_word);
|
|
for (i=10;i<42;i++) encode_pch_str(" ");
|
|
encode_pch_str(lin); // punch statement
|
|
encode_pch_str(" ");
|
|
sprintf_word(pch_word, CardNum, 0, 0); // punch statement number again as comment
|
|
for (i=0;i<4;i++) pch_word[i] = pch_word[i+6];
|
|
pch_word[4] = 0;
|
|
encode_pch_str(pch_word);
|
|
// convert to lowercase for punching
|
|
for (i=0;i<card_nbuf;i++)
|
|
if ((card_buf[i] >= 'A') && (card_buf[i] <= 'Z'))
|
|
card_buf[i] = card_buf[i] - 'A' + 'a';
|
|
}
|
|
|
|
// generate printout
|
|
if (b_data) {
|
|
// print data card output for PUNCH fortransit command
|
|
for (i=0;i<8;i++) {
|
|
d = IOSync[i];
|
|
if ((d == 0) && (i != 0)) {
|
|
encode_lpt_spc(11);
|
|
} else {
|
|
encode_lpt_word(d, 0, wf_nnnnnnnnnNs);
|
|
}
|
|
encode_lpt_spc(1);
|
|
}
|
|
} else if (b_it_hdr) {
|
|
// print IT header card as 8 word per card load card format
|
|
for (i=0;i<8;i++) {
|
|
if (i==4) {
|
|
encode_lpt_word(IOSync[i], 0, wf_NNNNNNNNNN);
|
|
} else {
|
|
encode_lpt_word(IOSync[i], 0, wf_nnnnnnnnnH);
|
|
}
|
|
}
|
|
} else if (b_soap) {
|
|
// print generated SOAP source listing
|
|
encode_lpt_spc(2);
|
|
encode_lpt_num(CardNum, -4);
|
|
encode_lpt_spc(6);
|
|
encode_lpt_str(loc);
|
|
encode_lpt_spc(2); encode_char(0, neg ? '-':' '); encode_lpt_spc(1);
|
|
encode_lpt_str(OpCode); encode_lpt_spc(3);
|
|
encode_lpt_str(data_addr); encode_lpt_spc(3);
|
|
encode_lpt_str(inst_addr); encode_lpt_spc(6);
|
|
encode_lpt_str(rem1); encode_lpt_str(rem2);
|
|
} else if (b_it_src) {
|
|
// print generated it source listing
|
|
if (CardNum == 0) {
|
|
encode_lpt_spc(5);
|
|
} else {
|
|
encode_lpt_num(CardNum, -4);
|
|
encode_lpt_str("+");
|
|
}
|
|
encode_lpt_spc(37);
|
|
encode_lpt_str(lin);
|
|
encode_lpt_spc(4);
|
|
encode_lpt_num(CardNum, 4);
|
|
}
|
|
}
|
|
|
|
|
|
/* Card punch routine */
|
|
uint32 cdp_cmd(UNIT * uptr, uint16 cmd, uint16 addr)
|
|
{
|
|
int i,c,h;
|
|
uint16 image[80];
|
|
uint32 wiring;
|
|
|
|
/* Are we currently tranfering? */
|
|
if (uptr->u5 & URCSTA_BUSY)
|
|
return SCPE_BUSY;
|
|
|
|
/* Test ready */
|
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
|
sim_debug(DEBUG_EXP, &cdp_dev, "No cards (no file attached)\n");
|
|
return SCPE_NOCARDS;
|
|
}
|
|
|
|
// copy and translate drum memory words to chars to punch
|
|
// using the control panel wiring.
|
|
|
|
wiring = (uptr->flags & UNIT_CARD_WIRING);
|
|
card_nbuf = card_nlpt = 0;
|
|
|
|
if (wiring == WIRING_SOAP) {
|
|
// encode soap card simulating soap control panel wiring for 533 (gasp!)
|
|
encode_soap_wiring(0);
|
|
} else if (wiring == WIRING_SOAPA) {
|
|
// encode soap card for multipass sopa IIA
|
|
encode_soap_wiring(1);
|
|
} else if (wiring == WIRING_SUPERSOAP) {
|
|
// encode super soap card
|
|
encode_supersoap_wiring();
|
|
} else if (wiring == WIRING_IS) {
|
|
// encode floating point interpretive system (bell interpreter) card
|
|
encode_is_wiring();
|
|
} else if (wiring == WIRING_IT) {
|
|
// encode Carnegie Internal Translator compiler card
|
|
encode_it_wiring();
|
|
} else if (wiring == WIRING_RA) {
|
|
// endecode Missile Systems Division Lockheed Aircraft Corporation - regional assembly card
|
|
encode_ra_wiring();
|
|
} else if (wiring == WIRING_FORTRANSIT) {
|
|
// encode Fortransit translator card
|
|
encode_fortransit_wiring();
|
|
} else if (wiring == WIRING_8WORD) {
|
|
// encode 8 words per card
|
|
encode_8word_wiring();
|
|
} else {
|
|
// default wiring: decode up to 8 numerical words per card
|
|
encode_8word_wiring();
|
|
}
|
|
|
|
if ((card_nlpt == 1) && (card_lpt[0] == 0)) {
|
|
// skip this line printout & echo
|
|
} else {
|
|
/* echo? */
|
|
encode_char(0, 13); encode_char(0, 10);
|
|
if (uptr->flags & UNIT_CARD_ECHO) {
|
|
for (i=0;i<card_nlpt;i++) sim_putchar(card_lpt[i]);
|
|
}
|
|
/* printout punched cards? */
|
|
if (uptr->flags & UNIT_CARD_PRINT) {
|
|
// printout will be directed to file attached to CDP0 unit, if any
|
|
if (cdp_unit[0].flags & UNIT_ATT) {
|
|
sim_fwrite(card_lpt, 1, card_nlpt, cdp_unit[0].fileref);
|
|
}
|
|
}
|
|
}
|
|
|
|
// trim right spaces for printing punch card
|
|
card_buf[card_nbuf] = 0;
|
|
sim_debug(DEBUG_DETAIL, &cpu_dev, "Punch Card: %s\n", card_buf);
|
|
|
|
/* punch the cards */
|
|
for (i=0; i<80; i++) {
|
|
if (i >= card_nbuf) {
|
|
c = 32;
|
|
} else {
|
|
c = card_buf[i];
|
|
}
|
|
if (c == 32) {
|
|
// no punch
|
|
image[i] = 0;
|
|
} else {
|
|
// punch char
|
|
h = sim_ascii_to_hol(c);
|
|
image[i] = h;
|
|
}
|
|
}
|
|
sim_punch_card(uptr, image);
|
|
sim_debug(DEBUG_CMD, &cdp_dev, "PUNCH\n");
|
|
uptr->u5 |= URCSTA_BUSY;
|
|
uptr->u6++; // incr number of punched cards
|
|
|
|
uptr->u5 &= ~URCSTA_BUSY;
|
|
|
|
return SCPE_OK;
|
|
|
|
}
|
|
|
|
/* Handle transfer of data for card punch */
|
|
t_stat
|
|
cdp_srv(UNIT *uptr) {
|
|
|
|
// I/O is synchronous. No need to set up srv
|
|
return SCPE_OK;
|
|
}
|
|
|
|
|
|
/* Set card read/punch control panel wiring */
|
|
t_stat cdp_set_wiring (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
int f;
|
|
|
|
if (uptr == NULL) return SCPE_IERR;
|
|
if (cptr == NULL) return SCPE_ARG;
|
|
for (f = 0; wirings[f].name != 0; f++) {
|
|
if (strcmp (cptr, wirings[f].name) == 0) {
|
|
uptr->flags = (uptr->flags & ~UNIT_CARD_WIRING) | wirings[f].mode;
|
|
return SCPE_OK;
|
|
}
|
|
}
|
|
return SCPE_ARG;
|
|
}
|
|
|
|
/* Show card read/punch control panel wiring */
|
|
t_stat cdp_show_wiring (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
|
{
|
|
int f;
|
|
|
|
for (f = 0; wirings[f].name != 0; f++) {
|
|
if ((uptr->flags & UNIT_CARD_WIRING) == wirings[f].mode) {
|
|
fprintf (st, "%s wiring", wirings[f].name);
|
|
return SCPE_OK;
|
|
}
|
|
}
|
|
fprintf (st, "invalid control panel wiring (%d)", uptr->flags & UNIT_CARD_WIRING);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Set card read/punch echo to console */
|
|
t_stat cdp_set_echo (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
int u = (uptr - cdp_unit);
|
|
t_stat r;
|
|
int num;
|
|
|
|
if (uptr == NULL) return SCPE_IERR;
|
|
if (cptr == NULL) {
|
|
num = 1; // no param means set (=1)
|
|
} else {
|
|
num = (int) get_uint (cptr, 10, 1, &r);
|
|
if (r != SCPE_OK) return r;
|
|
}
|
|
if (u == 0) {
|
|
sim_printf("this option cannot be set for CDP0\r\n");
|
|
return SCPE_ARG;
|
|
}
|
|
switch(val) {
|
|
case 0:
|
|
if (num== 0) {
|
|
uptr->flags = uptr->flags & ~UNIT_CARD_ECHO;
|
|
} else {
|
|
uptr->flags = uptr->flags | UNIT_CARD_ECHO;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (num== 0) {
|
|
uptr->flags = uptr->flags & ~UNIT_CARD_PRINT;
|
|
} else {
|
|
uptr->flags = uptr->flags | UNIT_CARD_PRINT;
|
|
}
|
|
break;
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Show card read/punch control panel wiring */
|
|
t_stat cdp_show_echo (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
|
{
|
|
switch(val) {
|
|
case 0:
|
|
fprintf (st, (uptr->flags & UNIT_CARD_ECHO) ? "ECHO": "No ECHO");
|
|
break;
|
|
case 1:
|
|
fprintf (st, (uptr->flags & UNIT_CARD_PRINT) ? "PRINT": "No PRINT");
|
|
break;
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat
|
|
cdp_attach(UNIT * uptr, CONST char *file)
|
|
{
|
|
t_stat r;
|
|
|
|
r = sim_card_attach(uptr, file);
|
|
if (SCPE_BARE_STATUS(r) != SCPE_OK)
|
|
return r;
|
|
uptr->u5 = 0;
|
|
uptr->u6 = 0; // u6 = number of cards punched
|
|
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat
|
|
cdp_detach(UNIT * uptr)
|
|
{
|
|
return sim_card_detach(uptr);
|
|
}
|
|
|
|
t_stat
|
|
cdp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
fprintf (st, "%s\r\n\r\n", cdp_description(dptr));
|
|
fprintf (st, "The 533 Card Read-punch writes cards using the selected\r\n");
|
|
fprintf (st, "control panel wiring to set the format of punched cards.\r\n");
|
|
fprintf (st, "It is possible to simulate a 407 accounting machine for\r\n");
|
|
fprintf (st, "printing using SET CDP1 PRINT=1. In this case, punched\r\n");
|
|
fprintf (st, "cards will be printed to file attached to unit 0 (CDP0).\r\n");
|
|
fprintf (st, "SET CDP ECHO=1 will display on console cards printout.\r\n");
|
|
|
|
sim_card_attach_help(st, dptr, uptr, flag, cptr);
|
|
fprint_set_help(st, dptr);
|
|
fprint_show_help(st, dptr);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *
|
|
cdp_description(DEVICE *dptr)
|
|
{
|
|
return "533 Card Punch + 407 Accounting for printing";
|
|
}
|
|
|
|
|