;Interface Age Floppy ROM load/dump program ; Interface Age May 78 ; ; Modified for Sol-20 by R. Parsons ; 4-29-78 ; ORG 100H XEQ CLEAR ; SOUT EQU 0C019H SINP EQU 0C01FH STACK EQU 0CBFFH SOLOS EQU 0C004H PTDOS EQU 0BCB0H CPM EQU 0 MONIT EQU SOLOS FSTAT EQU 0FAH ;file status port FDATA EQU 0FBH ;file data port FIMSK EQU 040H ;input mask TSTAT EQU 0FAH ;tape status port TDATA EQU 0FBH ;tape data port TOMSK EQU 080H ;tape output mask CSTAT EQU 0FAH ;console status CDATA EQU 0FCH ;console data CIMSK EQU 001H ;console input mask SOH EQU 1 STX EQU 2 ETX EQU 3 EOT EQU 4 DLE EQU 16 CR EQU 13 LF EQU 10 CTRLZ EQU 1AH ; CLEAR: MVI A,11 ;clear screen CALL OUTT START: LXI SP,STACK CALL TOFF ;tape unit off CALL CRLF LXI H,CMSG ;command message CALL SENDM ;print it XRA A ;get a zero STA LFLAG ;reset load flag STA EFLAG ;zero error count CALL CRLF MVI A,':' ;prompt CALL OUTT ;print a prompt CALL READ ;input task from console CPI 'D' ;dump file to tape JZ DUMP CPI 'L' ;load to memory JZ LOAD CPI 'C' ;copy all to memory JNZ ERROR MVI A,1 STA LFLAG ;set load flag ; ; input address from terminal and load into memory ; HL is memory pointer; BC is data sum ; LOAD: CALL READHL ;input start address CALL GO ;wait for CR CALL TON ;tape unit on XCHG LXI H,CSUMT ;start of checksum table SHLD CPNTR ;reset pointer to start XCHG LOADN: CALL INBYTE ;get a byte CPI EOT ;end of file? JZ DONE ;yes CPI SOH ;start of block? JNZ LOADN ;loop until start XRA A ;get a zero MOV B,A ;zero the data sum MOV C,A LXI D,BLOCK ;current block number ; ; input the block number (1-8 hex characters) ; NOTE: there is no check for > 8 characters ; BLCKN: PUSH D CALL INBYTE ;get a byte POP D STAX D ;save digit of block number INX D CPI STX ;end of number? JNZ BLCKN ;loop until end DCX D ;back pointer to STX MVI A,' ' STAX D ;clear STX ; ; input the text ; TEXT: CALL INBYTE ;get a byte CPI ETX ;end of block? JZ DEND CPI DLE ;control character? JNZ MOVE ;no, put byte in memory CALL BYTE ;get the control character CALL INBY2 ;add to check sum ANI 1FH ;convert to control character MOVE: MOV E,A ; LDA LFLAG ;see if loading all ORA A JNZ TEXT ;skip second prnting MOV M,E ;put byte in memory MOV A,E ;echo to screen while reading CALL OUTT INX H ;increment memory pointer JMP TEXT ;next byte ; ; end of block - get checksum and compare ; to calculated sum ; DEND: LDA LFLAG ;check load flag ORA A ;see if zero JNZ DEN2 ;skip if full load MVI M,CR ;put CR in memory CALL CRLF ;put CR on screen INX H ;increment pointer DEN2: PUSH B ;save sum CALL FIXSM ;get first two characters MOV D,A ;put in H CALL FIXSM ;get second two characters MOV E,A ;put in L POP B ;retrieve sum XCHG ; ;check sum to HL DAD B ;add data sum to checksum MOV A,H ORA L ;see if both H & L are zero XCHG ; ;restore pointer to HL JZ LOADN ;ok, start next block ; ; checksum error. save block number in buffer for ; later listing ; PUSH H LXI D,BLOCK ;block number LHLD CPNTR ;pointer to checksum table NCHAR: LDAX D ;get block character MOV M,A ;put in table INX D INX H SHLD CPNTR ;save pointer CPI ' ' JNZ NCHAR ;next character MVI M,CTRLZ ;put ctrl-Z at end of table LDA EFLAG ;fetch error count INR A DAA ; ;convert to decimal STA EFLAG ;save new value POP H ;restore text pointer JMP LOADN ; ; input two bytes for half of checksum ; convert to one binary byte in A ; FIXSM: CALL BYTE5 ;get first byte RLC ;rotate to upper half RLC RLC RLC MOV B,A ;save in B CALL BYTE5 ;get second part ORA B ;combine both parts RET ; ; get a byte without altering checksum ; BYTE5: CALL BYTE MOV E,A CALL INBY3 ;see if loading all ANI 0FH ;keep lower four bits RET ; ; input a byte from file, add to checksum ; check for end of file ; INBYTE: CALL BYTE ;get the byte INBY2: MOV E,A ;save byte in E ADD C ;add to sum MOV C,A ;put new sum back in C JNC INBY3 ;done if no carry INR B ;add carry to B INBY3: LDA LFLAG ;ckeck load flag ORA A MOV A,E RZ MOV M,A ;put control bytes in memory INX H ;increment pointer RET ; ; input a byte from file ; BYTE: IN FSTAT ;ckeck file status ANI FIMSK JZ BYTE ;loop until ready IN FDATA ;get byte ANI 127 ;strip parity RET ; ; end of file, print pointer ; DONE: CALL OUTHL MVI M,CTRLZ ;ctrl-Z marks end LDA EFLAG ;see if any checksum errors ORA A JZ START ;no, restart MOV B,A ;save error count CALL CRLF MOV A,B CALL OUTHX ;print number of errors LXI H,EMESG ;point to error message CALL SENDM ;print it ; ; print block numbers which had checksum errors ; PLINES: CALL CRLF PLIN2: MOV A,M ;get character INX H ;increment pointer CPI 1 ;binary 1 at end of table JZ START ;done CPI ' ' ;blank at end of number JZ PLINES ;start on next number CALL OUTT ;print character JMP PLIN2 ;next character ; ; routine to send text in memory to tape ; ad time delay after CR ; DUMP: CALL READHL ;get starting address CALL GO ;wait for CR CALL TON ;tape unit on DMP2: MOV A,M ;fetch byte INX H ;increment pointer CPI CTRLZ ;ctrl-Z at buffer end JZ START ;done CALL TOUT ;output byte JMP DMP2 ;continue - NO delay *CPI CR ;check for CR *JNZ DMP2 ;continue if not *MVI D,120 ;outer timing loop *DMP3: MVI E,200 ;inner timing loop *DMP4: DCR E *JNZ DMP4 ;loop on E *DCR D *JNZ DMP3 ;loop on D *JMP DMP2 ;delay done ; ; routine to output a byte to tape ; TOUT: PUSH PSW TOUTW: IN TSTAT ;check status ANI TOMSK ;mask unwanted bits JZ TOUTW ;loop until ready POP PSW ;get byte OUT TDATA RET ; ; console input routine ; READ: CALL SINP ;SOLOS input JZ READ ANI 127 ;strip parity CPI 3 ;ctrl-C? JZ START ;restart CPI 24 ;ctrl-X? JZ MONIT ;return to monitor ; ; console output routine ; OUTT: PUSH PSW OUTW: PUSH B MOV B,A CALL SOUT ;SOLOS output POP B POP PSW RET ; ; input an address to HL from console ; READHL: PUSH D CALL RDHEX ;input high half MOV H,A CALL RDHEX ;input low half MOV L,A POP D RET ; ; input two hex characters and convert to ; a binary byte in E ; RDHEX: CALL HEX2 ;read upper character RLC RAL ;rotate RAL RAL MOV E,A CALL HEX2 ;read lower half ADD E ;combine in both MOV E,A ;save in E RET ; ; input a hex character to A ; HEX2: CALL READ ;console input SUI '0' ;remove ASCII bias JC ERROR ;error, less than '0' CPI 23 JNC ERROR ;error, greater than 'F' CPI 10 RC ; ;a number 0-9 SUI 7 CPI 10 RNC ; ;a letter A-F ERROR: MVI A,'?' CALL OUTT ;print ? for error JMP START ; ; output a double byte in hex ; OUTHL: MOV A,H ;get H CALL OUTHX ;print it MOV A,L ;get L ; ; convert a binary byte to two hex characters ; and print them ; OUTHX: PUSH PSW PUSH PSW RAR ; ;rotate upper character to lower RAR RAR RAR CALL HEX1 ;output upper character POP PSW CALL HEX1 ;output lower character POP PSW RET ; ; output a hex character from ; lower four bits ; HEX1: ANI 0FH ;mask upper four bits ADI 90H DAA ACI 40H DAA JMP OUTT ; ; look for a character ; return at end of console input line ; GO: CALL READ CPI CR JNZ ERROR ; ; line feed and carriage return to console ; CRLF: MVI A,LF CALL OUTT MVI A,CR CALL OUTT RET ; ; send message to console until binary ; zero is found. HL points to message ; SENDM: MOV A,M ;fetch byte CALL OUTT ;print it INX H ;increment pointer ORA A ;zero at end JNZ SENDM ;keep going RET ; TON: MVI A,80H+20H ;set 300 baud, unit 1 on OUT TSTAT MVI B,2 DELAY: LXI D,0 ;delay as in SOLOS DLOP1: DCX D MOV A,D ORA E JNZ DLOP1 DCR B JNZ DELAY RET ; TOFF: MVI B,1 ;turn units off CALL DELAY XRA A OUT TSTAT RET ; ; ; EFLAG DB 0 ;checksum error count LFLAG DB 0 ;load flag CPNTR DW CSUMT ;pointer to checksum table CMSG ASC 'Type C, L, or D followed by a four digit hex address' DB LF,CR ASC 'C = copy as is; L = load as text; D = dump memory' DB 0 EMESG ASC ' Checksum errors' DB 0 BLOCK DS 8 ;store current block number DS 1 ;pad for STX - bug in original CSUMT DS 40 ;table of error records ;