; Extra MT commands 12/4/02 3/15/03 9/8/04 9/2/07 10/4/07 ; Contains... ; MTDIR - tape directory ; DLTF - deletes last tape file ; file# MTSEEK - pops file# and positions to that file ; "Filename" Adr WordLen #datarecords MMTID - make file ID record ; "Filename" FromAdr ToAdr MTSAVE - save memory to file ; file# MTLOAD - loads file according to type.. if text (adr=0) ; then directed to stdin, if memory loads, if system then mtboots ; "Filename" ByteLen MS2MT - copy MS input to magtape file ; file# MT2MS - copy magtape file to MS output ; "Filename" block# #words B2MT - write block mem to MT file ; file# block# MT2B - read block(s) from MT file ; file# MTSHOW - displays file ; "DefName" D2MT - saves definition to magtape file ; HELP - brief ;--------------------------------------------------- ; ** general-purpose tape file system ** ; store the filename in offset 5-16 oct with crlf at 4 ; offset 0 = 15400, same as a typical 33oct ABS ; offset 1 = binary load address (also for ABS) ; 2000 for MTGEN, 0 for text/ipl, any other is binary ; offset 2 = length of data record(s) in words ; offset 3 = number of data record(s) (normally 1) ; offset 4 = 6412 (crlf) to mark format ; offset 5-16 oct = 20 dec char filename ; offset 17 = presently not used ;--------------------------------------------------- "Variable IDREC" $PRINT CRLF OCTAL VARIABLE IDREC 20 ;to contain tape ID record ; "Loading MTDIR" $PRINT CRLF ; ; MTDIR - adapted from MTSCAN, lists version strings ; of HP-IPL/OS builds on a tape volume. Only recognizes ; recent versions (coded for version 0.54), if the kernal ; or MTGEN changes in any way that moves the string in the ; encoded ABS on magtape then this will need adjusting. ; For '54 version was moved to a place that won't move. ; Note - locks up if run on an empty volume. ; OCTAL DEFINE MTDIR CRLF MTINIT RWLP MTWAIT EOF #0 PUT RECORDS #0 PUT FILES #0 PUT DO MTINIT ;3/15/03 try to recover from read errors FS1R MTWAIT ?MTERROR MTSTATUS 240 AND IFZ RECORDS GET INC RECORDS SWAP PUT EOF #0 PUT #1 ELSE FILES GET INC FILES SWAP PUT EOF GET INC EOF SWAP PUT EOF GET 2 SUB IFZ BS1R MTWAIT #0 ELSE EOF GET IFZ #0 ELSE ;this bit redundant? "File " $PRINT FILES GET PNUM FILES GET #1 SUB IFZ RWLP MTWAIT ELSE BS1F MTWAIT BS1R MTWAIT RECORDS GET #1 SUB IFNZ ;if more than one record BS1F MTWAIT FS1R MTWAIT ;back up to header beginning ENDIF ;bit convolted... would like to simplify ENDIF ;not sure why a simple BS1R BS1F doesn't work IDREC 20 MTREAD MTWAIT FS1F MTWAIT IDREC GET 15400 SUB IFZ ;if 1st word = 15400 IDREC 4 ADD GET 6412 SUB IFZ ;if crlf found IDREC 5 ADD IDREC 16 ADD 40 PCHR +DO INDEX GET PWRD +LOOP #1 ;print "filename" ; prints HP-IPL/OS version from 0.54 and up MTGEN builds ; "filename" for other kinds of files. Print filetype... 20040 PWRD IDREC INC GET CASE = 2000 "System" $PRINT = 0 "File " $PRINT IDREC 2 ADD GET PNUM "words" $PRINT DEFAULT "Binary " $PRINT IDREC 2 ADD GET PNUM "words LA=" $PRINT IDREC INC GET PNUM ENDCASE ELSE #0 ENDIF ELSE #0 ENDIF IFZ " Records = " $PRINT RECORDS GET PNUM ENDIF CRLF RECORDS #0 PUT #1 ENDIF ENDIF ENDIF WHILE END ;--------------------------------------------------- "Loading DLTF" $PRINT CRLF ; ; DLTF - deletes the last tape file ; OCTAL DEFINE DLTF MTSCAN "Delete last tape file? (Y/N) " $PRINT CHRIN CRLF 131 SUB IFZ BS1F MTWAIT BS1F MTWAIT GAPMARK MTWAIT GAPMARK MTWAIT BS1R MTWAIT "Done" $PRINT ENDIF END ;--------------------------------------------------- "Loading MTSEEK" $PRINT CRLF ; ; file# MTSEEK - positions tape to specified file ; OCTAL DEFINE MTSEEK DUP DEC IF<0 DROP "Seek error" $PRINT ELSE MTINIT RWLP MTWAIT ;wake up and rewind tape DUP DEC IFZ DROP ELSE ;if file#1 just exit otherwise 2 SWAP +DO ;skip to file... MTSTATUS 76 AND IFZ ;if no error FS1F MTWAIT ;forward space one file ENDIF +LOOP ENDIF ?MTERROR ;print error if one occured ENDIF END ;--------------------------------------------------- "Loading MMTID" $PRINT CRLF ; ; MMTID - Make MagTape File ID record in IDREC and write to magtape ; Usage: "Filename" StartAdr Length #DataBlocks MMTID ; OCTAL DEFINE MMTID S>Z ;save #blocks IDREC 15400 PUT ;write 15400 to offset 0 SWAP IDREC INC SWAP PUT ;write StartAdr to offset 1 IDREC INC INC SWAP PUT ;write Length to offset 2 IDREC 3 ADD Z>S PUT ;write #blocks to offset 3 IDREC 4 ADD 6412 PUT ;write 6412 to offset 4 DO $LEN CASE < 24 40 $APPEND #0 DEFAULT #1 ENDCASE UNTIL ;string is 20 dec chars long $ADR ;push string address #0 11 +DO ;write filename to 5-16 INDEX OVER ADD GET ;get word from string IDREC INDEX ADD 5 ADD SWAP PUT ;write to fn slot +LOOP DROP $DROP ;string adr IDREC 40 MTWRITE MTWAIT ;write to tape, 32 dec words ?MTERROR GAP MTWAIT ;error-check, write 1 gap END ;--------------------------------------------------- "Loading MTSAVE" $PRINT CRLF ; ; MTSAVE - save an area of memory to tape ; Usage: "Filename" FromAdr ToAdr MTSAVE ; Note - there must already be something on tape! ; (put a boot file first) ; OCTAL DEFINE MTSAVE OVER OVER SWAP SUB DUP ;calculate length IF<0 "Error" $PRINT DROP $DROP ELSE INC ;now stack = start, end, length MTSCAN ;get to the end of tape "Saving " $PRINT S>Z OVER PNUM 10 PCHR "-" $PRINT DUP PNUM "to file " $PRINT $DUP $PRINT DROP ;don't need end address anymore ;length on Z, start on stack DUP Z>S DUP S>Z #1 MMTID ;start len #blocks makemagtapeid Z>S MTWRITE MTWAIT ?MTERROR ;write whatever's being saved GAPMARK MTWAIT GAPMARK MTWAIT BS1R MTWAIT ;terminate ENDIF END ;--------------------------------------------------- "Loading MTLOAD" $PRINT CRLF ; ; MTLOAD - "loads" the specified file ; if binary then loads into memory ; if text then redirects into stdin (like LOAD) ; if MTGEN build then boots it ; Usage: file# MTLOAD ; OCTAL DEFINE MTLOAD DUP MTSEEK ;go to file IDREC 20 MTREAD MTWAIT ;read header record IDREC GET 15400 SUB IFNZ "Unknown file" $PRINT DROP ELSE IDREC INC GET CASE = 2000 ;9/8/04 mod ALTSAVE ; save system to alt mem and add exit to himem -DMS MTBOOT ; turn off dms and boot tape file = 0 DROP ;already there UDMA 2 IDREC INC INC GET MTREAD MTWAIT ?MTERROR SDMA MS_SAVE 2 MSUSER CON DROP ;restore, drop original #bytes UPTR GET 2 SUB ;convert msuser pointer into word length MTSCAN ;get to end of tape "Writing file " $PRINT $DUP $PRINT DUP #0 SWAP #1 MMTID ;make ID record UDMA ;user DMA 2 SWAP MTWRITE MTWAIT ?MTERROR ;write data record SDMA ;back to system DMA GAPMARK MTWAIT GAPMARK MTWAIT BS1R MTWAIT ;terminate END ;--------------------------------------------------- "Loading MT2MS" $PRINT CRLF ; ; file# MT2MS - copy magtape file to MS output ; OCTAL DEFINE MT2MS MTSEEK IDREC 20 MTREAD MTWAIT IDREC GET 15400 SUB IFNZ "Unknown file" $PRINT ELSE UDMA 2 IDREC INC INC GET MTREAD MTWAIT SDMA ;read file 2 IDREC INC INC GET INC +DO ;from 2 to wlen+1 INDEX IDREC #1 A>CCOPY ;copy word to IDREC(0) IDREC GET MSWOUT ;copy IDREC(0) to MS output +LOOP ENDIF END ;--------------------------------------------------- "Loading B2MT" $PRINT CRLF ; ; "Filename" block# #words B2MT - write block memory to MT file ; OCTAL DEFINE B2MT $ADR DROP ;go ahead and bomb now if no filename SWAP 2000 MUL @BLK GET ADD DUP S>Z ;convert block to adr on Z @END GET SWAP SUB IF<0 ;test block# DROP Z>S DROP $DROP "Invalid block" $PRINT ELSE ;length on stack DUP Z>S DUP S>Z ADD @END GET SWAP SUB IF<0 ;test length DROP Z>S DROP $DROP "Past blocks" $PRINT ELSE ;length still on stack, block adr on Z MTSCAN ;get to end of tape "Writing new file " $PRINT $DUP $PRINT DUP #0 SWAP #1 MMTID ;write ID record (startadr=0, "file") Z>S SWAP MTWRITE MTWAIT ?MTERROR ;write data record to tape GAPMARK MTWAIT GAPMARK MTWAIT BS1R MTWAIT ENDIF ENDIF END ;--------------------------------------------------- "Loading MT2B" $PRINT CRLF ; ; file# block# MT2B - read block(s) from MT file ; reads back as many blocks as was written ; OCTAL DEFINE MT2B SWAP MTSEEK ;put file# on top of stack and seek IDREC 20 MTREAD MTWAIT ;read header record IDREC GET 15400 SUB IFNZ "Unknown file" $PRINT DROP ELSE 2000 MUL @BLK GET ADD ;convert block# into address IDREC INC INC GET ;get length from ID record OVER OVER ADD @END GET SUB IF<0 ;if not past end MTREAD MTWAIT ?MTERROR ;read data record into block(s) ELSE DROP DROP "Past blocks" $PRINT ENDIF ENDIF END ;--------------------------------------------------- "Loading MTSHOW" $PRINT CRLF ; ; file# MTSHOW - shows magtape (hopefully text) files ; OCTAL DEFINE MTSHOW MTSEEK IDREC 20 MTREAD MTWAIT IDREC GET 15400 SUB IFNZ "Unknown file" $PRINT ELSE IDREC DUP INC INC GET INC INC PUT ;copy length+2 to idrec(0) UDMA 2 IDREC INC INC GET MTREAD MTWAIT SDMA ;read file MS_SAVE 2 MSUSER ;redirect MS to alt map loc 2 #0 ;line counter DO MSBIN DUP PCHR 12 SUB IFZ INC ENDIF ;inc line count if char=LF DUP 27 SUB IFZ ;if 23 lines... (9/2/07 for 24 line display) DROP #0 "---- B F Q or any for next ---- " $PRINT CHRIN CASE ;10/3/07 modified to erase prompt = 102 ;back to beginning... 2 MSUSER CRLF ;set pointer to 2 = 106 ;skip forward 64 crlf's (max (idrec)) DROP 100 DO UPTR GET IDREC GET SUB IF<0 ;if pointer < max MSBIN 12 SUB IFZ DEC ENDIF ;get byte, if LF dec count ELSE DROP #0 ENDIF ;else count=0 to terminate DUP WHILE CRLF = 121 ;quit... UPTR 77777 PUT ;force pointer to max DEFAULT #0 42 +DO 4010 PWRD 40 PCHR +LOOP 10 PCHR ;erase prompt ENDCASE ENDIF UPTR GET IDREC GET SUB IF<0 #0 ELSE #1 ENDIF ;term. if >=end UNTIL MS_RESTORE DROP ENDIF END ;--------------------------------------------------- "Loading D2MT" $PRINT CRLF ; ; "DefName" D2MT - saves definition to magtape ; Saved with same filename as DefName ; Doesn't work with non-explainable definitions ; OCTAL DEFINE D2MT $DUP $DEFADR IFZ $PRINT " not found" $PRINT ELSE MTSCAN "Saving definition " $PRINT ;save definition to block 0 in IPL format... MS_SAVE #0 OUTBLOCK >MS $DUP $DEFADR PDEF "CONSOLE" $PRINT CRLF " " $PRINT <>CON MS_RESTORE #0 GETOP 2 DIV DUP S>Z #1 MMTID ;make ID rec, save wordlen on Z @BLK GET Z>S MTWRITE MTWAIT ?MTERROR ;write definition to 2nd record GAPMARK MTWAIT GAPMARK MTWAIT BS1R MTWAIT ;terminate ENDIF END ;--------------------------------------------------- "Loading HELP" $PRINT CRLF OCTAL DEFINE HELP "WORDS lists currently defined words" $PRINT CRLF "MTGEN saves system to magtape (sel new vol if empty)" $PRINT CRLF "MTDIR lists contents of magtape (must not be empty)" $PRINT CRLF "file# MTLOAD loads a system, binary or IPL magtape file" $PRINT CRLF "file# MTSHOW displays a text/IPL magtape file" $PRINT CRLF "file# MT2MS copies a magtape file to MS output" $PRINT CRLF 42 PCHR "MT Name" $PRINT 42 PCHR " ByteLen MS2MT copies file from MS to magtape" $PRINT CRLF 42 PCHR "MT Name" $PRINT 42 PCHR " From To MTSAVE saves memory to magtape" $PRINT CRLF 42 PCHR "DefName" $PRINT 42 PCHR " D2MT saves definition to magtape" $PRINT END ;--------------------------------------------------- "Done" $PRINT CONSOLE