mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-25 20:01:52 +00:00
1. Release emulator version 0.07.
2. Implement interrupt and device status latching in B5500CentralControl to support better UI display. 3. Implement B5500CardPunch device. 4. Implement preliminary and experimental B5500DummyPrinter device; correct printer I/O initiation in IOUnit. 5. Correct the way that Printer Finished interrupts are handled in IOUnit and CentralControl. 6. Implement Card Load Select in B5500Console and B5500SyllableDebugger. 7. Fix lack of presence-bit detection in return ops for returned values. 8. Redesign B5500CardReader UI to show last two cards read; change method of emptying the input hopper. 9. Set CHECK option and rework SYSTEM/LOG initialization in B5500ColdLoader.html. 10. Centralize system memory cycle time setting; change from 6us to 4us memory cycle time. 11. Increase Processor timeslice to 16ms and rework Processor.schedule() internals for more accurate performance throttling in browsers with poor setTimeout() granularity. 12. Reduce Processor syllable overhead from 2 cycles to 1. 13. Change B5500SPOUnit method of output to "paper" to work better in Google Chrome. 14. Make documentation and debugging enhancements in B5500IOUnit. 15. Release initial test website HTML and Unisys license PDF. 16. Commit Mark XVI DCMCP transcription as of 2013-06-21.
This commit is contained in:
@@ -23052,3 +23052,512 @@ BEGIN REAL RCW=+0,MSCW=-2; 38001000
|
||||
EXIT: 38099100
|
||||
P(P&RCW[CTC],0,RDS,0,XCH,P&P[CTF],STF); 38100000
|
||||
END DISKFILEOPEN; 38101000
|
||||
PROCEDURE OTHERFILEOPENIN(ALPHA); AVLUE ALPHA; INTEGER ALPHA; 38102000
|
||||
BEGIN REAL RCW=+0,MSCW=-2; 38102100
|
||||
REAL IOM=IOMASK, IOMASK=+1; 38102200
|
||||
INTEGER NBUFS=+2,FNUM=+3,RLEN=+4,TYPE=+5,IO=+6,BLEN=+7,U=+8, 38102300
|
||||
KIND=+9,MODE=+10,DIREC=+11,FORMS=+12,COBOL=+13, 38102400
|
||||
UNLABELED=+14,OPTIONAL=+15,CNTCTL=+16; 38102500
|
||||
REAL T1=+17,T2=+18,MASK=+19,STATE=+20; 38102600
|
||||
REAL MFID=+21,FID=+22; INTEGER REEL=+23,CDATE=+24,CYCLE=+25; 38102700
|
||||
ARRAY FIB=+26[*],FPB=+27[*];% 38102800
|
||||
INTEGER ACCESS=+28,FIB7=+29; 38102900
|
||||
ARRAY HEADER=+30[*];% 38103000
|
||||
REAL TOG=+31; 38103100
|
||||
REAL USASI=NT1, RHEAD=HEADER; 38103200
|
||||
LABEL FIND,DCN,DC19; 38103300
|
||||
SUBROUTINE TYPEOPEN;% 38103400
|
||||
BEGIN 38103500
|
||||
T1:=(OPNMESS AND ((T1:=JAR[P1MIX,0])>0 OR 38103600
|
||||
COPNMESS AND T1<0)); 38103700
|
||||
$ SET OMIT = PACKETS 38103800
|
||||
BEGIN NT2:=0; 38104100
|
||||
IF U<16 THEN 38104200
|
||||
STREAM(S:=PRNTABLE[U].[30:18], D:=[NT2]); 38104300
|
||||
BEGIN SI ~ LOC S; DS ~ 8 DEC; % 38104400
|
||||
DI ~ DI-7; DS ~ 6 FILL; % 38104500
|
||||
END; % 38104600
|
||||
FILEMESSAGE((" IN ")& 38104700
|
||||
TINU[U][6:30:18], NT2, FPB[FNUM], FPB[FNUM+1], 38104800
|
||||
IF KIND=2 OR KIND=9 THEN P(REEL,CDATE) ELSE 38104900
|
||||
P(0,0), P, CYCLE, T1) 38105000
|
||||
END; 38105100
|
||||
END; 38105200
|
||||
SUBROUTINE REED;% 38105300
|
||||
BEGIN IF (T2~WAITIO(T1,(MASK OR @40)&@377[CTF],U) AND @367)!0 THEN38105400
|
||||
IF (T2 AND NOT MASK)!0 THEN 38105500
|
||||
BEGIN STOPTIMING(FNUM,1023); BLASTQ(U); SETNOTINUSE(U,0); 38105600
|
||||
FILEMESS(-"PARITY ","ON ... "&TINU[U][24:30:18],% 38105700
|
||||
MFID,FID,REEL,CDATE,CYCLE);% 38105800
|
||||
END;% 38105900
|
||||
IF TERMSET(P1MIX) THEN 38106000
|
||||
BEGIN STOPTIMING(FNUM,1023); SETNOTINUSE(U,0); 38106100
|
||||
GO TO INITIATE; 38106200
|
||||
END; 38106300
|
||||
END REED;% 38106400
|
||||
REAL SUBROUTINE CNTLBITS;% 38106500
|
||||
CNTLBITS~IOMASK&MODE[21:47:1]&DIREC[22:47:1]&CNTCTL[23:47:1]38106600
|
||||
&IO[24:47:1]&(KIND=7 OR KIND>9 AND KIND{12)[20:47:1] 38106700
|
||||
&(IF KIND=1OR KIND=7OR KIND=12THEN@20ELSE 0)[27:42:6];38106800
|
||||
SUBROUTINE LABELAREA;% 38106900
|
||||
M[T1:=ALPHA-2]:=M OR (GETSPACE((T1:=M[T1],SIZE)+4, %167-38107000
|
||||
LABELAREAV,1)+4) & T1[SIZE] & CNTLBITS[FTF];38107100
|
||||
P(ALPHA); % DETERMINE IF BRANCH TO DC19 38109000
|
||||
P(RCW,MSCW,STF); 38110000
|
||||
RCW:=RCW&P(XCH)[CTC]; 38110500
|
||||
IF P=2 THEN GO DC19; 38111000
|
||||
IF STATE.[41:1] THEN% 38111500
|
||||
BEGIN U~FIB[15].[25:5];% 38112000
|
||||
END ELSE% 38112500
|
||||
BEGIN IF (U~FINDINPUT(MFID,FID,REEL,CDATE,CYCLE,COBOL,UNLABELED, 38113000
|
||||
OPTIONAL,MODE,FNUM))<0 THEN% 38113500
|
||||
BEGIN FIB[5].[39:4]~9; GO TO FIND END;% 38114000
|
||||
STARTIMING(FNUM,IF U>31 THEN 18 ELSE U); 38114500
|
||||
FPB:=PRT[P1MIX,3]; % STARTIMING MAY HAVE MOVED IT. 38115000
|
||||
KIND:=IF U GTR 31 THEN 11 ELSE UNIT[U].[1:4]; 38115100
|
||||
TYPEOPEN;% 38115500
|
||||
IF U<16 THEN BEGIN RRRMECH~TWO(U) OR RRRMECH; 38116000
|
||||
PRNTABLE[U].[15:15]~ALPHA;% 38116500
|
||||
END;% 38117000
|
||||
% TGW38117500
|
||||
IF (T1~RDCTABLE[U].[14:10])!0 THEN REEL~T1; 38118000
|
||||
STATE.[39:4]~0;% 38118500
|
||||
END;% 38119000
|
||||
IF KIND=0 THEN% 38119500
|
||||
BEGIN IF U=23 THEN BEGIN T1~READERA; READERA~0 END% 38120000
|
||||
ELSE BEGIN T1~READERB; READERB~0 END;% 38120500
|
||||
M[ALPHA-2]:=[M[T1]]&10[8:38:10]&1[24:47:1];% 38121000
|
||||
M[T1-4]:=P(DUP,LOD)&P1MIX[AREAMIXF]&LABELAREAV[AREATYPEF];% 38121500
|
||||
IF MODE := (MODE=0) AND BLEN=20 THEN %301-38122000
|
||||
SAVEWORD:=SAVEWORD OR TWO(U); %301-38122100
|
||||
CNTCTL:=DIREC:=0;% 38122500
|
||||
IF BLEN<T1~(MODE+1)|10 THEN BLEN~T1;% 38123000
|
||||
END ELSE% 38123500
|
||||
IF KIND=2 THEN% 38124000
|
||||
BEGIN IF NOT UNLABELED THEN BEGIN% 38124500
|
||||
IF DIREC AND NOT FIB[16].[22:1] THEN 38125000
|
||||
BEGIN IF NOT STATE.[40:1] THEN BEGIN% 38125500
|
||||
T1~5&3[23:46:2] OR M;% 38126000
|
||||
MASK~0; REED;% 38126500
|
||||
MASK:=@60; DO REED UNTIL T2.[42:1]; 38127000
|
||||
DO REED UNTIL T2.[42:1]; 38127500
|
||||
MASK~0; REED; END;% 38128000
|
||||
END; 38128500
|
||||
CNTCTL~1; LABELAREA;% 38129000
|
||||
T1:=NFLAG(M[ALPHA-2]);% 38129500
|
||||
IF DIREC THEN T1:=T1.[8:10]-1 INX T1;% 38130000
|
||||
MASK:=@40; REED; 38130500
|
||||
STREAM(Y:=0:X:=0,X1:=0,X2:=0,Z:=T1); 38131000
|
||||
BEGIN DI:=LOC X; DS:=24 LIT "VOL1HDR1HDR2EOF1EOF2EOV1"; 38131500
|
||||
DI:=LOC X; 38132000
|
||||
6(TALLY:=TALLY+1; 38132500
|
||||
SI:=Z; 38133000
|
||||
IF 4 SC=DC THEN 38133500
|
||||
JUMP OUT TO B); 38134000
|
||||
TALLY:=0; 38134500
|
||||
B: 38135000
|
||||
Y:=TALLY; 38135500
|
||||
END; 38136000
|
||||
IF (USASI:=P)>0 THEN 38136500
|
||||
USASITAPE(T1.[CF],USASI,4,U,DIREC) ELSE 38137000
|
||||
IF M[T1 INX 6].[24:6]=1 THEN 38137500
|
||||
BEGIN 38138000
|
||||
REED; 38138500
|
||||
MASK~@60; 38139000
|
||||
T1~5&3[23:46:2] OR M; 38139500
|
||||
T2~0; 38140000
|
||||
END; 38140500
|
||||
IF T2 NEQ @40 THEN DO REED UNTIL T2.[42:1] ELSE 38141000
|
||||
FOR CNTCTL~DIREC STEP 1 UNTIL 2 DO% DIREC = 0 OR 1 %DB 38141500
|
||||
P(WAITIO(@4740000005&(NOT DIREC)[22:47:1],@377,U),DEL);%DB38142000
|
||||
FWD;% 38142500
|
||||
CNTCTL~BLEN{1023;% 38143000
|
||||
END ELSE% 38143500
|
||||
IF KIND=9 THEN% 38144000
|
||||
BEGIN UNLABELED~CNTCTL~1;% 38144500
|
||||
DIREC~0;% 38145000
|
||||
END ELSE% 38145500
|
||||
IF KIND=11 THEN 38146000
|
||||
BEGIN T1~CIDROW[U-32].[18:15]; 38146500
|
||||
CIDROW[U-32].[18:15]~0; 38147000
|
||||
M[ALPHA-2]:=[M[T1]]&10[8:38:10]&1[24:47:1];% 38147500
|
||||
M[T1-4]:=P(DUP,LOD)&P1MIX[AREAMIXF]&LABELAREAV[AREATYPEF];% 38148000
|
||||
MODE:=0;% 38148500
|
||||
CNTCTL:=DIREC:=0;% 38149000
|
||||
FIB[13].[1:9]~NBUFS~1; FIB[13].[10:9]~1; 38149500
|
||||
IF BLEN<10 THEN BLEN~10; 38150000
|
||||
END ELSE 38150500
|
||||
DCN:: FILEMESS(-"I/O ERR",0,MFID,FID,REEL,CDATE,CYCLE);% 38151000
|
||||
P(1); 38151500
|
||||
IF BLEN=0 THEN GO TO DCN;% 38151800
|
||||
IF NOT FIB[18].[1:1] OR P THEN 38151900
|
||||
GETBUFFERS(BLEN,NBUFS,U,ALPHA); 38152000
|
||||
GO FIND; 38152100
|
||||
DC19: 38152250
|
||||
$ SET OMIT = NOT(DATACOM AND RJE ) 38152500
|
||||
FIB[14]:=NBUFS; 38156500
|
||||
U:=30; KIND:=13; 38157000
|
||||
FIB[13].[1:9]~ NBUFS~2; 38157500
|
||||
FIB[18]:=(*P(DUP))&(BLEN:=RLEN)[3:33:15]&BLEN[CTF]; 38158000
|
||||
IF MFID>0 THEN 38158500
|
||||
BEGIN ; 38159000
|
||||
STREAM(A~0,B~0:MFID,FID,C~0); 38159500
|
||||
BEGIN 38160000
|
||||
SI~ LOC MFID; DI~ LOC A; 38160500
|
||||
2(C~ SI; 8(IF SC}0 THEN IF SC{9 THEN TALLY~ TALLY+1 38161000
|
||||
ELSE JUMP OUT ELSE JUMP OUT; SI~ SI+1);38161500
|
||||
SI~ C; C~ TALLY; DS~ C OCT; TALLY~ 0; SI~ LOC FID);38162000
|
||||
END; 38162500
|
||||
FID~ P; 38163000
|
||||
MFID~P; 38163500
|
||||
END; 38164000
|
||||
M[ALPHA-2]~ 0&MFID[9:44:4]&FID[14:44:4]; 38164500
|
||||
FIND:: 38191500
|
||||
P(P&RCW[CTC],0,RDS,0,XCH,P&P[CTF],STF); 38192000
|
||||
END OTHER FILE OPEN IN; 38192500
|
||||
PROCEDURE OTHERFILEOPENOUT(ALPHA); VALUE ALPHA; INTEGER ALPHA; 38200000
|
||||
BEGIN REAL RCW=+0,MSCW=-2; 38200100
|
||||
REAL IOM=IOMASK, IOMASK=+1; 38200200
|
||||
INTEGER NBUFS=+2,FNUM=+3,RLEN=+4,TYPE=+5,IO=+6,BLEN=+7,U=+8, 38200300
|
||||
KIND=+9,MODE=+10,DIREC=+11,FORMS=+12,COBOL=+13, 38200400
|
||||
UNLABELED=+14,OPTIONAL=+15,CNTCTL=+16; 38200500
|
||||
REAL T1=+17,T2=+18,MASK=+19,STATE=+20; 38200600
|
||||
REAL MFID=+21,FID=+22; INTEGER REEL=+23,CDATE=+24,CYCLE=+25; 38200700
|
||||
ARRAY FIB=+26[*],FPB=+27[*];% 38200800
|
||||
INTEGER ACCESS=+28,FIB7=+29,; 38200900
|
||||
ARREAY HEADER=+30[*]; 38201000
|
||||
REAL TOG=+31; 38201100
|
||||
REAL USASI=NT1, RHEAD=HEADER 38201200
|
||||
LABEL LPS,FIND,DNC,PBS; 38201300
|
||||
SUBROUTINE TYPEOPEN;% 38201400
|
||||
BEGIN 38201500
|
||||
T1:=(OPNMESS AND ((T1:=JAR[P1MIX,0])>0 OR 38201600
|
||||
COPNMESS AND T1<0)); 38201700
|
||||
$ SET OMIT = PACKETS 38201800
|
||||
BEGIN NT2:=0; 38202100
|
||||
IF U<16 THEN 38202200
|
||||
STREAM(S:=PRNTABLE[U].[30:18], D:=[NT2]); 38202300
|
||||
BEGIN SI ~ LOC S; DS ~ 8 DEC; % 38202400
|
||||
DI ~ DI-7; DS ~ 6 FILL; % 38202500
|
||||
END; % 38202600
|
||||
FILEMESSAGE((" OUT")& 38202700
|
||||
TINU[U][6:30:18], NT2, FPB[FNUM], FPB[FNUM+1], 38202800
|
||||
IF KIND=2 OR KIND=9 THEN P(REEL,CDATE) ELSE 38202900
|
||||
P(0,0), P, CYCLE, T1); 38203000
|
||||
END; 38203100
|
||||
END; 38203200
|
||||
SUBROUTINE REED;% 38203300
|
||||
BEGIN IF (T2~WAITIO(T1,(MASK OR @40)&@377[CTF],U) AND @367)!0 THEN38203400
|
||||
IF (T2 AND NOT MASK)!0 THEN 38203500
|
||||
BEGIN STOPTIMING(FNUM,1023); BLASTQ(U); SETNOTINUSE(U,0); 38203600
|
||||
FILEMESS(-"PARITY ","ON ... "&TINU[U][24:30:18],% 38203700
|
||||
MFID,FID,REEL,CDATE,CYCLE);% 38203800
|
||||
END;% 38203900
|
||||
IF TERMSET(P1MIX) THEN 38204000
|
||||
BEGIN STOPTIMING(FNUM,1023); SETNOTINUSE(U,0); 38204100
|
||||
GO TO INITIATE; 38204200
|
||||
END; 38204300
|
||||
END REED% 38204400
|
||||
REAL SUBROUTINE CNTLBITS;% 38204500
|
||||
CNTLBITS~IOMASK&MODE[21:47:1]&DIREC[22:47:1]&CNTCTL[23:47:1]38204600
|
||||
&[24:47:1]&(KIND=7 OR KIND>9 AND KIND{12)[20:47:1] 38204700
|
||||
&(IF KIND=1OR KIND=7OR KIND=12THEN@20ELSE 0)[27:42:6];38204800
|
||||
SUBROUTINE LABELAREA;% 38204900
|
||||
M[T1:=ALPHA-2]:=M OR (GETSPACE((T1:=M[T1],SIZE)+4, %167-38205000
|
||||
LABELAREAV,1)+4) & T1[SIZE] & CNTLBITS[FTF];38205100
|
||||
P(RCW,MSCW,STF); 38210000
|
||||
RCW:=RCW&P(XCH)[CTC]; 38210500
|
||||
IF STATE.[41:1] THEN% 38211500
|
||||
BEGIN U~FIB[15].[25:5];% 38212000
|
||||
END ELSE% 38212500
|
||||
BEGIN T2:=FPB[FNUM+3]; % SAVES COPIES FOR BACK UP 38213000
|
||||
IF (U:=FINDOUTPUT(MFID,FID,REEL,CDATE,CYCLE,TYPE 38213500
|
||||
$ SET OMIT = NOT PACKETS 38214000
|
||||
&FPB[FNUM-3][1:23:1] 38214500
|
||||
$ POP OMIT 38215000
|
||||
,FORMS,KIND))>40 THEN 38215500
|
||||
BEGIN FIB[14].[3:15]~U; 38216000
|
||||
FPB[FNUM+2],[18:30]~DATE; 38216500
|
||||
IF MCP!NOT(-0) THEN M[U+2]~USERCODE[P1MIX]; 38217000
|
||||
M[U+3]~XCLOCK+P(RTR); 38217500
|
||||
T1:=SPACE(30); 38218000
|
||||
MOVE(30,U,T1); 38218500
|
||||
STREAM(DATE,B:=T1+3); 38219000
|
||||
BEGIN SI:=LOC DATE;DS:=8OCT;DI:=DI-8;DS:=2LIT"+2";END; 38219500
|
||||
M[T1+1]~(XCLOCK+P(RTR))&(M[T1+3])[6:30:18]; 38220000
|
||||
M[T1+4]:= 0&SYSNO[4:46:2]&1[2:47:1]; 38220500
|
||||
M[T1+5]~(*PDUP))&1[2:47:1]; %ABORTED PBD TOG. 38221000
|
||||
$ SET OMIT = RJE AND DATACOM 38221500
|
||||
P(0); 38222000
|
||||
$ POP OMIT 38222500
|
||||
$ SET OMIT = NOT(RJE AND DATACOM) 38223000
|
||||
M[T1+6]~P(XCH); 38226500
|
||||
M[U-1]:=EUF(IF TYPE NEQ 0 AND TYPE LSS 20 THEN 38227000
|
||||
"PRD " ELSE "PUD ",M[U+6],T1-1); 38227500
|
||||
FORGETSPACE(T1); 38228000
|
||||
$ SET OMIT = PACKETS 38228500
|
||||
FILEMESSAGE((IF TYPE GEQ 20 OR TYPE=0 THEN "PUD...." 38230000
|
||||
ELSE "PBD....")&M[U+6][24:6:24], 38230500
|
||||
"OUT "&M[U+6][30:30:18], 38231000
|
||||
MFID,FID,0,0,0, 38231500
|
||||
(PBDREL OR OPNMESS)); 38232000
|
||||
STARTIMING(FNUM,U~18); 38232500
|
||||
FPB:=PRT[P1MIX,3]; % STARTIMING MAY HAVE MOVED IT. 38233000
|
||||
END ELSE 38233500
|
||||
IF U LSS 0 THEN %DSED 38234000
|
||||
BEGIN FIB[5].[39:4]:=9; GO FIND END ELSE 38234500
|
||||
BEGIN 38235000
|
||||
STARTIMING(FNUM,U);% 38235500
|
||||
FPB:=PRT[P1MIX,3]; % WATCH OUT FOR STARTIMING, 38236000
|
||||
IF KIND=7 THEN FPB[FNUM+3] := (*P(DUP))&T2[15:15:8]; 38236010
|
||||
TYPEOPEN;% 38236500
|
||||
IF TYPE=5 OR TYPE=8 OR TYPE=9 THEN UNLABELED~1;% 38237000
|
||||
IF U<16 THEN BEGIN RRRMECH~TWO(U) OR RRRMECH; 38237500
|
||||
PRNTABLE[U].[15:15]~ALPHA;% 38238000
|
||||
END; END; 38238500
|
||||
END;% 38239000
|
||||
IF KIND=6 THEN% 38239500
|
||||
BEGIN BLEN:=10; 38240000
|
||||
FIB[18]:=(*P(DUP))&BLEN[CTC]&BLEN[CTF]&BLEN[3:33:15]; 38240500
|
||||
MODE~DIREC~CNTCTL~0;% 38241000
|
||||
END ELSE% 38241500
|
||||
IF KIND=1 THEN% 38242000
|
||||
BEGIN MODE~DIREC~CNTCTL~0;% 38242500
|
||||
LPS: 38243000
|
||||
IF NOT COBOL THEN M[ALPHA-2]~0&15[8:38:10];% 38243500
|
||||
END ELSE% 38244000
|
||||
IF KIND=12 THEN 38244500
|
||||
BEGIN TYPE~IF (TYPE!0 AND TYPE<20) THEN 15 ELSE 22; 38245000
|
||||
PBS: MODE~DIREC~0; FIB[13].[1:9]~NBUFS~CNTCTL~1; FIB[13].[10:9]~1; 38245500
|
||||
BLEN~IF TYPE}20 THEN 10 ELSE IF BLEN>17 THEN 17 ELSE BLEN; 38246000
|
||||
M[T1~GETSPACE(92,3,1)+2]~M[T1-1]~[M[ALPHA]]&(T1+2)[CTF]& 38246500
|
||||
U[12:42:6]; 38247000
|
||||
DISKIO(RHEAD,-T1-75,11,JAR[P1MIX,6].[CF]); 38247500
|
||||
M[ALPHA]:=T1+2; 38248000
|
||||
FIB[14]~(*P(DUP))&(T1+2)[CTC]&(T1+56)[CTF]; 38248500
|
||||
FIB[18]~(*P(DUP))&BLEN[CTC]&BLEN[CTF]&BLEN[03:33:15]; 38249000
|
||||
STREAM(D~T1+1); 2(36(DS~8 LIT"0")); 38249500
|
||||
FIB[5].[FF]~(M[T1+91]~FIB[5].[FF]&1[18:47:1])+1; 38250000
|
||||
SLEEP([RHEAD],IOMASK); 38250500
|
||||
HEADER:=[M[T1]]&92[8:38:10]; 38251000
|
||||
HEADER[74]~MFID; 38251500
|
||||
HEADER[75]~FID; 38252000
|
||||
HEADER[87]~FORMS; 38252500
|
||||
HEADER[88]:=T2.[15:8]; % COPIES 38253000
|
||||
HEADER[89]:=USERCODE[P1MIX]; %132-38253100
|
||||
HEADER[76]~ABS(JAR[P1MIX,0]); 38253500
|
||||
HEADER[77]~ABS(JAR[P1MIX,1]); 38254000
|
||||
REEL~RDCTABLE[U].[14:10]; % GET ACTUAL REEL NUMBER %745-38254100
|
||||
GO TO LPS; 38254500
|
||||
END ELSE 38255000
|
||||
IF KIND=7 THEN% 38255500
|
||||
BEGIN TYPE~IF (TYPE!0 AND TYPE<20) THEN 6 ELSE 20; 38256000
|
||||
IF SVPBT THEN SAVEWORD:=TWO(U) OR SAVEWORD; 38256500
|
||||
GO TO PBS; 38257000
|
||||
END ELSE% 38257500
|
||||
IF KIND=2 THEN% 38258000
|
||||
BEGIN IF PRNTABLE[U]}0 THEN GO TO DCN;% 38258500
|
||||
CNTCTL~MODE;% 38259000
|
||||
END ELSE% 38259500
|
||||
IF KIND=8 THEN% 38260000
|
||||
BEGIN UNLABELED~CNTCTL~1;% 38260500
|
||||
DIREC~0;% 38261000
|
||||
END;% 38261500
|
||||
IF UNLABELED THEN% 38262000
|
||||
BEGIN IF COBOL THEN% 38262500
|
||||
BEGIN MASK~0;% 38263000
|
||||
IF KIND=1 THEN BEGIN T1~@4000100000; REED END ELSE 38263500
|
||||
IF KIND=7 OR KIND=12 THEN 38264000
|
||||
BEGIN 38264500
|
||||
IF TYPE < 20 THEN 38265000
|
||||
BEGIN 38265500
|
||||
HEADER[73]~@1540176000100000&FIB[5][FTC]; 38266000
|
||||
FIB[5].[FF]~FIB[5].[FF]+1; 38266500
|
||||
FIB[14].[FF]:=T1+38; 38267000
|
||||
END; 38267500
|
||||
GO FIND; 38268000
|
||||
END; 38268500
|
||||
END;% 38269000
|
||||
END ELSE% 38269500
|
||||
BEGIN IF COBOL THEN% 38270000
|
||||
BEGIN M[ALPHA-2]~P(DUP,LOD)&CNTLBITS[18:18:15];% 38270500
|
||||
IF U<16 THEN% 38271000
|
||||
STREAM(N~PRNTABLE[U].[30:18],D~M[ALPHA-2]);% 38271500
|
||||
BEGIN SI~LOC N; DI~DI+53; DS~5 DEC END;% 38272000
|
||||
END ELSE% 38272500
|
||||
BEGIN IF REEL=0 THEN REEL~1;% 38273000
|
||||
IF CYCLE=0 THEN CYCLE~1;% 38273500
|
||||
IF CDATE=0 THEN STREAM(DATE,CD~[CDATE]);% 38274000
|
||||
BEGIN SI~LOC DATE; SI~SI+3; DS~5 OCT END; 38274500
|
||||
LABELAREA;% 38275000
|
||||
BUILDLABEL(M[ALPHA-2],MFID,FID,REEL,CDATE,CYCLE,% 38275500
|
||||
FIB[4],(IF U<16 THEN PRNTABLE[U].[30:18] 38276000
|
||||
ELSE 0),STATE.[46:2],% 38276500
|
||||
BLEN,RLEN);% 38277000
|
||||
END;% 38277500
|
||||
M[M[ALPHA-2] INX P(DUP).[8:10]]~@3700000000000000;% 38278000
|
||||
IF (P(KIND,DUP)=7 OR (P(XCH,DUP)=12 OR P(XCH)=1)) THEN 38278500
|
||||
IF KIND=7 AND FIB[13].[28:10]!ABS(COBOL) THEN GO FIND ELSE 38279000
|
||||
BEGIN IF TYPE GEQ 20 THEN % MAKE CP BACK-UP LABEL 38279500
|
||||
BEGIN M[M[ALPHA-2] INX 4]:=FLAG(NABS(JAR[P1MIX,0])); 38280000
|
||||
M[M[ALPHA-2] INX 5]:=FLAG(JAR[P1MIX,1]&17[1:43:5]); 38280500
|
||||
STREAM(A:=[M[M[ALPHA-2] INX 6]]); 38281000
|
||||
BEGIN DS:=15 LIT" PUNCH BACK-UP "; DS:=LIT"%"; 38281500
|
||||
2(DS:=8 LIT"%%%%%%%%"); 38282000
|
||||
END; 38282500
|
||||
END ELSE % MAKE LP LABEL 38283000
|
||||
BEGIN T1:=M[M[ALPHA-2]INX 3]; 38283500
|
||||
DISKIO(T2,NABS(M[ALPHA-2]INX 1),11,JAR[P1MIX,6].[CF]);38284000
|
||||
M[M[ALPHA-2]INX 13]:=FLAG(NABS(JAR[P1MIX,0])); 38284500
|
||||
M[M[ALPHA-2]INX 14]:=FLAG(JAR[P1MIX,1]&17[1:43:5]); 38285000
|
||||
SLEEP([T2],IOMASK); 38285500
|
||||
M[M[ALPHA-2] INX 3]:=T1; 38286000
|
||||
END; 38286500
|
||||
M[M[ALPHA02] INX 1]:=MFID; 38287000
|
||||
M[M[ALPHA-2] INX 2]:=FID; 38287500
|
||||
IF KIND=1 THEN M[ALPHA-2]~P(DUP,LOD) & %150-38288000
|
||||
(IF SEPARATE THEN 1 ELSE @20)[27:42:6] %150-38288100
|
||||
ELSE %150-38288200
|
||||
BEGIN HEADER[73]~(FIB[5].[FF] OR @360170100000000)& 38288500
|
||||
(TYPE<20)[32:47:1]; 38289000
|
||||
IF NOT SEPARATE THEN %150-38289100
|
||||
IF (TYPE<20) THEN %150-38289200
|
||||
HEADER[73]~P(DUP,LOD)&(@20)[27:42:6];%150-38289300
|
||||
FIB[5]~P(DUP,LOD,0,1,CFX,+); 38289500
|
||||
STREAM(L~M[ALPHA-2],B~[HEADER[56]]); 38290000
|
||||
BEGIN SI~L; DS~17 WDS END; 38290500
|
||||
FIB[14].[FF]~[HEADER[38]]; GO FIND; 38291000
|
||||
END; END; 38291500
|
||||
T1~NFLAG(M[ALPHA-2]);% 38292000
|
||||
MASK~0L REEDL% 38292500
|
||||
IF KIND=2 THEN% 38293000
|
||||
BEGIN T2~@1737000000000000;% 38293500
|
||||
T1~NFLAG([T2]);% 38294000
|
||||
REED;% 38294500
|
||||
END;% 38295000
|
||||
END;% 38295500
|
||||
P(0); 38296000
|
||||
IF BLEN=0 THEN 38296500
|
||||
DCN:: FILEMESS(-"I/O ERR",0,MFID,FID,REEL,CDATE,CYCLE); 38296750
|
||||
IF NOT FIB[18].[1:1] OR P THEN 38297000
|
||||
GETBUFFERS(BLEN,NBUFS,U,ALPHA); 38297500
|
||||
FIND:: 38298000
|
||||
P(P&RCW[CTC],0,RDS,0,XCH,P&P[CTF],STF); 38298500
|
||||
END OTHER FILE OPEN OUT; 38299000
|
||||
PROCEDURE DISKCLOSE(ALPHA); VALUE ALPHA; INTEGER ALPHA;% 38355000
|
||||
BEGIN REAL RCW=+0,MSCW=-2; 38356000
|
||||
ARRAY FIB=+1[*],FPB=+2[*],HEADER=+3[*];% 38357000
|
||||
%%% DONT ADD ANY DECLARATIONS BETWEEN "HEADER" AND "KIND" %%% WCP 38358000
|
||||
INTEGER KIND=+4,NUBFS=+5,U=+6,BLEN=+7,CODE=+8, 38359000
|
||||
UNLABELED=+9,COBOL=+10,I=+11,J=+12, 38360000
|
||||
FNUM=+13; 38361000
|
||||
REAL MID=+14,FID=+15,H=+16,D=+17,C=+18,FORMS=+19,STATE=+20; 38362000
|
||||
LABEL L1,L2,L3,EOF,CLEANUP; 38363000
|
||||
LABEL OBJTYPE,DUMMY; 38364000
|
||||
REAL STA=+21;% 38364100
|
||||
REAL T1=+22,T2=+23,T3=+24,IOD=+25;% 38365000
|
||||
ARRAY SEG0=+26[*],SKEL=+27[*];% 38366000
|
||||
REAL T=+28,ACCESS=+29;% 38366010
|
||||
BOOLEAN COMPGO=+30; 38366020
|
||||
$ SET OMIT = NOT SHAREDISK 38366099
|
||||
SUBROUTINE COOLOFF; 38370700
|
||||
BEGIN FOR I~0 STEP 1 UNTIL NBUFS-1 DO% 38370800
|
||||
BEGIN IF NOT M[ALPHA+1].[19:1] THEN% 38371000
|
||||
SLEEP([M[ALPHA=I]],IOMASK);% 38372000
|
||||
IF KIND!4 THEN 38373000
|
||||
IF M[ALPHA+I].[27:1] THEN GO TO EOF;% 38374000
|
||||
END;% 38375000
|
||||
EOF: END COOLOFF;% 38376000
|
||||
% 38376500
|
||||
BOOLEAN SUBROUTINE WRITTENON; % PICKS UP THE ACCESSED BITS FROM38377000
|
||||
BEGIN J:=0; % THE BUFFERS. 38377200
|
||||
IF (T:=FIB[10].[3:15]) NEQ 0 THEN 38377400
|
||||
BEGIN 38377600
|
||||
FOR I:=NBUFS-1 STEP -1 UNTIL 0 DO 38377800
|
||||
IF M[T].[11:1] THEN J:=I:=-1 ELSE T:=M[T].[FF]-2; 38378000
|
||||
END; 38378200
|
||||
WRITTENON:=J; 38378400
|
||||
END; 38378600
|
||||
% 38379000
|
||||
DEFINE REW=CODE.[47:1]#,% 38380000
|
||||
KRUNCH=NOT CODE.[42:1]#, 38381000
|
||||
REL=CODE.[46:1]#,% 38382000
|
||||
TIME=CODE.[45:1]#,% 38383000
|
||||
LOCK=NOT CODE.[44:1]#,% 38384000
|
||||
PURGE=NOT CODE.[43:1]#,% 38385000
|
||||
DEFINE TECH=STATE.[46:2]#, OPENIO=FIB[13].[22:1]#, 38385400
|
||||
WRITBACK=FIB[13].[23:1]#, LASTIO=FIB[13].[46:1]#, 38385500
|
||||
WRITEAFTEREOF=FIB[13].[44:2]#, INPUT=STATE.[43:1]#; 38385600
|
||||
% 38386000
|
||||
% START OF CODE 38386010
|
||||
% 38386020
|
||||
P(RCW,MSCW,STF); RCW ~ RCW & P(XCH)[CTC]; 38387000
|
||||
HEADER ~ FIB[14]; ACCESS ~ FIB[4].[27:3]; 38388000
|
||||
IF COBOL THEN 38389000
|
||||
BEGIN IF COBOL > 0 THEN % COBOL 61 38389100
|
||||
BEGIN IF WRITBACK AND TECH=0 AND LASTIO AND 38389200
|
||||
(OPENIO OR NOT(INPUT)) THEN 38389300
|
||||
IF ACCESS=1 AND WRITEAFTEREOF!0 THEN 38389400
|
||||
BEGIN FIB[7] ~ *P(DUP) - 1; 38389500
|
||||
HEADER[7] ~ *P(DUP) - 1; 38389600
|
||||
END ELSE WRITEAFTEREOF ~ 0; 38389700
|
||||
IF TECH=0 THEN IF WRITEAFTEREOF=2 THEN 38389800
|
||||
BEGIN FIB[7] ~ *P(DUP) + 1; 38389900
|
||||
HEADER[7] ~ *P(DUP) + 1; 38390000
|
||||
END ELSE IF WRITEAFTEREOF=1 THEN 38390100
|
||||
BEGIN FIB[7] ~ *P(DUP) - 1; 38390200
|
||||
HEADER[7] ~ *P(DUP) - 1; 38390300
|
||||
END; 38390400
|
||||
WRITEAFTEREOF ~ 0; 38390500
|
||||
END; 38391000
|
||||
IF ACCESS=1 THEN % IF RANDOM 38391010
|
||||
BEGIN IF COBOL > 0 THEN % COBOL61 38391020
|
||||
BEGIN ACCESS ~ 4; 38391025
|
||||
IF FIB[13].[10:9] = 2 THEN % SEEK IN PROCESS 38391030
|
||||
BEGIN 38391035
|
||||
$ SET OMIT = NOT SHAREDISK 38391039
|
||||
COOLOFF; FIB[13].[10:9] ~ 1; 38391050
|
||||
END 38391055
|
||||
END ELSE IF FIB[17]<BLEN THEN ACCESS~4; % COBOL68 38391060
|
||||
END; 38391070
|
||||
IF FIB[13].[23:1] AND ACCESS=0 THEN 38391080
|
||||
BEGIN FIB[7]~P(DUP,LOD)-1; 38391090
|
||||
ACCESS~4; 38391100
|
||||
END; END; 38391110
|
||||
IF NOT STATE.[41:1] THEN% 38392000
|
||||
BEGIN IF ACCESS=1 THEN% 38393000
|
||||
BEGIN 38394000
|
||||
$ SET OMIT = NOT SHAREDISK 38394099
|
||||
COOLOFF; 38394300
|
||||
END ELSE% 38395000
|
||||
IF ACCESS=0 THEN% 38396000
|
||||
BEGIN COOLOFF; IF NOT STATE.[43:1] THEN% 38397000
|
||||
IF FIB[17]<BLEN AND STATE.[46:2]!0 THEN% 38398000
|
||||
BEGIN R:=SPACE(((BLEN+29) DIV 30)|30+1); 38399000
|
||||
IF (M[R]~M[FIB[16]]~% 38400000
|
||||
DISKADDRESS(MID,FID,FPB[FNUM+3],FIB[7]-1,HEADER,0)) NEQ 0 THEN % (SHM)38401000
|
||||
BEGIN 38401100
|
||||
P(WAITIO(FIB[16]&1[24:47:1]&R[33:33{15],% 38402000
|
||||
0,U(,DEL);% 38403000
|
||||
MOVE(FIB[17],R+BLEN-FIB[17]+1,% 38404000
|
||||
FIB[16] INX BLEN-FIB[17]+1);% 38405000
|
||||
P(WIATIO(FIB[16],0,U),DEL);% 38406000
|
||||
IF NOT FIB[16].[24:1] THEN HEADER[4].[11:1]~1; 38406500
|
||||
END; 38407000
|
||||
FORGETSPACE(R);% 38408000
|
||||
END;% 38409000
|
||||
END ELSE% 38410000
|
||||
BEGIN 38411000
|
||||
$ SET OMIT = NOT SHAREDISK 38411009
|
||||
COOLOFF; 38411030
|
||||
IF (FIB[17]LSS BLEN AND STATE.[46:2]NEQ 0)OR ACCESS=4 THEN38411100
|
||||
BEGIN IF ACCESS=4 THEN 38411200
|
||||
IF FIB[13].[23:1] OR NOT STATE.[43:1] THEN 38411300
|
||||
ACCESS:=2; 38411400
|
||||
IF (M[FIB[16]]:=DISKADDRESS(MID,FID,FPB[FNUM+3], % (SHM)38411500
|
||||
FIB[7],HEADER,0))=0 THEN ACCESS:=4; 38411600
|
||||
IF ACCESS!4 THEN 38411700
|
||||
BEGIN P(WAITIO(FIB[16]&0[24:24:1],0,U),DEL); 38411750
|
||||
HEADER[4].[11:1]~1; END; 38411800
|
||||
END; IF ACCESS = 4 THEN ACCESS := 2; 38411900
|
||||
END;% 38412000
|
||||
|
||||
BIN
Unisys-B5500-Software-License.pdf
Normal file
BIN
Unisys-B5500-Software-License.pdf
Normal file
Binary file not shown.
@@ -42,8 +42,8 @@ function B5500CentralControl() {
|
||||
|
||||
// Instance variables and flags
|
||||
this.poweredUp = 0; // System power indicator
|
||||
|
||||
this.unitStatusMask = 0; // Peripheral unit ready-status bitmask
|
||||
this.unitBusyMask = 0; // Peripheral unit busy-status bitmask
|
||||
|
||||
this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1
|
||||
this.inhCCI03F = 0; // 0=> allow timer interrupts; 1=> inhibit 'em
|
||||
@@ -51,7 +51,6 @@ function B5500CentralControl() {
|
||||
|
||||
this.nextTimeStamp = 0; // Next actual Date.getTime() for timer tick
|
||||
this.timer = null; // Reference to the RTC setTimeout id.
|
||||
this.loadTimer = null; // Reference to the load setTimeout id.
|
||||
|
||||
// Establish contexts for asynchronously-called methods
|
||||
this.boundTock = B5500CentralControl.bindMethod(this.tock, this);
|
||||
@@ -62,9 +61,10 @@ function B5500CentralControl() {
|
||||
/**************************************/
|
||||
/* Global constants */
|
||||
|
||||
B5500CentralControl.version = "0.06";
|
||||
B5500CentralControl.version = "0.07";
|
||||
|
||||
B5500CentralControl.rtcTick = 1000/60; // Real-time clock period, milliseconds
|
||||
B5500CentralControl.memCycles = 4; // assume 4 µs memory cycle time (the other option was 6 µs)
|
||||
B5500CentralControl.rtcTick = 1000/60; // Real-time clock period, milliseconds
|
||||
|
||||
B5500CentralControl.pow2 = [ // powers of 2 from 0 to 52
|
||||
0x1, 0x2, 0x4, 0x8,
|
||||
@@ -121,9 +121,9 @@ B5500CentralControl.unitSpecs = {
|
||||
DKB: {unitIndex: 28, designate: 12, unitClass: B5500DiskUnit},
|
||||
CRA: {unitIndex: 24, designate: 10, unitClass: B5500CardReader},
|
||||
CRB: {unitIndex: 23, designate: 14, unitClass: B5500CardReader},
|
||||
CPA: {unitIndex: 25, designate: 10, unitClass: null},
|
||||
LPA: {unitIndex: 27, designate: 22, unitClass: null},
|
||||
LPB: {unitIndex: 26, designate: 26, unitClass: null},
|
||||
CPA: {unitIndex: 25, designate: 10, unitClass: B5500CardPunch},
|
||||
LPA: {unitIndex: 27, designate: 22, unitClass: B5500DummyPrinter},
|
||||
LPB: {unitIndex: 26, designate: 26, unitClass: B5500DummyPrinter},
|
||||
PRA: {unitIndex: 20, designate: 18, unitClass: null},
|
||||
PRB: {unitIndex: 19, designate: 20, unitClass: null},
|
||||
PPA: {unitIndex: 21, designate: 18, unitClass: null},
|
||||
@@ -204,6 +204,13 @@ B5500CentralControl.prototype.clear = function clear() {
|
||||
this.P2BF = 0; // Processor 2 busy FF
|
||||
this.HP2F = 1; // Halt processor 2 FF
|
||||
|
||||
this.interruptMask = 0; // Interrupt status mask
|
||||
this.interruptLatch = 0; // Interrupt latched status (reset by console UI)
|
||||
this.iouMask = 0; // I/O Unit busy status mask
|
||||
this.iouLatch = 0; // I/O Unit busy latched status (reset by console UI)
|
||||
this.unitBusyLatch = 0; // Peripheral unit latched status (reset by console UI)
|
||||
this.unitBusyMask = 0; // Peripheral unit busy-status bitmask
|
||||
|
||||
if (this.PA) {
|
||||
this.PA.clear();
|
||||
}
|
||||
@@ -427,6 +434,11 @@ B5500CentralControl.prototype.signalInterrupt = function signalInterrupt() {
|
||||
: 0
|
||||
)
|
||||
: 0; // no interrupt set
|
||||
|
||||
if (this.IAR) {
|
||||
this.interruptMask = this.bitSet(this.interruptMask, 65-this.IAR);
|
||||
this.interruptLatch = this.bitSet(this.interruptLatch, 65-this.IAR);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -437,100 +449,107 @@ B5500CentralControl.prototype.clearInterrupt = function clearInterrupt() {
|
||||
var p1 = this.P1;
|
||||
var p2 = this.P2;
|
||||
|
||||
switch (this.IAR) {
|
||||
case 0x12: // @22: Time interval
|
||||
this.CCI03F = 0;
|
||||
break;
|
||||
case 0x13: // @23: I/O busy
|
||||
this.CCI04F = 0;
|
||||
break;
|
||||
case 0x14: // @24: Keyboard request
|
||||
this.CCI05F = 0;
|
||||
break;
|
||||
case 0x15: // @25: Printer 1 finished
|
||||
this.CCI06F = 0;
|
||||
break;
|
||||
case 0x16: // @26: Printer 2 finished
|
||||
this.CCI07F = 0;
|
||||
break;
|
||||
case 0x17: // @27: I/O 1 finished
|
||||
this.CCI08F = 0;
|
||||
this.AD1F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x18: // @30: I/O 2 finished
|
||||
this.CCI09F = 0;
|
||||
this.AD2F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x19: // @31: I/O 3 finished
|
||||
this.CCI10F = 0;
|
||||
this.AD3F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x1A: // @32: I/O 4 finished
|
||||
this.CCI11F = 0;
|
||||
this.AD4F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x1B: // @33: P2 busy
|
||||
this.CCI12F = 0;
|
||||
break;
|
||||
case 0x1C: // @34: Inquiry request
|
||||
this.CCI13F = 0;
|
||||
break;
|
||||
case 0x1D: // @35: Special interrupt 1
|
||||
this.CCI14F = 0;
|
||||
break;
|
||||
case 0x1E: // @36: Disk file 1 read check finished
|
||||
this.CCI15F = 0;
|
||||
break;
|
||||
case 0x1F: // @37: Disk file 2 read check finished
|
||||
this.CCI16F = 0;
|
||||
break;
|
||||
if (this.IAR) {
|
||||
this.interruptMask = this.bitReset(this.interruptMask, 65-this.IAR)
|
||||
switch (this.IAR) {
|
||||
case 0x12: // @22: Time interval
|
||||
this.CCI03F = 0;
|
||||
break;
|
||||
case 0x13: // @23: I/O busy
|
||||
this.CCI04F = 0;
|
||||
break;
|
||||
case 0x14: // @24: Keyboard request
|
||||
this.CCI05F = 0;
|
||||
break;
|
||||
case 0x15: // @25: Printer 1 finished
|
||||
this.CCI06F = 0;
|
||||
break;
|
||||
case 0x16: // @26: Printer 2 finished
|
||||
this.CCI07F = 0;
|
||||
break;
|
||||
case 0x17: // @27: I/O 1 finished
|
||||
this.CCI08F = 0;
|
||||
this.AD1F = 0; // make unit non-busy
|
||||
this.iouMask &= 0xE;
|
||||
break;
|
||||
case 0x18: // @30: I/O 2 finished
|
||||
this.CCI09F = 0;
|
||||
this.AD2F = 0; // make unit non-busy
|
||||
this.iouMask &= 0xD;
|
||||
break;
|
||||
case 0x19: // @31: I/O 3 finished
|
||||
this.CCI10F = 0;
|
||||
this.AD3F = 0; // make unit non-busy
|
||||
this.iouMask &= 0xB;
|
||||
break;
|
||||
case 0x1A: // @32: I/O 4 finished
|
||||
this.CCI11F = 0;
|
||||
this.AD4F = 0; // make unit non-busy
|
||||
this.iouMask &= 0x7;
|
||||
break;
|
||||
case 0x1B: // @33: P2 busy
|
||||
this.CCI12F = 0;
|
||||
break;
|
||||
case 0x1C: // @34: Inquiry request
|
||||
this.CCI13F = 0;
|
||||
break;
|
||||
case 0x1D: // @35: Special interrupt 1
|
||||
this.CCI14F = 0;
|
||||
break;
|
||||
case 0x1E: // @36: Disk file 1 read check finished
|
||||
this.CCI15F = 0;
|
||||
break;
|
||||
case 0x1F: // @37: Disk file 2 read check finished
|
||||
this.CCI16F = 0;
|
||||
break;
|
||||
|
||||
case 0x20: // @40: P2 memory parity error
|
||||
if (p2) {p2.I &= 0xFE}
|
||||
break;
|
||||
case 0x21: // @41: P2 invalid address error
|
||||
if (p2) {p2.I &= 0xFD}
|
||||
break;
|
||||
case 0x22: // @42: P2 stack overflow
|
||||
if (p2) {p2.I &= 0xFB}
|
||||
break;
|
||||
case 0x24: // @44-55: P2 syllable-dependent
|
||||
case 0x25:
|
||||
case 0x26:
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
if (p2) {p2.I &= 0x0F}
|
||||
break;
|
||||
case 0x20: // @40: P2 memory parity error
|
||||
if (p2) {p2.I &= 0xFE}
|
||||
break;
|
||||
case 0x21: // @41: P2 invalid address error
|
||||
if (p2) {p2.I &= 0xFD}
|
||||
break;
|
||||
case 0x22: // @42: P2 stack overflow
|
||||
if (p2) {p2.I &= 0xFB}
|
||||
break;
|
||||
case 0x24: // @44-55: P2 syllable-dependent
|
||||
case 0x25:
|
||||
case 0x26:
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2A:
|
||||
case 0x2B:
|
||||
case 0x2C:
|
||||
case 0x2D:
|
||||
if (p2) {p2.I &= 0x0F}
|
||||
break;
|
||||
|
||||
case 0x30: // @60: P1 memory parity error
|
||||
p1.I &= 0xFE;
|
||||
break;
|
||||
case 0x31: // @61: P1 invalid address error
|
||||
p1.I &= 0xFD;
|
||||
break;
|
||||
case 0x32: // @62: P1 stack overflow
|
||||
p1.I &= 0x0B;
|
||||
break;
|
||||
case 0x34: // @64-75: P1 syllable-dependent
|
||||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
case 0x38:
|
||||
case 0x39:
|
||||
case 0x3A:
|
||||
case 0x3B:
|
||||
case 0x3C:
|
||||
case 0x3D:
|
||||
p1.I &= 0x0F;
|
||||
break;
|
||||
case 0x30: // @60: P1 memory parity error
|
||||
p1.I &= 0xFE;
|
||||
break;
|
||||
case 0x31: // @61: P1 invalid address error
|
||||
p1.I &= 0xFD;
|
||||
break;
|
||||
case 0x32: // @62: P1 stack overflow
|
||||
p1.I &= 0x0B;
|
||||
break;
|
||||
case 0x34: // @64-75: P1 syllable-dependent
|
||||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
case 0x38:
|
||||
case 0x39:
|
||||
case 0x3A:
|
||||
case 0x3B:
|
||||
case 0x3C:
|
||||
case 0x3D:
|
||||
p1.I &= 0x0F;
|
||||
break;
|
||||
|
||||
default: // no interrupt vector was set
|
||||
break;
|
||||
default: // no interrupt vector was set
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.signalInterrupt();
|
||||
};
|
||||
@@ -551,7 +570,7 @@ B5500CentralControl.prototype.tock = function tock() {
|
||||
}
|
||||
}
|
||||
interval = (this.nextTimeStamp += B5500CentralControl.rtcTick) - thisTime;
|
||||
this.timer = setTimeout(this.boundTock, (interval < 0 ? 1 : interval));
|
||||
this.timer = setTimeout(this.boundTock, (interval < 1 ? 1 : interval));
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -588,15 +607,23 @@ B5500CentralControl.prototype.initiateIO = function initiateIO() {
|
||||
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
this.AD1F = 1;
|
||||
this.iouMask |= 0x1;
|
||||
this.iouLatch |= 0x1;
|
||||
this.IO1.initiate();
|
||||
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
|
||||
this.AD2F = 1;
|
||||
this.iouMask |= 0x2;
|
||||
this.iouLatch |= 0x2;
|
||||
this.IO2.initiate();
|
||||
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
|
||||
this.AD3F = 1;
|
||||
this.iouMask |= 0x4;
|
||||
this.iouLatch |= 0x4;
|
||||
this.IO3.initiate();
|
||||
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
|
||||
this.AD4F = 1;
|
||||
this.iouMask |= 0x8;
|
||||
this.iouLatch |= 0x8;
|
||||
this.IO4.initiate();
|
||||
} else {
|
||||
this.CCI04F = 1; // set I/O busy interrupt
|
||||
@@ -651,11 +678,42 @@ B5500CentralControl.prototype.setUnitBusy = function setUnitBusy(index, busy) {
|
||||
/* Sets or resets the unit-busy mask bit for unit index "index" */
|
||||
|
||||
if (index) {
|
||||
this.unitBusyMask = (busy ? this.bitSet(this.unitBusyMask, index)
|
||||
: this.bitReset(this.unitBusyMask, index));
|
||||
if (busy) {
|
||||
this.unitBusyMask = this.bitSet(this.unitBusyMask, index);
|
||||
this.unitBusyLatch = this.bitSet(this.unitBusyLatch, index);
|
||||
} else {
|
||||
this.unitBusyMask = this.bitReset(this.unitBusyMask, index);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fetchInterruptLatch = function fetchInterruptLatch() {
|
||||
/* Returns and resets this.interruptLatch; used by console UI */
|
||||
var latch = this.interruptLatch;
|
||||
|
||||
this.interruptLatch = this.interruptMask;
|
||||
return latch;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fetchIOUnitLatch = function fetchIOUnitLatch() {
|
||||
/* Returns and resets this.iouLatch; used by console UI */
|
||||
var latch = this.iouLatch;
|
||||
|
||||
this.iouLatch = this.iouMask;
|
||||
return latch;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.fetchUnitBusyLatch = function fetchUnitBusyLatch() {
|
||||
/* Returns and resets this.unitBusyLatch; used by console UI */
|
||||
var latch = this.unitBusyLatch;
|
||||
|
||||
this.unitBusyLatch = this.unitBusyMask;
|
||||
return latch;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.halt = function halt() {
|
||||
/* Halts the processors. Any in-process I/Os are allowed to complete */
|
||||
@@ -664,10 +722,6 @@ B5500CentralControl.prototype.halt = function halt() {
|
||||
clearTimeout(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
if (this.loadTimer) {
|
||||
clearTimeout(this.loadTimer);
|
||||
this.loadTimer = null;
|
||||
}
|
||||
|
||||
if (this.PA && this.PA.busy) {
|
||||
this.PA.busy = 0;
|
||||
@@ -698,22 +752,25 @@ B5500CentralControl.prototype.loadComplete = function loadComplete(dontStart) {
|
||||
completed = true;
|
||||
this.CCI08F = 0;
|
||||
this.AD1F = 0;
|
||||
this.iouMask &= 0xE;
|
||||
} else if (this.CCI09F) { // I/O Unit 2 finished
|
||||
completed = true;
|
||||
this.CCI09F = 0;
|
||||
this.AD2F = 0;
|
||||
this.iouMask &= 0xD;
|
||||
} else if (this.CCI10F) { // I/O Unit 3 finished
|
||||
completed = true;
|
||||
this.CCI10F = 0;
|
||||
this.AD3F = 0;
|
||||
this.iouMask &= 0xB;
|
||||
} else if (this.CCI11F) { // I/O Unit 4 finished
|
||||
completed = true;
|
||||
this.CCI11F = 0;
|
||||
this.AD4F = 0;
|
||||
this.iouMask &= 0x7;
|
||||
}
|
||||
|
||||
if (completed) {
|
||||
this.loadTimer = null;
|
||||
this.LOFF = 0;
|
||||
this.P1.preset(0x10); // start execution at C=@20
|
||||
if (!dontStart) {
|
||||
@@ -737,15 +794,23 @@ B5500CentralControl.prototype.load = function load(dontStart) {
|
||||
this.LOFF = 1;
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
this.AD1F = 1;
|
||||
this.iouMask |= 0x1;
|
||||
this.iouLatch |= 0x1;
|
||||
this.IO1.initiateLoad(this.cardLoadSelect, boundLoadComplete);
|
||||
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
|
||||
this.AD2F = 1;
|
||||
this.iouMask |= 0x2;
|
||||
this.iouLatch |= 0x2;
|
||||
this.IO2.initiateLoad(this.cardLoadSelect, boundLoadComplete);
|
||||
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
|
||||
this.AD3F = 1;
|
||||
this.iouMask |= 0x4;
|
||||
this.iouLatch |= 0x4;
|
||||
this.IO3.initiateLoad(this.cardLoadSelect, boundLoadComplete);
|
||||
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
|
||||
this.AD4F = 1;
|
||||
this.iouMask |= 0x8;
|
||||
this.iouLatch |= 0x8;
|
||||
this.IO4.initiateLoad(this.cardLoadSelect, boundLoadComplete);
|
||||
} else {
|
||||
this.CCI04F = 1; // set I/O busy interrupt
|
||||
@@ -815,7 +880,6 @@ B5500CentralControl.prototype.runTest = function runTest(runAddr) {
|
||||
(typically 0x10 [octal 20]) */
|
||||
|
||||
this.clear();
|
||||
this.loadTimer = null;
|
||||
this.LOFF = 0;
|
||||
this.P1.preset(runAddr);
|
||||
this.P1.start();
|
||||
@@ -850,28 +914,26 @@ B5500CentralControl.prototype.configureSystem = function configureSystem() {
|
||||
break;
|
||||
case "LPA":
|
||||
return function signalLPA() {
|
||||
cc.setUnitBusy(27, 0);
|
||||
cc.CCI06F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "LPB":
|
||||
return function signalLPB() {
|
||||
cc.setUnitBusy(26, 0);
|
||||
cc.CCI07F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "DKA":
|
||||
return function signalDKA() {
|
||||
cc.setUnitBusy(29, 0);
|
||||
cc.setUnitBusy(29, 0); // Is this needed here ??
|
||||
cc.CCI15F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
break;
|
||||
case "DKB":
|
||||
return function signalDKB() {
|
||||
cc.setUnitBusy(28, 0);
|
||||
cc.setUnitBusy(28, 0); // Is this needed here ??
|
||||
cc.CCI16F = 1;
|
||||
cc.signalInterrupt();
|
||||
};
|
||||
|
||||
@@ -73,9 +73,6 @@ function B5500IOUnit(ioUnitID, cc) {
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500IOUnit.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
B5500IOUnit.memCycles = 6; // assume 6 us memory cycle time (the other option was 4 usec)
|
||||
|
||||
B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
|
||||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // 00-07, @00-07
|
||||
0x38,0x39,0x23,0x40,0x3F,0x3A,0x3E,0x7D, // 08-1F, @10-17
|
||||
@@ -219,7 +216,7 @@ B5500IOUnit.prototype.fetch = function fetch(addr) {
|
||||
this.cc.fetch(acc);
|
||||
this.W = acc.word;
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // set memory address error
|
||||
return 1;
|
||||
@@ -241,7 +238,7 @@ B5500IOUnit.prototype.store = function store(addr) {
|
||||
acc.word = this.W;
|
||||
this.cc.store(acc);
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // set memory address error
|
||||
return 1;
|
||||
@@ -699,12 +696,18 @@ B5500IOUnit.prototype.initiatePrinterIO = function initiatePrinterIO(u) {
|
||||
this.D30F = 1; // can't read from the printer
|
||||
this.finish();
|
||||
} else {
|
||||
memWords = this.DwordCount;
|
||||
if (memWords > 0) {
|
||||
chars = memWords*8;
|
||||
if (this.D18F) {
|
||||
chars = memWords = 0;
|
||||
} else {
|
||||
memWords = 17; // assume a 132-character printer
|
||||
chars = 132;
|
||||
memWords = (this.D23F ? this.DwordCount : 0);
|
||||
if (memWords > 0) {
|
||||
chars = memWords*8;
|
||||
} else {
|
||||
memWords = 17; // assume a 132-character printer
|
||||
chars = 132;
|
||||
}
|
||||
this.fetchBuffer(1, memWords);
|
||||
this.Daddress = (addr-1) & 0x7FFF; // printer accesses memory backwards, so final address is initial-1
|
||||
}
|
||||
cc = this.LP;
|
||||
if (cc & 0x0F) {
|
||||
@@ -716,10 +719,8 @@ B5500IOUnit.prototype.initiatePrinterIO = function initiatePrinterIO(u) {
|
||||
} else {
|
||||
cc = 0; // zero space after print
|
||||
}
|
||||
this.fetchBuffer(1, memWords);
|
||||
this.DwordCount = memWords*32; // actual word count in D.[8:5], D.[13:5]=0
|
||||
this.Daddress = addr-1; // printer accesses memory backwards, so final address is initial-1
|
||||
u.write(this.boundFinishBusy, this.buffer, chars, 0, cc);
|
||||
u.write(this.boundFinishGeneric, this.buffer, chars, 0, cc);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -779,8 +780,11 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
if (this.D24F) { // CRA
|
||||
u.read(this.boundFinishGenericRead, this.buffer, (this.D21F ? 160 : 80), this.D21F, 0);
|
||||
} else { // CPA
|
||||
this.D30F = 1; // >>> temp until CPA implemented <<<
|
||||
this.finish();
|
||||
this.fetchBuffer(1, 10);
|
||||
this.D21F = 0; // force alpha mode
|
||||
this.DwordCount = 10; // word count to 10
|
||||
x = (this.D % 0x10000) >>> 15; // D32F = select alternate stacker
|
||||
u.write(this.boundFinishGeneric, this.buffer, 80, 0, x);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -893,7 +897,7 @@ B5500IOUnit.prototype.initiateLoad = function initiateLoad(cardLoadSelect, loadC
|
||||
if (cardLoadSelect) {
|
||||
this.D = 0x0A0004800010; // unit 10, read, binary mode, addr @00020
|
||||
this.Dunit = 10; // 10=CRA
|
||||
this.D24F = 1; // read
|
||||
this.D21F = 1; // binary mode
|
||||
chars = 20*8;
|
||||
} else {
|
||||
this.D = 0x0600009F8010; // unit 6, read, alpha mode, 63 segs, addr @00020
|
||||
|
||||
@@ -52,8 +52,7 @@ function B5500Processor(procID, cc) {
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500Processor.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
B5500Processor.memCycles = 6; // assume 6 us memory cycle time (the other option was 4 usec)
|
||||
B5500Processor.timeSlice = 16000; // Standard run() timeslice in clocks (about 16ms, we hope)
|
||||
|
||||
B5500Processor.collation = [ // index by BIC to get collation value
|
||||
53, 54, 55, 56, 57, 58, 59, 60, // @00: 0 1 2 3 4 5 6 7
|
||||
@@ -112,9 +111,9 @@ B5500Processor.prototype.clear = function clear() {
|
||||
this.cycleCount = 0; // Current cycle count for this.run()
|
||||
this.cycleLimit = 0; // Cycle limit for this.run()
|
||||
this.totalCycles = 0; // Total cycles executed on this processor
|
||||
this.procStart = 0; // Javascript time that the processor started running, µs
|
||||
this.procTime = 0; // Total processor running time, based on cycles executed, µs
|
||||
this.procSlack = 0; // Total processor throttling delay, µs
|
||||
this.procStart = 0; // Javascript time that the processor started running, ms
|
||||
this.procTime = 0; // Total processor running time, ms
|
||||
this.procSlack = 0; // Total processor throttling delay, ms
|
||||
this.busy = 0; // Processor is running, not idle or halted
|
||||
};
|
||||
|
||||
@@ -144,7 +143,7 @@ B5500Processor.prototype.loadAviaS = function loadAviaS() {
|
||||
acc.addr = this.S;
|
||||
acc.MAIL = (this.S < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -162,7 +161,7 @@ B5500Processor.prototype.loadBviaS = function loadBviaS() {
|
||||
acc.addr = this.S;
|
||||
acc.MAIL = (this.S < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -180,7 +179,7 @@ B5500Processor.prototype.loadAviaM = function loadAviaM() {
|
||||
acc.addr = this.M;
|
||||
acc.MAIL = (this.M < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -198,7 +197,7 @@ B5500Processor.prototype.loadBviaM = function loadBviaM() {
|
||||
acc.addr = this.M;
|
||||
acc.MAIL = (this.M < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -216,7 +215,7 @@ B5500Processor.prototype.loadMviaM = function loadMviaM() {
|
||||
acc.addr = this.M;
|
||||
acc.MAIL = (this.M < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -234,7 +233,7 @@ B5500Processor.prototype.loadPviaC = function loadPviaC() {
|
||||
acc.MAIL = (this.C < 0x0200 && this.NCSF);
|
||||
this.cc.fetch(acc);
|
||||
this.PROF = 1; // PROF gets set even for invalid address
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
} else {
|
||||
@@ -252,7 +251,7 @@ B5500Processor.prototype.storeAviaS = function storeAviaS() {
|
||||
acc.MAIL = (this.S < 0x0200 && this.NCSF);
|
||||
acc.word = this.A;
|
||||
this.cc.store(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
}
|
||||
@@ -268,7 +267,7 @@ B5500Processor.prototype.storeBviaS = function storeBviaS() {
|
||||
acc.MAIL = (this.S < 0x0200 && this.NCSF);
|
||||
acc.word = this.B;
|
||||
this.cc.store(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
}
|
||||
@@ -284,7 +283,7 @@ B5500Processor.prototype.storeAviaM = function storeAviaM() {
|
||||
acc.MAIL = (this.M < 0x0200 && this.NCSF);
|
||||
acc.word = this.A;
|
||||
this.cc.store(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
}
|
||||
@@ -300,7 +299,7 @@ B5500Processor.prototype.storeBviaM = function storeBviaM() {
|
||||
acc.MAIL = (this.M < 0x0200 && this.NCSF);
|
||||
acc.word = this.B;
|
||||
this.cc.store(acc);
|
||||
this.cycleCount += B5500Processor.memCycles;
|
||||
this.cycleCount += B5500CentralControl.memCycles;
|
||||
if (acc.MAED || acc.MPED) {
|
||||
this.accessError();
|
||||
}
|
||||
@@ -1344,7 +1343,7 @@ B5500Processor.prototype.start = function start() {
|
||||
/* Initiates the processor by scheduling it on the Javascript thread */
|
||||
|
||||
this.busy = 1;
|
||||
this.procTime = this.procStart = new Date().getTime()*1000;
|
||||
this.procStart = new Date().getTime();
|
||||
this.scheduler = setTimeout(this.boundSchedule, 0);
|
||||
};
|
||||
|
||||
@@ -2136,7 +2135,7 @@ B5500Processor.prototype.doublePrecisionAdd = function doublePrecisionAdd(adding
|
||||
var xb; // extended mantissa for B
|
||||
|
||||
// Estimate some general overhead and account for stack manipulation we don't do
|
||||
this.cycleCount += B5500Processor.memCycles*4 + 8;
|
||||
this.cycleCount += B5500CentralControl.memCycles*4 + 8;
|
||||
|
||||
this.adjustABFull(); // extract the top (A) operand fields:
|
||||
ma = this.A % 0x8000000000; // extract the A mantissa
|
||||
@@ -2363,8 +2362,9 @@ B5500Processor.prototype.computeRelativeAddr = function computeRelativeAddr(offs
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.presenceTest = function presenceTest(word) {
|
||||
/* Tests and returns the presence bit [2:1] of the "word" parameter. If
|
||||
0, the p-bit interrupt is set; otherwise no further action */
|
||||
/* Tests and returns the presence bit [2:1] of the "word" parameter,
|
||||
which it assumes is a control word. If [2:1] is 0, the p-bit interrupt
|
||||
is set; otherwise no further action */
|
||||
|
||||
if (word % 0x400000000000 >= 0x200000000000) {
|
||||
return 1;
|
||||
@@ -2629,11 +2629,11 @@ B5500Processor.prototype.enterCharModeInline = function enterCharModeInline() {
|
||||
|
||||
// execute the portion of CM XX04=RDA operator starting at J=2
|
||||
this.S = bw % 0x8000;
|
||||
if (bw >= 0x800000000000) { // if it's a descriptor,
|
||||
this.K = 0; // force K to zero and
|
||||
this.presenceTest(bw); // just take the side effect of any p-bit interrupt
|
||||
if (bw < 0x800000000000) { // if it's an operand
|
||||
this.K = (bw % 0x40000) >>> 15; // set K from [30:3]
|
||||
} else {
|
||||
this.K = (bw % 0x40000) >>> 15;
|
||||
this.K = 0; // otherwise, force K to zero and
|
||||
this.presenceTest(bw); // just take the side effect of any p-bit interrupt
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2726,7 +2726,7 @@ B5500Processor.prototype.exitSubroutine = function exitSubroutine(inline) {
|
||||
do {
|
||||
this.S = (this.B % 0x40000000) >>> 15;
|
||||
this.loadBviaS(); // B = [S], fetch prior MSCW
|
||||
} while ((this.B % 0x100000000 - this.B % 0x80000000)/0x80000000 == 1); // MSFF
|
||||
} while ((this.B % 0x100000000 - this.B % 0x80000000)/0x80000000); // MSFF
|
||||
this.S = this.R*64 + 7;
|
||||
this.storeBviaS(); // [S] = B, store last MSCW at [R]+7
|
||||
}
|
||||
@@ -2916,11 +2916,11 @@ B5500Processor.prototype.run = function run() {
|
||||
this.loadBviaS(); // B = [S]
|
||||
this.BROF = 0;
|
||||
this.S = (t1 = this.B) % 0x8000;
|
||||
if (t1 >= 0x800000000000) { // if it's a descriptor,
|
||||
this.K = 0; // force K to zero and
|
||||
this.presenceTest(t1); // just take the side effect of any p-bit interrupt
|
||||
if (t1 < 0x800000000000) { // if it's an operand,
|
||||
this.K = (t1 % 0x40000) >>> 15;// set K from [30:3]
|
||||
} else {
|
||||
this.K = (t1 % 0x40000) >>> 15;
|
||||
this.K = 0; // otherwise, force K to zero and
|
||||
this.presenceTest(t1); // just take the side effect of any p-bit interrupt
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3300,15 +3300,16 @@ B5500Processor.prototype.run = function run() {
|
||||
this.S = this.F - variant;
|
||||
this.loadBviaS(); // B = [S]
|
||||
this.S = t1;
|
||||
if (this.B >= 0x800000000000) { // if it's a descriptor,
|
||||
if (this.presenceTest(this.B)) {// if present, initiate a fetch to P
|
||||
t2 = this.B;
|
||||
if (t2 >= 0x800000000000) { // if it's a descriptor,
|
||||
if (this.presenceTest(t2)) { // if present, initiate a fetch to P
|
||||
this.C = this.B % 0x8000; // get the word address,
|
||||
this.L = 0; // force L to zero and
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
}
|
||||
} else {
|
||||
this.C = this.B % 0x8000;
|
||||
t1 = (this.B % 0x4000000000 - this.B % 0x1000000000)/0x1000000000;
|
||||
this.C = t2 % 0x8000;
|
||||
t1 = (t2 % 0x4000000000 - t2 % 0x1000000000)/0x1000000000;
|
||||
if (t1 < 3) { // if not a descriptor, increment the address
|
||||
this.L = t1+1;
|
||||
} else {
|
||||
@@ -3370,12 +3371,13 @@ B5500Processor.prototype.run = function run() {
|
||||
this.H = 0;
|
||||
this.M = this.F - variant;
|
||||
this.loadBviaM(); // B = [M]
|
||||
this.M = this.B % 0x8000;
|
||||
if (this.B >= 0x800000000000) { // if it's a descriptor,
|
||||
this.G = 0; // force G to zero and
|
||||
this.presenceTest(this.B); // just take the side effect of any p-bit interrupt
|
||||
} else { // it's an operand
|
||||
this.G = (this.B % 0x40000) >>> 15;
|
||||
t1 = this.B;
|
||||
this.M = t1 % 0x8000;
|
||||
if (t1 < 0x800000000000) { // if it's an operand,
|
||||
this.G = (t1 % 0x40000) >>> 15; // set G from [30:3]
|
||||
} else { //
|
||||
this.G = 0; // otherwise, force G to zero and
|
||||
this.presenceTest(t1); // just take the side effect of any p-bit interrupt
|
||||
}
|
||||
this.B = this.A; // restore B from A
|
||||
this.BROF = this.AROF;
|
||||
@@ -4211,20 +4213,24 @@ B5500Processor.prototype.run = function run() {
|
||||
|
||||
case 0x02: // 0235: RTN=return normal
|
||||
this.adjustAFull();
|
||||
this.S = this.F;
|
||||
this.loadBviaS(); // B = [S], fetch the RCW
|
||||
switch (this.exitSubroutine(0)) {
|
||||
case 0:
|
||||
this.X = 0;
|
||||
this.operandCall();
|
||||
break;
|
||||
case 1:
|
||||
this.Q |= 0x10; // set Q05F, for display only
|
||||
this.X = 0;
|
||||
this.descriptorCall();
|
||||
break;
|
||||
case 2: // flag-bit interrupt occurred, do nothing
|
||||
break;
|
||||
// If A is an operand or a present descriptor, proceed with the return,
|
||||
// otherwise throw a p-bit interrupt (this isn't well-documented)
|
||||
if (this.A < 0x800000000000 || this.presenceTest(this.A)) {
|
||||
this.S = this.F;
|
||||
this.loadBviaS(); // B = [S], fetch the RCW
|
||||
switch (this.exitSubroutine(0)) {
|
||||
case 0:
|
||||
this.X = 0;
|
||||
this.operandCall();
|
||||
break;
|
||||
case 1:
|
||||
this.Q |= 0x10; // set Q05F, for display only
|
||||
this.X = 0;
|
||||
this.descriptorCall();
|
||||
break;
|
||||
case 2: // flag-bit interrupt occurred, do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4237,20 +4243,24 @@ B5500Processor.prototype.run = function run() {
|
||||
|
||||
case 0x0A: // 1235: RTS=return special
|
||||
this.adjustAFull();
|
||||
// Note that RTS assumes the RCW is pointed to by S, not F
|
||||
this.loadBviaS(); // B = [S], fetch the RCW
|
||||
switch (this.exitSubroutine(0)) {
|
||||
case 0:
|
||||
this.X = 0;
|
||||
this.operandCall();
|
||||
break;
|
||||
case 1:
|
||||
this.Q |= 0x10; // set Q05F, for display only
|
||||
this.X = 0;
|
||||
this.descriptorCall();
|
||||
break;
|
||||
case 2: // flag-bit interrupt occurred, do nothing
|
||||
break;
|
||||
// If A is an operand or a present descriptor, proceed with the return,
|
||||
// otherwise throw a p-bit interrupt (this isn't well-documented)
|
||||
if (this.A < 0x800000000000 || this.presenceTest(this.A)) {
|
||||
// Note that RTS assumes the RCW is pointed to by S, not F
|
||||
this.loadBviaS(); // B = [S], fetch the RCW
|
||||
switch (this.exitSubroutine(0)) {
|
||||
case 0:
|
||||
this.X = 0;
|
||||
this.operandCall();
|
||||
break;
|
||||
case 1:
|
||||
this.Q |= 0x10; // set Q05F, for display only
|
||||
this.X = 0;
|
||||
this.descriptorCall();
|
||||
break;
|
||||
case 2: // flag-bit interrupt occurred, do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4536,7 +4546,7 @@ B5500Processor.prototype.run = function run() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ((this.cycleCount += 2) < this.cycleLimit);
|
||||
} while ((this.cycleCount += 1) < this.cycleLimit);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -4548,10 +4558,13 @@ B5500Processor.prototype.schedule = function schedule() {
|
||||
each and calls run() to execute at most that number of cycles. run()
|
||||
counts up cycles until it reaches this limit or some terminating event
|
||||
(such as a halt), then exits back here. If the processor remains active,
|
||||
this routine will reschedule itself for an appropriate later time, thereby
|
||||
this routine will reschedule itself after an appropriate delay, thereby
|
||||
throttling the performance and allowing other modules a chance at the
|
||||
Javascript execution thread. */
|
||||
var delayTime;
|
||||
Javascript execution thread */
|
||||
var delayTime; // delay until next run() for this processor, ms
|
||||
var elapsedTime; // elapsed real time for this run() call, ms
|
||||
var startTime = new Date().getTime(); // starting time for this run() call, ms
|
||||
var stopTime; // ending time for this run() call, ms
|
||||
|
||||
this.scheduler = null;
|
||||
this.cycleLimit = B5500Processor.timeSlice;
|
||||
@@ -4559,12 +4572,14 @@ B5500Processor.prototype.schedule = function schedule() {
|
||||
|
||||
this.run(); // execute syllables for the timeslice
|
||||
|
||||
stopTime = new Date().getTime();
|
||||
elapsedTime = stopTime - startTime;
|
||||
this.procTime += elapsedTime;
|
||||
this.totalCycles += this.cycleCount;
|
||||
this.procTime += this.cycleCount;
|
||||
if (this.busy) {
|
||||
delayTime = this.procTime - new Date().getTime()*1000;
|
||||
delayTime = this.cycleCount/1000 - elapsedTime;
|
||||
this.procSlack += delayTime;
|
||||
this.scheduler = setTimeout(this.boundSchedule, (delayTime > 0 ? delayTime/1000 : 1));
|
||||
this.scheduler = setTimeout(this.boundSchedule, (delayTime > 0 ? delayTime : 1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ var B5500SystemConfiguration = {
|
||||
DKB: false, // Disk File Control B
|
||||
CRA: true, // Card Reader A
|
||||
CRB: false, // Card Reader B
|
||||
CPA: false, // Card Punch A
|
||||
LPA: false, // Line Printer A
|
||||
CPA: true, // Card Punch A
|
||||
LPA: true, // Line Printer A
|
||||
LPB: false, // Line Printer B
|
||||
PRA: false, // Paper Tape Reader A
|
||||
PRB: false, // Paper Tape Reader B
|
||||
|
||||
59
index.css
Normal file
59
index.css
Normal file
@@ -0,0 +1,59 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator index.css
|
||||
************************************************************************
|
||||
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 emulator test site home page style sheet.
|
||||
************************************************************************
|
||||
* 2013-06-18 P.Kimpel
|
||||
* Original version, from B5500Console.css.
|
||||
***********************************************************************/
|
||||
|
||||
BODY {
|
||||
position: relative;
|
||||
max-width: 80ex;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: medium;
|
||||
margin: 4px}
|
||||
|
||||
H1 {
|
||||
margin-top: 18pt;
|
||||
margin-bottom: 6pt;
|
||||
vertical-align: middle;
|
||||
font-size: larger;
|
||||
font-weight: bold}
|
||||
|
||||
H2 {
|
||||
margin-top: 12pt;
|
||||
margin-bottom: 0;
|
||||
font-size: medium;
|
||||
font-weight: bold}
|
||||
|
||||
UL {
|
||||
margin-top: 6pt;
|
||||
margin-bottom: 6pt}
|
||||
|
||||
UL LI {
|
||||
margin-top: 3pt;
|
||||
margin-bottom: 3pt}
|
||||
|
||||
.center {
|
||||
text-align: center}
|
||||
|
||||
.data {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: left}
|
||||
.number {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: right}
|
||||
|
||||
IMG#retroButton {
|
||||
float: right}
|
||||
|
||||
DIV#footerDiv {
|
||||
position: fixed;
|
||||
bottom: 1ex;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: xx-small}
|
||||
45
index.html
Normal file
45
index.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>retro-B5500 Emulator Test Site</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="index.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<img id=retroButton src="./webUI/retro-Button-Logo.png" alt="retro yellow button logo">
|
||||
|
||||
<h1><img src="./webUI/retro-B5500-Logo.png" alt="retro logo">
|
||||
<hr>
|
||||
Burroughs B5500 Emulator Test Site
|
||||
</h1>
|
||||
|
||||
<p>This site hosts the current test version of the retro-B5500 emulator, a web-browser based emulator for the legendary Burroughs B5500 system of the 1960s.
|
||||
|
||||
<h2>Main Links</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="./webUI/B5500Console.html">B5500 Console</a>
|
||||
<br>Opens the B5500 operations console to run the emulator
|
||||
|
||||
<li><a href="./SoftwareRequest.html">B5500 Mark-XIII System Software</a>
|
||||
<br>Provides access to tape images of B5500 system software for the Mark-XIII (1971) software release.
|
||||
|
||||
<li><a href="./HelpMenu.html">Help</a>
|
||||
<br>Opens a menu for information resources to assist you in setting up and operating the emulator.
|
||||
|
||||
<li><a href="https://code.google.com/p/retro-b5500/">Open Source Project</a>
|
||||
<br>Source code, downloads, and other developer resources for the project on Google Code.
|
||||
|
||||
<li><a href="http://retro-b5500.blogspot.com/">Project Blog</a>
|
||||
<br>Opens a menu for information resources to assist you in setting up and operating the emulator.
|
||||
</ul>
|
||||
|
||||
|
||||
<div id=footerDiv>
|
||||
Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
139
webUI/B5500CardPunch.css
Normal file
139
webUI/B5500CardPunch.css
Normal file
@@ -0,0 +1,139 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500CardPunch.css
|
||||
************************************************************************
|
||||
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 emulator Card Punch web interface style sheet.
|
||||
************************************************************************
|
||||
* 2013-06-16 P.Kimpel
|
||||
* Original version, from B5500CardReader.css.
|
||||
***********************************************************************/
|
||||
|
||||
BODY {
|
||||
position: relative;
|
||||
color: white;
|
||||
background-color: black;
|
||||
font-family: Arial, Helventica, sans-serif;
|
||||
font-size: 9pt;
|
||||
margin: 4px}
|
||||
|
||||
PRE {
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}
|
||||
|
||||
DIV#CPDiv {
|
||||
position: relative;
|
||||
color: white;
|
||||
background-color: #666;
|
||||
width: 700px;
|
||||
height: 300px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
vertical-align: top}
|
||||
|
||||
BUTTON.greenButton {
|
||||
background-color: #060;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.redButton {
|
||||
background-color: #900;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
border: 1px solid #DDD;
|
||||
border-radius: 4px}
|
||||
|
||||
BUTTON.greenLit {
|
||||
background-color: green}
|
||||
|
||||
BUTTON.redLit {
|
||||
background-color: #F00}
|
||||
|
||||
#CPNotReadyLight {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px}
|
||||
|
||||
#CPRunoutBtn {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 76px}
|
||||
|
||||
#CPStopBtn {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 144px}
|
||||
|
||||
#CPStartBtn {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 212px;}
|
||||
|
||||
#CPStacker1Div {
|
||||
position: absolute;
|
||||
top: 56px;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 160px;
|
||||
font-weight: bold}
|
||||
|
||||
#CPStacker1Bar {
|
||||
border: 1px solid white;
|
||||
width: 610px}
|
||||
|
||||
#CPStacker1Frame {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-weight: normal}
|
||||
|
||||
#CPStacker2Div {
|
||||
position: absolute;
|
||||
top: 220px;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 70px;
|
||||
font-weight: bold}
|
||||
|
||||
#CPStacker2Bar {
|
||||
border: 1px solid white;
|
||||
width: 610px}
|
||||
|
||||
#CPStacker2Frame {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 10pt;
|
||||
font-weight: normal}
|
||||
|
||||
32
webUI/B5500CardPunch.html
Normal file
32
webUI/B5500CardPunch.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>B5500 Emulator Card Punch</title>
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<!-- 2013-06-16 Original version, cloned from B5500CardReader.html -->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500CardPunch.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id=CPDiv>
|
||||
<button id=CPNotReadyLight class="redButton redLit">NOT READY</button>
|
||||
<button id=CPRunoutBtn class="redButton">RUNOUT</button>
|
||||
<button id=CPStopBtn class="redButton">STOP</button>
|
||||
<button id=CPStartBtn class="greenButton">START</button>
|
||||
|
||||
<div id=CPStacker1Div>
|
||||
Stacker 1 <progress id=CPStacker1Bar min=0 max=100 value=0></progress>
|
||||
<iframe id=CPStacker1Frame scrolling=auto></iframe>
|
||||
</div>
|
||||
|
||||
<div id=CPStacker2Div>
|
||||
Stacker 2 <progress id=CPStacker2Bar min=0 max=100 value=0></progress>
|
||||
<iframe id=CPStacker2Frame scrolling=auto></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
322
webUI/B5500CardPunch.js
Normal file
322
webUI/B5500CardPunch.js
Normal file
@@ -0,0 +1,322 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500CardPunch.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 Card Punch Peripheral Unit module.
|
||||
*
|
||||
* Defines a card punch peripheral unit type.
|
||||
*
|
||||
************************************************************************
|
||||
* 2013-06-16 P.Kimpel
|
||||
* Original version, from B5500CardReader.js & B5500DummyPrinter.js.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the CardPunch object */
|
||||
var that = this;
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
this.designate = designate; // IOD unit designate number
|
||||
this.statusChange = statusChange; // external function to call for ready-status change
|
||||
this.signal = signal; // external function to call for special signals (not used here)
|
||||
|
||||
this.clear();
|
||||
|
||||
this.window = window.open("", mnemonic);
|
||||
if (this.window) {
|
||||
this.window.close(); // destroy the previously-existing window
|
||||
this.window = null;
|
||||
}
|
||||
this.doc = null;
|
||||
this.stacker1 = null;
|
||||
this.endOfStacker1 = null;
|
||||
this.stacker2 = null;
|
||||
this.endOfStacker2 = null;
|
||||
this.window = window.open("/B5500/webUI/B5500CardPunch.html", mnemonic,
|
||||
"scrollbars=no,resizable,width=700,height=500");
|
||||
this.window.addEventListener("load", function() {
|
||||
that.punchOnload();
|
||||
}, false);
|
||||
}
|
||||
|
||||
B5500CardPunch.prototype.cardsPerMinute = 300; // Punch speed
|
||||
B5500CardPunch.prototype.maxScrollLines = 800; // Maximum punch stacker scrollback (stacker capacity)
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.$$ = function $$(e) {
|
||||
return this.doc.getElementById(e);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the punch unit state */
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
|
||||
this.runoutArmed = false; // EOF button: armed state
|
||||
this.stopCount = 0; // stopCount for clearing the input buffer
|
||||
this.stacker1Count = 0; // cards in stacker #1
|
||||
this.stacker2Count = 0; // cards in stacker #2
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.hasClass = function hasClass(e, name) {
|
||||
/* returns true if element "e" has class "name" in its class list */
|
||||
var classes = e.className;
|
||||
|
||||
if (!e) {
|
||||
return false;
|
||||
} else if (classes == name) {
|
||||
return true;
|
||||
} else {
|
||||
return (classes.search("\\b" + name + "\\b") >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.addClass = function addClass(e, name) {
|
||||
/* Adds a class "name" to the element "e"s class list */
|
||||
|
||||
if (!this.hasClass(e, name)) {
|
||||
e.className += (" " + name);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.removeClass = function removeClass(e, name) {
|
||||
/* Removes the class "name" from the element "e"s class list */
|
||||
|
||||
e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), "");
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.setPunchReady = function setPunchReady(ready) {
|
||||
/* Controls the ready-state of the card punch */
|
||||
|
||||
if (ready && !this.ready) {
|
||||
this.statusChange(1);
|
||||
this.removeClass(this.$$("CPNotReadyLight"), "redLit");
|
||||
this.ready = true;
|
||||
if (this.runoutArmed) {
|
||||
if (this.stacker1Count || this.stacker2Count) {
|
||||
if (this.window.confirm("Empty both " + this.mnemonic + " stackers?")) {
|
||||
this.stacker1Count = this.stacker2Count = 0;
|
||||
this.$$("CPStacker1Bar").value = 0;
|
||||
this.$$("CPStacker2Bar").value = 0;
|
||||
while (this.stacker1.firstChild) {
|
||||
this.stacker1.removeChild(this.stacker1.firstChild);
|
||||
}
|
||||
while (this.stacker2.firstChild) {
|
||||
this.stacker2.removeChild(this.stacker2.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.armRunout(false);
|
||||
}
|
||||
} else if (!ready && this.ready) {
|
||||
this.statusChange(0);
|
||||
this.addClass(this.$$("CPNotReadyLight"), "redLit");
|
||||
this.ready = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.armRunout = function armRunout(armed) {
|
||||
/* Controls the arming/disarming of the EOF signal when starting with
|
||||
an empty input stacker */
|
||||
|
||||
if (armed && !this.ready) {
|
||||
this.addClass(this.$$("CPRunoutBtn"), "redLit");
|
||||
this.runoutArmed = true;
|
||||
} else {
|
||||
this.removeClass(this.$$("CPRunoutBtn"), "redLit");
|
||||
this.runoutArmed = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.CPStartBtn_onclick = function CPStartBtn_onclick(ev) {
|
||||
/* Handle the click event for the START button */
|
||||
var that = this;
|
||||
|
||||
if (!this.ready) {
|
||||
this.stopCount = 0;
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
}
|
||||
this.setPunchReady(true);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.CPStopBtn_onclick = function CPStopBtn_onclick(ev) {
|
||||
/* Handle the click event for the STOP button */
|
||||
|
||||
if (this.ready) {
|
||||
this.setPunchReady(false);
|
||||
} else if (this.runoutArmed) {
|
||||
this.armRunout(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.CPRunoutBtn_onclick = function CPRunoutBtn_onclick(ev) {
|
||||
/* Handle the click event for the EOF button */
|
||||
|
||||
this.armRunout(!this.runoutArmed);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.punchOnload = function punchOnload() {
|
||||
/* Initializes the punch window and user interface */
|
||||
var that = this;
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.doc.title = "retro-B5500 " + this.mnemonic;
|
||||
|
||||
this.stacker1Frame = this.$$("CPStacker1Frame");
|
||||
this.stacker1Frame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #F0DCB0; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.stacker1 = this.doc.createElement("pre");
|
||||
this.stacker1Frame.contentDocument.body.appendChild(this.stacker1);
|
||||
this.endOfStacker1 = this.doc.createElement("div");
|
||||
this.stacker1Frame.contentDocument.body.appendChild(this.endOfStacker1);
|
||||
|
||||
this.stacker2Frame = this.$$("CPStacker2Frame");
|
||||
this.stacker2Frame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #F0DCB0; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.stacker2 = this.doc.createElement("pre");
|
||||
this.stacker2Frame.contentDocument.body.appendChild(this.stacker2);
|
||||
this.endOfStacker2 = this.doc.createElement("div");
|
||||
this.stacker2Frame.contentDocument.body.appendChild(this.endOfStacker2);
|
||||
|
||||
this.window.moveTo(0, 180);
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("CPDiv").scrollWidth-this.window.innerWidth+12,
|
||||
this.window.outerHeight+this.$$("CPDiv").scrollHeight-this.window.innerHeight+12);
|
||||
|
||||
this.armRunout(false);
|
||||
this.setPunchReady(true);
|
||||
|
||||
this.$$("CPStartBtn").addEventListener("click", function(ev) {
|
||||
that.CPStartBtn_onclick(ev);
|
||||
}, false);
|
||||
|
||||
this.$$("CPStopBtn").addEventListener("click", function(ev) {
|
||||
that.CPStopBtn_onclick(ev);
|
||||
}, false);
|
||||
|
||||
this.$$("CPRunoutBtn").addEventListener("click", function(ev) {
|
||||
that.CPRunoutBtn_onclick(ev);
|
||||
}, false);
|
||||
|
||||
this.$$("CPStacker1Bar").max = this.maxScrollLines;
|
||||
this.$$("CPStacker2Bar").max = this.maxScrollLines;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.appendLine = function appendLine(stacker, text) {
|
||||
/* Removes excess lines already printed, then appends a new <pre> element
|
||||
to the <iframe>, creating an empty text node inside the new element */
|
||||
var count = stacker.childNodes.length;
|
||||
var line = this.doc.createTextNode(text || "");
|
||||
|
||||
//while (count-- > this.maxScrollLines) {
|
||||
// stacker.removeChild(stacker.firstChild);
|
||||
//}
|
||||
stacker.appendChild(line);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.read = function read(finish, buffer, length, mode, control) {
|
||||
/* Initiates a read operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.space = function space(finish, length, control) {
|
||||
/* Initiates a space operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.write = function write(finish, buffer, length, mode, control) {
|
||||
/* Initiates a write operation on the unit */
|
||||
var text;
|
||||
var that = this;
|
||||
|
||||
this.errorMask = 0;
|
||||
this.busy = true;
|
||||
text = String.fromCharCode.apply(null, buffer.subarray(0, length));
|
||||
//console.log("WRITE: L=" + length + ", M=" + mode + ", C=" + control + " : " + text);
|
||||
if (control) {
|
||||
this.appendLine(this.stacker2, text + "\n");
|
||||
this.endOfStacker2.scrollIntoView();
|
||||
this.$$("CPStacker2Bar").value = (++this.stacker2Count);
|
||||
if (this.stacker2Count >= this.maxScrollLines) {
|
||||
this.setPunchReady(false);
|
||||
}
|
||||
} else {
|
||||
this.appendLine(this.stacker1, text + "\n");
|
||||
this.endOfStacker1.scrollIntoView();
|
||||
this.$$("CPStacker1Bar").value = (++this.stacker1Count);
|
||||
if (this.stacker1Count >= this.maxScrollLines) {
|
||||
this.setPunchReady(false);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
that.busy = false;
|
||||
finish(that.errorMask, length);
|
||||
}, 60000/this.cardsPerMinute);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.erase = function erase(finish, length) {
|
||||
/* Initiates an erase operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.rewind = function rewind(finish) {
|
||||
/* Initiates a rewind operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.readCheck = function readCheck(finish, length, control) {
|
||||
/* Initiates a read check operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.readInterrogate = function readInterrogate(finish, control) {
|
||||
/* Initiates a read interrogate operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardPunch.prototype.writeInterrogate = function writeInterrogate(finish, control) {
|
||||
/* Initiates a write interrogate operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
@@ -18,8 +18,8 @@ BODY {
|
||||
DIV#CRDiv {
|
||||
position: relative;
|
||||
background-color: #666;
|
||||
width: 280px;
|
||||
height: 112px;
|
||||
width: 700px;
|
||||
height: 150px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
@@ -94,6 +94,19 @@ BUTTON.redLit {
|
||||
#CRProgressBar {
|
||||
position: absolute;
|
||||
border: 1px solid white;
|
||||
top: 84px;
|
||||
top: 82px;
|
||||
left: 8px;
|
||||
width: 262px}
|
||||
width: 680px}
|
||||
|
||||
#CROutHopperFrame {
|
||||
position: absolute;
|
||||
top: 104px;
|
||||
left: 8px;
|
||||
width: 680px;
|
||||
height: 35px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 8pt;
|
||||
font-weight: normal}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
<button id=CREOFBtn class="redButton">EOF</button>
|
||||
<button id=CRStopBtn class="redButton">STOP</button>
|
||||
|
||||
<input id=CRFileSelector type=file size=29>
|
||||
<input id=CRFileSelector type=file size=90>
|
||||
|
||||
<progress id=CRProgressBar min=0 max=100 value=0>
|
||||
<progress id=CRProgressBar min=0 max=100 value=0 title="Click to clear input hopper"></progress>
|
||||
|
||||
<iframe id=CROutHopperFrame scrolling=no></iframe>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -24,7 +24,7 @@ function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
this.designate = designate; // IOD unit designate number
|
||||
this.statusChange = statusChange; // external function to call for ready-status change
|
||||
this.signal = signal; // external function to call for special signals (e.g,. SPO input request)
|
||||
this.signal = signal; // external function to call for special signals (not used here)
|
||||
|
||||
this.clear();
|
||||
|
||||
@@ -35,11 +35,15 @@ function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
}
|
||||
this.doc = null;
|
||||
this.window = window.open("/B5500/webUI/B5500CardReader.html", mnemonic,
|
||||
"scrollbars=no,resizable,width=200,height=200");
|
||||
this.window.onload = function() {
|
||||
"scrollbars=no,resizable,width=700,height=150");
|
||||
this.window.addEventListener("load", function() {
|
||||
that.readerOnload();
|
||||
};
|
||||
}, false);
|
||||
|
||||
this.outHopperFrame = null;
|
||||
this.outHopper = null;
|
||||
}
|
||||
|
||||
B5500CardReader.prototype.eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
|
||||
|
||||
B5500CardReader.prototype.cardsPerMinute = 800;
|
||||
@@ -74,7 +78,6 @@ B5500CardReader.prototype.clear = function clear() {
|
||||
this.bufLength = 0; // Current input buffer length (characters)
|
||||
this.bufIndex = 0; // 0-relative offset to next "card" to be read
|
||||
this.eofArmed = false; // EOF button: armed state
|
||||
this.stopCount = 0; // stopCount for clearing the input buffer
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -141,7 +144,6 @@ B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
|
||||
var that = this;
|
||||
|
||||
if (!this.ready) {
|
||||
this.stopCount = 0;
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
this.setReaderReady(true);
|
||||
}
|
||||
@@ -156,18 +158,6 @@ B5500CardReader.prototype.CRStopBtn_onclick = function CRStopBtn_onclick(ev) {
|
||||
this.setReaderReady(false);
|
||||
} else if (this.eofArmed) {
|
||||
this.armEOF(false);
|
||||
} else if (this.bufIndex < this.bufLength) {
|
||||
if (this.stopCount < 3) {
|
||||
this.stopCount++;
|
||||
} else {
|
||||
if (confirm("Empty the " + this.mnemonic + " input hopper?")) {
|
||||
this.stopCount = 0;
|
||||
this.buffer = "";
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.$$("CRProgressBar").value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,6 +168,21 @@ B5500CardReader.prototype.CREOFBtn_onclick = function CREOFBtn_onclick(ev) {
|
||||
this.armEOF(!this.eofArmed);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.CRProgressBar_onclick = function CRProgressBar_onclick(ev) {
|
||||
/* Handle the click event for the "input hopper" progress bar */
|
||||
|
||||
if (this.bufIndex < this.bufLength && !this.ready) {
|
||||
if (confirm((this.bufLength-this.bufIndex).toString() + " of " + this.bufLength.toString() +
|
||||
" characters remaining to read.\nDo you want to clear the reader input hopper?")) {
|
||||
this.buffer = "";
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
this.$$("CRProgressBar").value = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange(ev) {
|
||||
/* Handle the <input type=file> onchange event when a file is selected */
|
||||
@@ -200,12 +205,6 @@ B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange
|
||||
that.$$("CRProgressBar").max = that.bufLength;
|
||||
}
|
||||
|
||||
/********************
|
||||
alert("File selected: " + f.name +
|
||||
"\nModified " + f.lastModifiedDate +
|
||||
"\nType=" + f.type + ", Size=" + f.size + " octets");
|
||||
********************/
|
||||
|
||||
reader.onload = fileLoader_onLoad;
|
||||
reader.readAsText(f);
|
||||
};
|
||||
@@ -214,7 +213,8 @@ B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange
|
||||
B5500CardReader.prototype.readCardAlpha = function readCardAlpha(buffer, length) {
|
||||
/* Reads one card image from the buffer in alpha mode; pads or trims the
|
||||
image as necessary to the I/O buffer length. Invalid BCL characters are
|
||||
translated to ASCII "?" and the invalid character bit is set in the errorMask */
|
||||
translated to ASCII "?" and the invalid character bit is set in the errorMask.
|
||||
Returns the raw card image as a string */
|
||||
var card; // card image
|
||||
var cardLength; // length of card image
|
||||
var match; // result of eolRex.exec()
|
||||
@@ -223,6 +223,7 @@ B5500CardReader.prototype.readCardAlpha = function readCardAlpha(buffer, length)
|
||||
this.eolRex.lastIndex = this.bufIndex;
|
||||
match = this.eolRex.exec(this.buffer);
|
||||
if (!match) {
|
||||
card = "";
|
||||
cardLength = 0;
|
||||
} else {
|
||||
this.bufIndex += match[0].length;
|
||||
@@ -241,13 +242,16 @@ B5500CardReader.prototype.readCardAlpha = function readCardAlpha(buffer, length)
|
||||
while (cardLength < length) {
|
||||
buffer[cardLength++] = 0x20; // pad with spaces
|
||||
}
|
||||
|
||||
return card;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.readCardBinary = function readCardBinary(buffer, length) {
|
||||
/* Reads one card image from the buffer in binary mode; pads or trims the
|
||||
image as necessary to the I/O buffer length. Invalid BCL characters are
|
||||
translated to ASCII "?", but are not reported in the errorMask */
|
||||
translated to ASCII "?", but are not reported in the errorMask.
|
||||
Returns the raw card image as a string */
|
||||
var card; // card image
|
||||
var cardLength; // length of card image
|
||||
var match; // result of eolRex.exec()
|
||||
@@ -256,6 +260,7 @@ B5500CardReader.prototype.readCardBinary = function readCardBinary(buffer, lengt
|
||||
this.eolRex.lastIndex = this.bufIndex;
|
||||
match = this.eolRex.exec(this.buffer);
|
||||
if (!match) {
|
||||
card = "";
|
||||
cardLength = 0;
|
||||
} else {
|
||||
this.bufIndex += match[0].length;
|
||||
@@ -272,6 +277,8 @@ B5500CardReader.prototype.readCardBinary = function readCardBinary(buffer, lengt
|
||||
while (cardLength < length) {
|
||||
buffer[cardLength++] = 0x30; // pad with ASCII zeroes
|
||||
}
|
||||
|
||||
return card;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -280,12 +287,20 @@ B5500CardReader.prototype.readerOnload = function readerOnload() {
|
||||
var that = this;
|
||||
var x = (this.mnemonic == "CRA" ? 0 : this.window.outerWidth + 16);
|
||||
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.doc.title = "retro-B5500 " + this.mnemonic;
|
||||
|
||||
this.window.moveTo(x, 0);
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("CRDiv").scrollWidth-this.window.innerWidth+8,
|
||||
this.window.outerHeight+this.$$("CRDiv").scrollHeight-this.window.innerHeight+8);
|
||||
this.window.resizeTo(this.window.outerWidth+this.$$("CRDiv").scrollWidth-this.window.innerWidth+12,
|
||||
this.window.outerHeight+this.$$("CRDiv").scrollHeight-this.window.innerHeight+12);
|
||||
|
||||
this.outHopperFrame = this.$$("CROutHopperFrame");
|
||||
this.outHopperFrame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #F0DCB0; margin: 2px} " +
|
||||
"PRE {margin: 0; font-size: 9pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
this.outHopper = this.doc.createElement("pre");
|
||||
this.outHopperFrame.contentDocument.body.appendChild(this.outHopper);
|
||||
|
||||
this.armEOF(false);
|
||||
this.setReaderReady(false);
|
||||
@@ -305,13 +320,18 @@ B5500CardReader.prototype.readerOnload = function readerOnload() {
|
||||
this.$$("CREOFBtn").addEventListener("click", function(ev) {
|
||||
that.CREOFBtn_onclick(ev);
|
||||
}, false);
|
||||
|
||||
this.$$("CRProgressBar").addEventListener("click", function(ev) {
|
||||
that.CRProgressBar_onclick(ev);
|
||||
}, false);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.read = function read(finish, buffer, length, mode, control) {
|
||||
/* Initiates a read operation on the unit. If the reader is not ready and the input
|
||||
buffer is empty and EOF is armed , returns EOF; otherwise if not ready,
|
||||
buffer is empty and EOF is armed, returns EOF; otherwise if not ready,
|
||||
returns Not Ready */
|
||||
var card;
|
||||
var that = this;
|
||||
|
||||
this.errorMask = 0;
|
||||
@@ -327,9 +347,9 @@ B5500CardReader.prototype.read = function read(finish, buffer, length, mode, con
|
||||
} else {
|
||||
this.busy = true;
|
||||
if (mode == 0) {
|
||||
this.readCardAlpha(buffer, length);
|
||||
card = this.readCardAlpha(buffer, length);
|
||||
} else {
|
||||
this.readCardBinary(buffer, length);
|
||||
card = this.readCardBinary(buffer, length);
|
||||
}
|
||||
if (this.bufIndex < this.bufLength) {
|
||||
this.$$("CRProgressBar").value = this.bufLength-this.bufIndex;
|
||||
@@ -345,6 +365,12 @@ B5500CardReader.prototype.read = function read(finish, buffer, length, mode, con
|
||||
that.busy = false;
|
||||
finish(that.errorMask, length);
|
||||
}, 60000/this.cardsPerMinute);
|
||||
|
||||
while (this.outHopper.childNodes.length > 1) {
|
||||
this.outHopper.removeChild(this.outHopper.firstChild);
|
||||
}
|
||||
this.outHopper.appendChild(this.doc.createTextNode("\n"));
|
||||
this.outHopper.appendChild(this.doc.createTextNode(card));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -359,7 +385,7 @@ B5500CardReader.prototype.space = function space(finish, length, control) {
|
||||
B5500CardReader.prototype.write = function write(finish, buffer, length, mode, control) {
|
||||
/* Initiates a write operation on the unit */
|
||||
|
||||
finish(0x04); // report unit not ready
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
|
||||
@@ -1685,15 +1685,14 @@ window.onload = function() {
|
||||
stringToANSI("0000001?", fileLabels, labelx-16); // @114, last-entry marker
|
||||
stringToANSI("00000000", fileLabels, labelx-8);
|
||||
}
|
||||
header[0] = 0x0141; // BIC "51" = @0501 = 1 rec/block, 1 seg/block
|
||||
header[3] = 0x1001200; // Date: BIC "00010180" = 1980-01-01
|
||||
header[0] = 0x0181; // BIC "61" = @0601 = 6 rec/block, 1 seg/block
|
||||
header[3] = (365*0x40000 + 10180) * 0x40000 + 10180; // save=365, create+update=1980-01-01
|
||||
header[7] = -1; // currently has no records
|
||||
header[8] = areasize;
|
||||
header[9] = 1; // number of areas
|
||||
header[10] = 0; // row address unallocated
|
||||
wordsToANSI(header, 0, 30, buffer, 0);
|
||||
eu.put(buffer, directoryTop + 18 - fileNr);
|
||||
|
||||
fileNr++;
|
||||
}
|
||||
|
||||
@@ -1756,7 +1755,7 @@ window.onload = function() {
|
||||
pow2[47-28] + // 28: prevent I/O below user disk area
|
||||
pow2[47-27] + // 27: prevent disk RELEASE statement
|
||||
pow2[47-26] + // 26: printer backup disk release
|
||||
// 25: check memory links
|
||||
pow2[47-25] + // 25: check memory links
|
||||
pow2[47-24] + // 24: type disk error messages
|
||||
pow2[47-23] + // 23: disk logging
|
||||
pow2[47-22] + // 22: suppress library error messages
|
||||
|
||||
@@ -16,7 +16,7 @@ BODY {
|
||||
|
||||
DIV#consoleDiv {
|
||||
position: relative;
|
||||
width: 1052px;
|
||||
width: 1052px;
|
||||
height: 72px;
|
||||
padding: 32px;
|
||||
background-color: #666}
|
||||
@@ -42,6 +42,16 @@ DIV#B5500Logo {
|
||||
right: 32px;
|
||||
z-index: 15}
|
||||
|
||||
DIV#RetroVersion {
|
||||
display: none; /***** TEMPORARY *****/
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 170px;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: x-small;
|
||||
font-weight: bold}
|
||||
|
||||
IMG#BurroughsLogoImage {
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
@@ -56,7 +66,7 @@ BUTTON.whiteButton {
|
||||
background-color: #CCC;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: x-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -68,7 +78,7 @@ BUTTON.blackButton {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: x-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -80,7 +90,7 @@ BUTTON.yellowButton {
|
||||
background-color: #990;
|
||||
color: black;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: x-small;
|
||||
font-weight: bold;
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
@@ -92,72 +102,81 @@ BUTTON.whiteLit {
|
||||
|
||||
BUTTON.yellowLit {
|
||||
background-color: #FFFF00}
|
||||
|
||||
|
||||
BUTTON.blackBorder {
|
||||
border: 1px solid black}
|
||||
|
||||
|
||||
BUTTON.yellowBorder {
|
||||
border: 2px solid yellow}
|
||||
|
||||
BUTTON.silverBorder {
|
||||
border: 1px solid #DDD}
|
||||
|
||||
BUTTON#HaltBtn {
|
||||
top: 31px;
|
||||
left: 32px}
|
||||
|
||||
|
||||
BUTTON#NotReadyBtn {
|
||||
top: 31px;
|
||||
left: 132px}
|
||||
|
||||
|
||||
BUTTON#LoadSelectBtn {
|
||||
top: 31px;
|
||||
left: 202px}
|
||||
|
||||
|
||||
BUTTON#LoadBtn {
|
||||
top: 31px;
|
||||
left: 272px}
|
||||
|
||||
|
||||
BUTTON#MemoryCheckBtn {
|
||||
top: 31px;
|
||||
left: 372px}
|
||||
|
||||
|
||||
BUTTON#ANormalBtn {
|
||||
top: 31px;
|
||||
left: 442px}
|
||||
|
||||
|
||||
BUTTON#AControlBtn {
|
||||
top: 31px;
|
||||
left: 512px}
|
||||
|
||||
|
||||
BUTTON#BNormalBtn {
|
||||
top: 31px;
|
||||
left: 582px}
|
||||
|
||||
|
||||
BUTTON#BControlBtn {
|
||||
top: 31px;
|
||||
left: 652px}
|
||||
|
||||
|
||||
BUTTON#PowerOnBtn {
|
||||
top: 31px;
|
||||
left: 752px}
|
||||
|
||||
|
||||
BUTTON#PowerOffBtn {
|
||||
top: 31px;
|
||||
left: 822px}
|
||||
|
||||
|
||||
TABLE#CentralControl {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #666;
|
||||
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: x-small;
|
||||
font-weight: bold}
|
||||
|
||||
|
||||
COL.AnnunciatorCol {
|
||||
width: 2.9%}
|
||||
|
||||
TD#procRate, TD#procSlack {
|
||||
color: white;
|
||||
text-align: right}
|
||||
|
||||
|
||||
|
||||
.busy {
|
||||
color: white}
|
||||
.idle {
|
||||
color: #666}
|
||||
|
||||
|
||||
.center {
|
||||
text-align: center}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>B5500 Emulator Operator Console</title>
|
||||
<title>retro-B5500 Emulator Operator Console</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
@@ -11,6 +11,8 @@
|
||||
<script src="./B5500SPOUnit.js"></script>
|
||||
<script src="./B5500DiskUnit.js"></script>
|
||||
<script src="./B5500CardReader.js"></script>
|
||||
<script src="./B5500CardPunch.js"></script>
|
||||
<script src="./B5500DummyPrinter.js"></script>
|
||||
|
||||
<script src="../emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="../emulator/B5500CentralControl.js"></script>
|
||||
@@ -18,15 +20,22 @@
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.addEventListener("load", function() {
|
||||
var aControl;
|
||||
var aNormal;
|
||||
var bControl;
|
||||
var bNormal;
|
||||
var boundBlinkenlicht;
|
||||
var cc = new B5500CentralControl();
|
||||
var lastBusyMask = 0;
|
||||
var procRate;
|
||||
var intLightsMap = new Array(48);
|
||||
var iouLightsMap = new Array(4);
|
||||
var lastInterruptMask = 0;
|
||||
var lastIOUMask = 0;
|
||||
var lastUnitBusyMask = 0;
|
||||
var lastPAState = -1;
|
||||
var lastPBState = -1;
|
||||
var perLightsMap = new Array(48);
|
||||
var procRate;
|
||||
var procSlack;
|
||||
var timer;
|
||||
var timerInterval = 50; // milliseconds
|
||||
@@ -43,7 +52,11 @@ window.onload = function() {
|
||||
$$("PowerOnBtn").className = "whiteButton whiteLit";
|
||||
$$("AControlBtn").className = "yellowButton yellowLit";
|
||||
cc.powerOn();
|
||||
$$("PowerOnBtn").disabled = true;
|
||||
$$("PowerOffBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = false;
|
||||
$$("HaltBtn").disabled = true;
|
||||
window.focus();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,6 +66,8 @@ window.onload = function() {
|
||||
$$("AControlBtn").className = "yellowButton";
|
||||
$$("BNormalBtn").className = "yellowButton";
|
||||
cc.powerOff();
|
||||
$$("PowerOnBtn").disabled = false;
|
||||
$$("PowerOffBtn").disabled = true;
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("LoadBtn").disabled = true;
|
||||
if (timer) {
|
||||
@@ -69,40 +84,70 @@ window.onload = function() {
|
||||
}
|
||||
|
||||
function LoadBtn_Click(ev) {
|
||||
cc.load();
|
||||
cc.load(false);
|
||||
$$("HaltBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = true;
|
||||
boundBlinkenlicht();
|
||||
}
|
||||
|
||||
function LoadSelectBtn_Click(ev) {
|
||||
if (cc.cardLoadSelect) {
|
||||
cc.cardLoadSelect = 0;
|
||||
$$("LoadSelectBtn").className = "blackButton silverBorder";
|
||||
} else {
|
||||
cc.cardLoadSelect = 1;
|
||||
$$("LoadSelectBtn").className = "blackButton yellowBorder";
|
||||
}
|
||||
}
|
||||
|
||||
function displayCentralControl() {
|
||||
/* Displays the I/O and interrupt status in Central Control */
|
||||
var cells;
|
||||
var s;
|
||||
var busyMask = cc.unitBusyMask;
|
||||
var busyChange = lastBusyMask ^ busyMask;
|
||||
var interruptMask = cc.fetchInterruptLatch() % 0x4000;
|
||||
var interruptChange = lastInterruptMask ^ interruptMask;
|
||||
var iouMask = cc.fetchIOUnitLatch();
|
||||
var iouChange = lastIOUMask ^ iouMask;
|
||||
var unitBusyMask = cc.fetchUnitBusyLatch();
|
||||
var unitBusyChange = lastUnitBusyMask ^ unitBusyMask;
|
||||
var x;
|
||||
|
||||
lastBusyMask = busyMask;
|
||||
lastInterruptMask = interruptMask;
|
||||
lastIOUMask = iouMask;
|
||||
lastUnitBusyMask = unitBusyMask;
|
||||
|
||||
$$("AD1F").className = (cc.AD1F ? "busy" : "");
|
||||
$$("AD2F").className = (cc.AD2F ? "busy" : "");
|
||||
$$("AD3F").className = (cc.AD3F ? "busy" : "");
|
||||
$$("AD4F").className = (cc.AD4F ? "busy" : "");
|
||||
|
||||
for (x=3; x<=16; x++) {
|
||||
s = "CCI" + (x+100).toString().substring(1) + "F";
|
||||
$$(s).className = (cc[s] ? "busy" : "");
|
||||
x = 0;
|
||||
while (iouChange) {
|
||||
if (iouChange & 0x01) {
|
||||
iouLightsMap[x].className = (iouMask & 0x01 ? "busy" : "");
|
||||
}
|
||||
iouMask >>>= 1;
|
||||
iouChange >>>= 1;
|
||||
x++;
|
||||
}
|
||||
|
||||
cells = $$("CCPeripheralRow").cells;
|
||||
x = 47;
|
||||
while (busyChange) {
|
||||
if (busyChange & 0x01) {
|
||||
cells[x-17].className = (busyMask & 0x01 ? "busy" : "");
|
||||
while (interruptChange) {
|
||||
if (interruptChange & 0x01) {
|
||||
intLightsMap[x].className = (interruptMask & 0x01 ? "busy" : "");
|
||||
}
|
||||
busyMask >>>= 1;
|
||||
busyChange >>>= 1;
|
||||
interruptMask >>>= 1;
|
||||
interruptChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
|
||||
x = 47;
|
||||
while (unitBusyChange) {
|
||||
if (unitBusyChange & 0x01) {
|
||||
perLightsMap[x].className = (unitBusyMask & 0x01 ? "busy" : "");
|
||||
}
|
||||
unitBusyMask >>>= 1;
|
||||
unitBusyChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
}
|
||||
@@ -114,32 +159,44 @@ window.onload = function() {
|
||||
|
||||
if (pa) {
|
||||
if (!pa.busy) {
|
||||
aControl.className = "yellowButton";
|
||||
aNormal.className = "yellowButton";
|
||||
} else if (pa.NCSF) {
|
||||
aControl.className = "yellowButton";
|
||||
aNormal.className = "yellowButton yellowLit";
|
||||
} else {
|
||||
aNormal.className = "yellowButton";
|
||||
if (pa === cc.P1) {
|
||||
aControl.className = "yellowButton yellowLit";
|
||||
if (lastPAState != -1) {
|
||||
aControl.className = "yellowButton";
|
||||
aNormal.className = "yellowButton";
|
||||
lastPAState = -1;
|
||||
}
|
||||
} else if (pa.NCSF != lastPAState) {
|
||||
lastPAState = pa.NCSF;
|
||||
if (lastPAState) {
|
||||
aControl.className = "yellowButton";
|
||||
aNormal.className = "yellowButton yellowLit";
|
||||
} else {
|
||||
aNormal.className = "yellowButton";
|
||||
if (pa === cc.P1) {
|
||||
aControl.className = "yellowButton yellowLit";
|
||||
}
|
||||
}
|
||||
et = new Date().getTime() - pa.procStart;
|
||||
procRate.innerHTML = (pa.procTime/et*100).toFixed(1) + "%";
|
||||
procSlack.innerHTML = (pa.procSlack/et*100).toFixed(1) + "%";
|
||||
}
|
||||
et = new Date().getTime()*1000 - pa.procStart;
|
||||
procRate.innerHTML = ((pa.procTime - pa.procStart)/et*100).toFixed(1) + "%";
|
||||
//procSlack.innerHTML = (pa.procSlack/et*100).toFixed(1) + "%";
|
||||
}
|
||||
}
|
||||
if (pb) {
|
||||
if (!pb.busy) {
|
||||
bControl.className = "yellowButton";
|
||||
bNormal.className = "yellowButton";
|
||||
} else if (pb.NCSF) {
|
||||
bControl.className = "yellowButton";
|
||||
bNormal.className = "yellowButton yellowLit";
|
||||
} else {
|
||||
bNormal.className = "yellowButton";
|
||||
if (pb === cc.P1) {
|
||||
bControl.className = "yellowButton yellowLit";
|
||||
if (lastPBState != -1) {
|
||||
bControl.className = "yellowButton";
|
||||
bNormal.className = "yellowButton";
|
||||
lastPBState = -1;
|
||||
}
|
||||
} else if (pb.NCSF != lastPBState) {
|
||||
lastPBState = pb.NCSF;
|
||||
if (lastPBState) {
|
||||
bControl.className = "yellowButton";
|
||||
bNormal.className = "yellowButton yellowLit";
|
||||
} else {
|
||||
bNormal.className = "yellowButton";
|
||||
if (pb === cc.P1) {
|
||||
bControl.className = "yellowButton yellowLit";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,13 +225,36 @@ window.onload = function() {
|
||||
}
|
||||
}
|
||||
|
||||
function buildLightMaps() {
|
||||
/* Builds tables of the DOM entries for the annunciator lights, for efficient access */
|
||||
var mnem;
|
||||
var spec;
|
||||
var x;
|
||||
|
||||
iouLightsMap[0] = $$("AD1F");
|
||||
iouLightsMap[1] = $$("AD2F");
|
||||
iouLightsMap[2] = $$("AD3F");
|
||||
iouLightsMap[3] = $$("AD4F");
|
||||
|
||||
for (x=3; x<=16; x++) {
|
||||
intLightsMap[50-x] = $$("CCI" + (x+100).toString().substring(1) + "F");
|
||||
}
|
||||
|
||||
for (mnem in B5500CentralControl.unitSpecs) {
|
||||
spec = B5500CentralControl.unitSpecs[mnem];
|
||||
perLightsMap[spec.unitIndex] = $$(mnem);
|
||||
}
|
||||
}
|
||||
|
||||
/***** window.onload() outer block *****/
|
||||
|
||||
$$("RetroVersion").innerHTML = B5500CentralControl.version;
|
||||
if (!checkBrowser()) {
|
||||
$$("PowerOnBtn").addEventListener("click", PowerOnBtn_Click);
|
||||
$$("PowerOffBtn").addEventListener("click", PowerOffBtn_Click);
|
||||
$$("HaltBtn").addEventListener("click", HaltBtn_Click);
|
||||
$$("LoadBtn").addEventListener("click", LoadBtn_Click);
|
||||
$$("LoadSelectBtn").addEventListener("click", LoadSelectBtn_Click);
|
||||
|
||||
aControl = $$("AControlBtn");
|
||||
aNormal = $$("ANormalBtn");
|
||||
@@ -183,8 +263,9 @@ window.onload = function() {
|
||||
procRate = $$("procRate");
|
||||
procSlack = $$("procSlack");
|
||||
boundBlinkenlicht = bindMethod(dasBlinkenlicht, this);
|
||||
buildLightMaps();
|
||||
}
|
||||
};
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -194,7 +275,7 @@ window.onload = function() {
|
||||
<button id=HaltBtn class=blackButton DISABLED>HALT</button>
|
||||
|
||||
<button id=NotReadyBtn class=yellowButton>NOT READY</button>
|
||||
<button id=LoadSelectBtn class=blackButton>LOAD SELECT</button>
|
||||
<button id=LoadSelectBtn class="blackButton silverBorder">LOAD SELECT</button>
|
||||
<button id=LoadBtn class=blackButton DISABLED>LOAD</button>
|
||||
|
||||
<button id=MemoryCheckBtn class=yellowButton>MEMORY CHECK</button>
|
||||
@@ -204,18 +285,24 @@ window.onload = function() {
|
||||
<button id=BControlBtn class=yellowButton>B CONTROL</button>
|
||||
|
||||
<button id=PowerOnBtn class=whiteButton>POWER<br>ON</button>
|
||||
<button id=PowerOffBtn class=blackButton>POWER OFF</button>
|
||||
<button id=PowerOffBtn class=blackButton DISABLED>POWER OFF</button>
|
||||
|
||||
<div id=BurroughsLogo>
|
||||
<img id=BurroughsLogoImage src="Burroughs-Logo-Neg.jpg">
|
||||
<img id=BurroughsLogoImage src="Burroughs-Logo-Neg.jpg" alt="Burroughs logo">
|
||||
</div>
|
||||
<div id=RetroVersion>
|
||||
?.??
|
||||
</div>
|
||||
<div id=B5500Logo>
|
||||
<img src="retro-B5500-Logo.png" alt="retro-B5500 logo"><!-- B 5500 -->
|
||||
</div>
|
||||
<div id=B5500Logo><img src="retro-B5500-Logo.png" alt="retro-B5500 logo"><!-- B 5500 --></div>
|
||||
|
||||
<table id=CentralControl>
|
||||
<colgroup>
|
||||
<col span=32 style="width:3%">
|
||||
<col span=32 class=AnnunciatorCol>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tbody>
|
||||
<tr id=CCInterruptRow>
|
||||
<td id=AD1F>IOU1 <!-- I/O unit 1 busy -->
|
||||
<td id=AD2F>IOU2 <!-- I/O unit 2 busy -->
|
||||
@@ -237,6 +324,7 @@ window.onload = function() {
|
||||
<td id=CCI16F>DK2F <!-- Disk file #2 read check finished -->
|
||||
<td colspan=13>
|
||||
<td id=procSlack>
|
||||
<td class=busy>PA Slack
|
||||
<tr id=CCPeripheralRow>
|
||||
<td id=DCA>DCA <!-- 17 -->
|
||||
<td id=PPB>PPB <!-- 18 -->
|
||||
@@ -253,23 +341,24 @@ window.onload = function() {
|
||||
<td id=DKA>DKA <!-- 29 -->
|
||||
<td id=DRB>DRB <!-- 30 -->
|
||||
<td id=DRA>DRA <!-- 31 -->
|
||||
<td id=MTT>MTT <!-- 32 -->
|
||||
<td id=MTS>MTS <!-- 33 -->
|
||||
<td id=MTR>MTR <!-- 34 -->
|
||||
<td id=MTP>MTP <!-- 35 -->
|
||||
<td id=MTN>MTN <!-- 36 -->
|
||||
<td id=MTM>MTM <!-- 37 -->
|
||||
<td id=MTL>MTL <!-- 38 -->
|
||||
<td id=MTK>MTK <!-- 39 -->
|
||||
<td id=MTJ>MTJ <!-- 40 -->
|
||||
<td id=MTH>MTH <!-- 41 -->
|
||||
<td id=MTF>MTF <!-- 42 -->
|
||||
<td id=MTE>MTE <!-- 43 -->
|
||||
<td id=MTD>MTD <!-- 44 -->
|
||||
<td id=MTC>MTC <!-- 45 -->
|
||||
<td id=MTB>MTB <!-- 46 -->
|
||||
<td id=MTA>MTA <!-- 47 -->
|
||||
<td id=MTB>MTB <!-- 46 -->
|
||||
<td id=MTC>MTC <!-- 45 -->
|
||||
<td id=MTD>MTD <!-- 44 -->
|
||||
<td id=MTE>MTE <!-- 43 -->
|
||||
<td id=MTF>MTF <!-- 42 -->
|
||||
<td id=MTH>MTH <!-- 41 -->
|
||||
<td id=MTJ>MTJ <!-- 40 -->
|
||||
<td id=MTK>MTK <!-- 39 -->
|
||||
<td id=MTL>MTL <!-- 38 -->
|
||||
<td id=MTM>MTM <!-- 37 -->
|
||||
<td id=MTN>MTN <!-- 36 -->
|
||||
<td id=MTP>MTP <!-- 35 -->
|
||||
<td id=MTR>MTR <!-- 34 -->
|
||||
<td id=MTS>MTS <!-- 33 -->
|
||||
<td id=MTT>MTT <!-- 32 -->
|
||||
<td id=procRate>
|
||||
<td class=busy>PA Rate
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,16 +18,17 @@
|
||||
*
|
||||
* The database consists of a CONFIG object store and some number of EUn object
|
||||
* stores, where n is in 0..9. The CONFIG store contains an "eus" member that
|
||||
* specifies the total number of EU objects, plus an "EUn" member that specicies
|
||||
* specifies the total number of EU objects, plus an "EUn" member that specifies
|
||||
* the size of that EU in 240-character segments. There may be gaps in the EU
|
||||
* numbering.
|
||||
* numbering, but the EU sizes should be specified in increments of 40,000 up to
|
||||
* a maximum of 200,000 (for Model I) or 400,000 (for Model IB "slow" disks).
|
||||
*
|
||||
* Within an EU, segments are represented in the database as 240-byte Uint8Array
|
||||
* objects, each with a database key corresponding to its numeric segment address.
|
||||
* The segments are an EU are not pre-allocated, but are created as they are
|
||||
* The segments in an EU are not pre-allocated, but are created as they are
|
||||
* written to by IDB put() methods. When reading, any unallocated segments are
|
||||
* returned with their bytes set to binary zero, which will be translated to
|
||||
* BIC "?" by the IOU for both binary and alpha modes.
|
||||
* returned with their bytes set to 0x23 (#), which will be translated by the
|
||||
* IOU to BIC "0" for alpha mode and BIC "#" for binary mode.
|
||||
*
|
||||
* At present, disk write lockout is not supported. When there are two DFCUs in
|
||||
* the system, the presence of a Disk File Exchange is assumed, allowing either
|
||||
@@ -88,7 +89,7 @@ B5500DiskUnit.prototype.charXferRate = 96000; // avg. transfer rate, char
|
||||
B5500DiskUnit.prototype.maxLatency = 0.040; // max rotational latency, sec (Model I SU)
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.clear = function() {
|
||||
B5500DiskUnit.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the processor state */
|
||||
|
||||
this.ready = false; // ready status
|
||||
@@ -106,7 +107,7 @@ B5500DiskUnit.prototype.clear = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.genericDBError = function(ev) {
|
||||
B5500DiskUnit.genericDBError = function genericDBError(ev) {
|
||||
/* Formats a generic alert when otherwise-unhandled database errors occur */
|
||||
var disk = ev.currentTarget.result;
|
||||
|
||||
@@ -117,7 +118,7 @@ B5500DiskUnit.genericDBError = function(ev) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.copySegment = function(seg, buffer, offset) {
|
||||
B5500DiskUnit.prototype.copySegment = function copySegment(seg, buffer, offset) {
|
||||
/* Copies the bytes from a single segment Uint8Array object to "buffer" starting
|
||||
at "offset" for 240 bytes. If "seg" is undefined, copies zero bytes instead */
|
||||
var x;
|
||||
@@ -134,7 +135,7 @@ B5500DiskUnit.prototype.copySegment = function(seg, buffer, offset) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.openDatabase = function() {
|
||||
B5500DiskUnit.prototype.openDatabase = function openDataBase() {
|
||||
/* Attempts to open the disk subsystem database specified by this.dbName and
|
||||
this.dbVersion. If successful, sets this.disk to the IDB object and sets the
|
||||
DFCU to ready status */
|
||||
@@ -143,31 +144,31 @@ B5500DiskUnit.prototype.openDatabase = function() {
|
||||
var that = this;
|
||||
|
||||
that.statusChange(0); // initially force DFCU status to not ready
|
||||
req = window.indexedDB.open(that.dbName, that.dbVersion);
|
||||
req = indexedDB.open(that.dbName, that.dbVersion);
|
||||
|
||||
req.onerror = function(ev) {
|
||||
req.onerror = function idbOpenOnerror(ev) {
|
||||
alert("Cannot open " + that.mnemonic + " database: " + ev.target.error);
|
||||
};
|
||||
|
||||
req.onblocked = function(ev) {
|
||||
req.onblocked = function idbOpenOnblocked(ev) {
|
||||
alert("Database.open is blocked -- cannot continue");
|
||||
};
|
||||
|
||||
req.onupgradeneeded = function(ev) {
|
||||
req.onupgradeneeded = function idbOpenOnupgradeneeded(ev) {
|
||||
alert("Database requires version upgrade -- cannot continue");
|
||||
};
|
||||
|
||||
req.onsuccess = function(ev) {
|
||||
req.onsuccess = function idbOpenOnsuccess(ev) {
|
||||
that.disk = ev.target.result; // save the object reference globally for later use
|
||||
that.disk.onerror = function(ev) {
|
||||
alert("Database for \"" + this.mnemonic + "\" open error: " + ev.target.result.error);
|
||||
that.disk.onerror = function idbCONFIGGetOnerror(ev) {
|
||||
alert("Database for \"" + that.mnemonic + "\" CONFIG get error: " + ev.target.result.error);
|
||||
};
|
||||
|
||||
that.disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function(ev) {
|
||||
that.disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function idbCONFIGGetOnsuccess(ev) {
|
||||
that.config = ev.target.result;
|
||||
that.statusChange(1); // report the DFCU as ready to Central Control
|
||||
// Set up the generic error handler
|
||||
that.disk.onerror = function(ev) {
|
||||
that.disk.onerror = function idbGenericOnError(ev) {
|
||||
that.genericIDBError(ev);
|
||||
};
|
||||
};
|
||||
@@ -175,7 +176,7 @@ B5500DiskUnit.prototype.openDatabase = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
B5500DiskUnit.prototype.read = function read(finish, buffer, length, mode, control) {
|
||||
/* Initiates a read operation on the unit. "length" is in characters; segment address
|
||||
is in "control". "mode" is ignored (any translation would have been done by IOU) */
|
||||
var bx = 0; // current buffer offset
|
||||
@@ -215,19 +216,19 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
this.errorMask = 0;
|
||||
} else if (segs < 2) { // A single-segment read
|
||||
req = this.disk.transaction(euName).objectStore(euName).get(segAddr);
|
||||
req.onsuccess = function(ev) {
|
||||
req.onsuccess = function singleReadOnsuccess(ev) {
|
||||
that.copySegment(ev.target.result, buffer, 0);
|
||||
setTimeout(function() {
|
||||
setTimeout(function singleReadTimeout() {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, finishTime - new Date().getTime());
|
||||
}
|
||||
} else { // A multi-segment read
|
||||
range = window.IDBKeyRange.bound(segAddr, endAddr);
|
||||
range = IDBKeyRange.bound(segAddr, endAddr);
|
||||
txn = this.disk.transaction(euName);
|
||||
|
||||
req = txn.objectStore(euName).openCursor(range);
|
||||
req.onsuccess = function(ev) {
|
||||
req.onsuccess = function rangeReadOnsuccess(ev) {
|
||||
var cursor = ev.target.result;
|
||||
|
||||
if (cursor) { // found a segment at some address in range
|
||||
@@ -249,7 +250,7 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
bx += 240;
|
||||
segAddr++;
|
||||
}
|
||||
setTimeout(function() {
|
||||
setTimeout(function rangeReadTimeout() {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, finishTime - new Date().getTime());
|
||||
@@ -260,14 +261,14 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.space = function(finish, length, control) {
|
||||
B5500DiskUnit.prototype.space = function space(finish, length, control) {
|
||||
/* Initiates a space operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control) {
|
||||
B5500DiskUnit.prototype.write = function write(finish, buffer, length, mode, control) {
|
||||
/* Initiates a write operation on the unit. "length" is in characters; segment address
|
||||
is in "control". "mode" is ignored (any translation will done by the IOU) */
|
||||
var bx = 0; // current buffer offset
|
||||
@@ -310,8 +311,8 @@ B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control)
|
||||
// Do the write
|
||||
} else {
|
||||
txn = this.disk.transaction(euName, "readwrite")
|
||||
txn.oncomplete = function(ev) {
|
||||
setTimeout(function() {
|
||||
txn.oncomplete = function writeComplete(ev) {
|
||||
setTimeout(function writeTimeout() {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, finishTime - new Date().getTime());
|
||||
@@ -326,21 +327,21 @@ B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control)
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.erase = function(finish, length) {
|
||||
B5500DiskUnit.prototype.erase = function erase(finish, length) {
|
||||
/* Initiates an erase operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.rewind = function(finish) {
|
||||
B5500DiskUnit.prototype.rewind = function rewind(finish) {
|
||||
/* Initiates a rewind operation on the unit */
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
B5500DiskUnit.prototype.readCheck = function readCheck(finish, length, control) {
|
||||
/* Initiates a read check operation on the unit. "length" is in characters;
|
||||
segment address is in "control". "mode" is ignored. This is essentially a
|
||||
read without any data transfer to memory. Note that the errorMask is NOT
|
||||
@@ -384,18 +385,18 @@ B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
this.signal();
|
||||
// DO NOT clear the error mask -- will return it on the next interrogate
|
||||
} else { // A multi-segment read
|
||||
range = window.IDBKeyRange.bound(segAddr, endAddr);
|
||||
range = IDBKeyRange.bound(segAddr, endAddr);
|
||||
txn = this.disk.transaction(euName);
|
||||
finish(that.errorMask, length); // post I/O complete now -- DFCU will signal when check finished
|
||||
|
||||
req = txn.objectStore(euName).openCursor(range);
|
||||
req.onsuccess = function(ev) {
|
||||
req.onsuccess = function readCheckOnsuccess(ev) {
|
||||
var cursor = ev.target.result;
|
||||
|
||||
if (cursor) { // found a segment at some address in range
|
||||
cursor.continue();
|
||||
} else { // at end of range
|
||||
setTimeout(function() {
|
||||
setTimeout(function readCheckTimeout() {
|
||||
that.signal();
|
||||
// DO NOT clear the error mask
|
||||
}, finishTime - new Date().getTime());
|
||||
@@ -406,7 +407,7 @@ B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.readInterrogate = function(finish, control) {
|
||||
B5500DiskUnit.prototype.readInterrogate = function readInterrogate(finish, control) {
|
||||
/* Initiates a read interrogate operation on the unit. This serves only to
|
||||
check the addresss for validity and to return any errorMask from a prior
|
||||
read check operation. This implementation assumes completion will be delayed
|
||||
@@ -427,7 +428,7 @@ B5500DiskUnit.prototype.readInterrogate = function(finish, control) {
|
||||
if (segAddr < 0 || segAddr >= euSize) { // if read is past end of disk
|
||||
this.errorMask |= 0x20; // set D27F for invalid seg address
|
||||
}
|
||||
setTimeout(function() {
|
||||
setTimeout(function readInterrogateTimeout() {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, Math.random()*this.maxLatency*1000);
|
||||
@@ -435,7 +436,7 @@ B5500DiskUnit.prototype.readInterrogate = function(finish, control) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.writeInterrogate = function (finish, control) {
|
||||
B5500DiskUnit.prototype.writeInterrogate = function writeInterrogate(finish, control) {
|
||||
/* Initiates a write interrogate operation on the unit. This serves only to
|
||||
check the addresss for validity and to return any errorMask from a prior
|
||||
read check operation. This implementation assumes completion will be delayed
|
||||
@@ -460,7 +461,7 @@ B5500DiskUnit.prototype.writeInterrogate = function (finish, control) {
|
||||
if (segAddr < 0 || segAddr >= euSize) { // if read is past end of disk
|
||||
this.errorMask |= 0x20; // set D27F for invalid seg address
|
||||
}
|
||||
setTimeout(function() {
|
||||
setTimeout(function writeInterrogateTimeout() {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, Math.random()*this.maxLatency*1000);
|
||||
|
||||
32
webUI/B5500DummyPrinter.html
Normal file
32
webUI/B5500DummyPrinter.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>B5500 Emulator SPO Unit</title>
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<!-- 2012-12-16 Original version, cloned from SPO prototype script -->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500SPOUnit.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id=SPODiv>
|
||||
<iframe id=SPOUT scrolling=auto></iframe>
|
||||
<div id=SPOControlsDiv>
|
||||
<img id=TeletypeLogo src="TeletypeLogo.gif">
|
||||
<button id=SPOReadyBtn class="yellowButton blackBorder">READY</button>
|
||||
<button id=SPOPowerBtn class="blackButton blackBorder">POWER</button>
|
||||
<button id=SPORemoteBtn class="yellowButton blackBorder">REMOTE</button>
|
||||
<button id=SPOLocalBtn class="yellowButton blackBorder">LOCAL</button>
|
||||
<button id=SPOInputRequestBtn class="yellowButton blackBorder">INPUT REQUEST</button>
|
||||
<button id=SPOEndOfMessageBtn class="yellowButton blackBorder">END OF MESSAGE</button>
|
||||
<button id=SPOBlank1Btn class="yellowButton blackBorder"></button>
|
||||
<button id=SPOErrorBtn class="yellowButton blackBorder">ERROR</button>
|
||||
<button id=SPOBlank2Btn class="yellowButton blackBorder"></button>
|
||||
<button id=SPOBlank3Btn class="yellowButton blackBorder"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
180
webUI/B5500DummyPrinter.js
Normal file
180
webUI/B5500DummyPrinter.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500DummyPrinter.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2013, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 (DUMMY) Line Printer Peripheral Unit module.
|
||||
*
|
||||
* Defines a Line Printer peripheral unit type. Journals all output to
|
||||
* console.log() as well as the pritner window.
|
||||
*
|
||||
************************************************************************
|
||||
* 2013-06-11 P.Kimpel
|
||||
* Original version, from B5500SPOUnit.js.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B5500DummyPrinter(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
/* Constructor for the DummyPrinter object */
|
||||
var that = this;
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
this.designate = designate; // IOD unit designate number
|
||||
this.statusChange = statusChange; // external function to call for ready-status change
|
||||
this.signal = signal; // external function to call for special signals (e.g,. Printer Finished)
|
||||
|
||||
this.clear();
|
||||
|
||||
this.window = window.open("", mnemonic);
|
||||
if (this.window) {
|
||||
this.window.close(); // destroy the previously-existing window
|
||||
this.window = null;
|
||||
}
|
||||
this.doc = null;
|
||||
this.paper = null;
|
||||
this.endOfPaper = null;
|
||||
this.window = window.open("/B5500/webUI/B5500DummyPrinter.html", mnemonic,
|
||||
"scrollbars,resizable,width=600,height=500");
|
||||
this.window.addEventListener("load", function() {
|
||||
that.printerOnload();
|
||||
}, false);
|
||||
}
|
||||
B5500DummyPrinter.prototype.linesPerMinute = 800; // Printer speed
|
||||
B5500DummyPrinter.maxScrollLines = 150000; // Maximum printer scrollback (about a box of paper)
|
||||
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.$$ = function $$(e) {
|
||||
return this.doc.getElementById(e);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.clear = function clear() {
|
||||
/* Initializes (and if necessary, creates) the printer unit state */
|
||||
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.printerOnload = function printerOnload() {
|
||||
/* Initializes the line printer window and user interface */
|
||||
var that = this;
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.doc.title = "retro-B5500 " + this.mnemonic;
|
||||
this.paper = this.doc.createElement("pre");
|
||||
this.doc.body.appendChild(this.paper);
|
||||
this.endOfPaper = this.doc.createElement("div");
|
||||
this.doc.body.appendChild(this.endOfPaper);
|
||||
|
||||
this.window.moveTo(40, 40);
|
||||
this.window.resizeTo(1000, screen.availHeight*0.80);
|
||||
|
||||
this.statusChange(1);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.appendLine = function appendLine(text) {
|
||||
/* Removes excess lines already printed, then appends a new <pre> element
|
||||
to the <iframe>, creating an empty text node inside the new element */
|
||||
var count = this.paper.childNodes.length;
|
||||
var line = this.doc.createTextNode(text || "");
|
||||
|
||||
while (count-- > this.maxScrollLines) {
|
||||
this.paper.removeChild(this.paper.firstChild);
|
||||
}
|
||||
this.paper.appendChild(line);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.read = function read(finish, buffer, length, mode, control) {
|
||||
/* Initiates a read operation on the unit */
|
||||
|
||||
console.log("READ: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.space = function space(finish, length, control) {
|
||||
/* Initiates a space operation on the unit */
|
||||
|
||||
console.log("SPACE: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.write = function write(finish, buffer, length, mode, control) {
|
||||
/* Initiates a write operation on the unit */
|
||||
var text;
|
||||
var that = this;
|
||||
|
||||
this.errorMask = 0;
|
||||
text = String.fromCharCode.apply(null, buffer.subarray(0, length));
|
||||
//console.log("WRITE: L=" + length + ", M=" + mode + ", C=" + control + " : " + text);
|
||||
this.appendLine(text + "\n");
|
||||
if (control > 1) {
|
||||
this.appendLine("\n");
|
||||
} else if (control < 0) {
|
||||
this.paper.appendChild(this.doc.createElement("hr"));
|
||||
}
|
||||
|
||||
setTimeout(this.signal, 60000/this.linesPerMinute);
|
||||
finish(0, 0);
|
||||
this.endOfPaper.scrollIntoView();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.erase = function erase(finish, length) {
|
||||
/* Initiates an erase operation on the unit */
|
||||
|
||||
console.log("ERASE: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.rewind = function rewind(finish) {
|
||||
/* Initiates a rewind operation on the unit */
|
||||
|
||||
console.log("REWIND: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.readCheck = function readCheck(finish, length, control) {
|
||||
/* Initiates a read check operation on the unit */
|
||||
|
||||
console.log("READCK: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.readInterrogate = function readInterrogate(finish, control) {
|
||||
/* Initiates a read interrogate operation on the unit */
|
||||
|
||||
console.log("READIG: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DummyPrinter.prototype.writeInterrogate = function writeInterrogate(finish, control) {
|
||||
/* Initiates a write interrogate operation on the unit */
|
||||
|
||||
console.log("WRITEG: L=" + length + ", M=" + mode + ", C=" + control + " : " +
|
||||
String.fromCharCode.apply(null, buffer.subarray(0, length)));
|
||||
finish(0x04, 0);
|
||||
};
|
||||
@@ -24,7 +24,7 @@ PRE {
|
||||
DIV#SPODiv {
|
||||
position: relative;
|
||||
width: 800px;
|
||||
background-color: #FDA;
|
||||
background-color: #F0D0A0;
|
||||
border-radius: 32px;
|
||||
padding: 2em;
|
||||
text-align: left}
|
||||
|
||||
@@ -42,10 +42,13 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
|
||||
this.window = null;
|
||||
}
|
||||
this.doc = null;
|
||||
this.window = window.open("/B5500/webUI/B5500SPOUnit.html", mnemonic, "scrollbars,resizable,width=600,height=500");
|
||||
this.window.onload = function() {
|
||||
this.paper = null;
|
||||
this.endOfPaper = null;
|
||||
this.window = window.open("/B5500/webUI/B5500SPOUnit.html", mnemonic,
|
||||
"scrollbars,resizable,width=600,height=500");
|
||||
this.window.addEventListener("load", function() {
|
||||
that.spoOnload();
|
||||
};
|
||||
}, false);
|
||||
}
|
||||
|
||||
// this.spoState enumerations
|
||||
@@ -178,21 +181,20 @@ B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine() {
|
||||
/* Removes excess lines already printed, then appends a new <pre> element
|
||||
to the <iframe>, creating an empty text node inside the new element */
|
||||
var count = this.paper.childNodes.length;
|
||||
var line = document.createElement("pre");
|
||||
var line = this.doc.createTextNode("");
|
||||
|
||||
this.printChar(0x0A); // newline
|
||||
while (count-- > this.maxScrollLines) {
|
||||
this.paper.removeChild(this.paper.firstChild);
|
||||
}
|
||||
line.appendChild(document.createTextNode(""));
|
||||
this.paper.appendChild(line);
|
||||
line.scrollIntoView();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.backspaceChar = function backspaceChar() {
|
||||
/* Handles backspace for SPO input */
|
||||
var that = backspaceChar.that;
|
||||
var line = that.paper.lastChild.lastChild;
|
||||
var line = that.paper.lastChild;
|
||||
|
||||
if (that.bufLength > 0) {
|
||||
that.bufIndex--;
|
||||
@@ -209,9 +211,13 @@ B5500SPOUnit.prototype.backspaceChar = function backspaceChar() {
|
||||
B5500SPOUnit.prototype.printChar = function printChar(c) {
|
||||
/* Echoes the character code "c" to the SPO printer */
|
||||
var that = printChar.that;
|
||||
var line = that.paper.lastChild.lastChild;
|
||||
var line = that.paper.lastChild;
|
||||
var len = line.nodeValue.length;
|
||||
|
||||
if (line.nodeValue.length < 72) {
|
||||
if (len < 1) {
|
||||
line.nodeValue = String.fromCharCode(c);
|
||||
that.endOfPaper.scrollIntoView();
|
||||
} else if (len < 72) {
|
||||
line.nodeValue += String.fromCharCode(c);
|
||||
} else {
|
||||
line.nodeValue = line.nodeValue.substring(0, 71) + String.fromCharCode(c);
|
||||
@@ -422,7 +428,12 @@ B5500SPOUnit.prototype.spoOnload = function spoOnload() {
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.doc.title = "retro-B5500 " + this.mnemonic;
|
||||
this.paper = this.$$("SPOUT").contentDocument.body;
|
||||
this.paper = this.doc.createElement("pre");
|
||||
this.paper.appendChild(this.doc.createTextNode(""));
|
||||
this.$$("SPOUT").contentDocument.body.appendChild(this.paper);
|
||||
this.endOfPaper = this.doc.createElement("div");
|
||||
//this.endOfPaper.appendChild(this.doc.createTextNode("\xA0"));
|
||||
this.$$("SPOUT").contentDocument.body.appendChild(this.endOfPaper);
|
||||
this.$$("SPOUT").contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #FFE} " +
|
||||
"PRE {margin: 0; font-size: 10pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
@@ -475,6 +486,7 @@ B5500SPOUnit.prototype.spoOnload = function spoOnload() {
|
||||
this.appendEmptyLine();
|
||||
}
|
||||
this.setReady();
|
||||
this.window.focus();
|
||||
this.printText("retro-B5500 Emulator Version " + B5500CentralControl.version, function() {
|
||||
that.setRemote();
|
||||
that.appendEmptyLine();
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
<script src="/B5500/webUI/B5500DummyUnit.js"></script>
|
||||
<script src="/B5500/webUI/B5500SPOUnit.js"></script>
|
||||
<script src="/B5500/webUI/B5500DiskUnit.js"></script>
|
||||
<script src="./B5500CardReader.js"></script>
|
||||
<script src="/B5500/webUI/B5500CardReader.js"></script>
|
||||
<script src="/B5500/webUI/B5500CardPunch.js"></script>
|
||||
<script src="/B5500/webUI/B5500DummyPrinter.js"></script>
|
||||
|
||||
<script src="/B5500/emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="/B5500/emulator/B5500CentralControl.js"></script>
|
||||
@@ -876,6 +878,7 @@ function hardwareLoad_onClick(ev) {
|
||||
|
||||
cc.clear();
|
||||
cc.P1.clear();
|
||||
cc.cardLoadSelect = $$("CardLoadSelect").checked;
|
||||
cc.load(true);
|
||||
}
|
||||
|
||||
@@ -1101,6 +1104,8 @@ window.onload = function() {
|
||||
<input id=FileSelector type=file size=60>
|
||||
|
||||
<input id=HardwareLoad type=button value="Hardware Load">
|
||||
<input id=CardLoadSelect type=checkbox value="CardLoadSelect">
|
||||
<label for=CardLoadSelect>Card Load Select</label>
|
||||
</p>
|
||||
|
||||
<table id=RegisterBank1 class="normal border">
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
<style>
|
||||
|
||||
BODY {
|
||||
position: relative;
|
||||
margin: 1ex}
|
||||
|
||||
BUTTON.greenButton {
|
||||
background-color: #060;
|
||||
color: white;
|
||||
@@ -49,10 +53,13 @@ BUTTON.redLit {
|
||||
background-color: #F00}
|
||||
|
||||
#CardReaderPanel {
|
||||
position: relative;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 1ex;
|
||||
color: white;
|
||||
background-color: #666;
|
||||
width: 280px;
|
||||
height: 112px;
|
||||
width: 700px;
|
||||
height: 150px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
@@ -82,24 +89,43 @@ BUTTON.redLit {
|
||||
position: absolute;
|
||||
top: 56px;
|
||||
left: 8px;
|
||||
width: 120px}
|
||||
width: 100%;
|
||||
border: 1px solid white}
|
||||
|
||||
#CRProgressBar {
|
||||
position: absolute;
|
||||
top: 84px;
|
||||
left: 8px;
|
||||
width: 262px}
|
||||
width: 680px;
|
||||
border: 1px solid white}
|
||||
|
||||
#CROutHopperFrame {
|
||||
position: absolute;
|
||||
top: 106px;
|
||||
left: 8px;
|
||||
width: 680px;
|
||||
height: 32px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid white;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
|
||||
font-size: 8pt;
|
||||
font-weight: normal}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.onload = function() {
|
||||
window.addEventListener("load", function() {
|
||||
var buffer = "";
|
||||
var bufferLength = 0;
|
||||
var bufferOffset = 0;
|
||||
var eofArmed = 0;
|
||||
var panel = $$("TextPanel");
|
||||
var outHopperFrame = $$("CROutHopperFrame");
|
||||
var outHopper;
|
||||
//var endOfOutHopper;
|
||||
|
||||
var eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
|
||||
var blankCard = " "; // 80 spaces
|
||||
@@ -141,14 +167,14 @@ window.onload = function() {
|
||||
e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), "");
|
||||
}
|
||||
|
||||
function appendLine(panel, text) {
|
||||
function appendLine(text) {
|
||||
/* Appends "text"+NL as a new text node to the panel DOM element */
|
||||
var e = document.createTextNode(text + "\n");
|
||||
|
||||
panel.appendChild(e);
|
||||
}
|
||||
|
||||
function clearPanel(panel) {
|
||||
function clearPanel() {
|
||||
/* Clears the text panel */
|
||||
var kid;
|
||||
|
||||
@@ -189,6 +215,7 @@ window.onload = function() {
|
||||
var bx = bufferOffset;
|
||||
var card;
|
||||
var cardLength;
|
||||
var line;
|
||||
var match;
|
||||
|
||||
if (bx >= bufferLength) {
|
||||
@@ -199,19 +226,26 @@ window.onload = function() {
|
||||
match = eolRex.exec(buffer);
|
||||
if (!match) {
|
||||
card = blankCard;
|
||||
line = "";
|
||||
} else {
|
||||
bx += match[0].length;
|
||||
card = match[1];
|
||||
cardLength = card.length;
|
||||
if (cardLength < 80) {
|
||||
line = card;
|
||||
card += blankCard.substring(0, 80-cardLength);
|
||||
} else if (cardLength > 80) {
|
||||
card = card.substring(0, 80);
|
||||
line = card = card.substring(0, 80);
|
||||
}
|
||||
}
|
||||
|
||||
$$("CRProgressBar").value = bufferLength-bx;
|
||||
appendLine(panel, card);
|
||||
//appendLine(card);
|
||||
while (outHopper.childNodes.length > 1) {
|
||||
outHopper.removeChild(outHopper.firstChild);
|
||||
}
|
||||
outHopper.appendChild(document.createTextNode("\n"));
|
||||
outHopper.appendChild(document.createTextNode(line));
|
||||
|
||||
if (readerState == readerReady) {
|
||||
setTimeout(readACard, 60000/cardsPerMinute);
|
||||
@@ -228,7 +262,7 @@ window.onload = function() {
|
||||
if (bufferOffset >= bufferLength) {
|
||||
//alert("Empty hopper.");
|
||||
if (eofArmed) {
|
||||
appendLine(panel, "\\\\\\\\\\ [EOF] /////");
|
||||
appendLine("\\\\\\\\\\ [EOF] /////");
|
||||
armEOF(false);
|
||||
}
|
||||
} else {
|
||||
@@ -254,13 +288,26 @@ window.onload = function() {
|
||||
armEOF(!eofArmed);
|
||||
}
|
||||
|
||||
function CRProgressBar_onclick(ev) {
|
||||
/* Handle the click event for the "input hopper" progress bar */
|
||||
|
||||
if (bufferOffset < bufferLength && readerState == readerNotReady) {
|
||||
if (confirm("Do you want to clear the reader input hopper?")) {
|
||||
buffer = "";
|
||||
bufferLength = 0;
|
||||
bufferOffset = 0;
|
||||
$$("CRProgressBar").value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fileLoader_onLoad(ev) {
|
||||
/* Handle the onload event for a Text FileReader */
|
||||
|
||||
if (bufferOffset < bufferLength) {
|
||||
buffer = buffer.substring(bufferOffset);
|
||||
} else {
|
||||
clearPanel(panel);
|
||||
clearPanel();
|
||||
buffer = "";
|
||||
}
|
||||
|
||||
@@ -317,7 +364,18 @@ window.onload = function() {
|
||||
$$("CRStartBtn").addEventListener("click", CRStartBtn_onclick, false);
|
||||
$$("CRStopBtn").addEventListener("click", CRStopBtn_onclick, false);
|
||||
$$("CREOFBtn").addEventListener("click", CREOFBtn_onclick, false);
|
||||
}
|
||||
$$("CRProgressBar").addEventListener("click", CRProgressBar_onclick, false);
|
||||
|
||||
outHopperFrame.contentDocument.head.innerHTML += "<style>" +
|
||||
"BODY {background-color: #F0DCB0} " +
|
||||
"PRE {margin: 0; font-size: 8pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
|
||||
"</style>";
|
||||
outHopper = document.createElement("pre");
|
||||
outHopperFrame.contentDocument.body.appendChild(outHopper);
|
||||
//endOfOutHopper = document.createElement("div");
|
||||
//endOfOutHopper.appendChild(document.createTextNode("\xA0"));
|
||||
//outHopperFrame.contentDocument.body.appendChild(endOfOutHopper);
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -332,9 +390,11 @@ window.onload = function() {
|
||||
<button id=CREOFBtn class="redButton">EOF</button>
|
||||
<button id=CRStopBtn class="redButton">STOP</button>
|
||||
|
||||
<input id=CRFileSelector type=file size=29>
|
||||
<input id=CRFileSelector type=file size=90>
|
||||
|
||||
<progress id=CRProgressBar min=0 max=100 value=0>
|
||||
<progress id=CRProgressBar min=0 max=100 value=0 title="Click to clear input hopper"></progress>
|
||||
|
||||
<iframe id=CROutHopperFrame scrolling=auto></iframe>
|
||||
</div>
|
||||
|
||||
<pre id=TextPanel>
|
||||
|
||||
Reference in New Issue
Block a user