mirror of
https://github.com/PDP-10/its.git
synced 2026-01-29 13:21:11 +00:00
committed by
Lars Brinkhoff
parent
4e528d3ae7
commit
cc5789597e
578
src/sysen3/hexify.1
Normal file
578
src/sysen3/hexify.1
Normal file
@@ -0,0 +1,578 @@
|
||||
;-*- Midas -*-
|
||||
;Hex format:
|
||||
;:LL AAAA TT DD DD DD DD .. DD CC
|
||||
;LL: number of DD bytes AAAA: load address TT: 00 (or 01 for end rec)
|
||||
;DD: data bytes. CC: complemented checksum of all the bytes
|
||||
;Last record has rec-len 0, or can use TT=01 thing with AAAA=execution address
|
||||
;For CP/M execution address is irrelevant. (always 0100)
|
||||
|
||||
A=1 ;general purpose, arg passing
|
||||
B=2
|
||||
C=3
|
||||
D=4
|
||||
|
||||
RLen=5 ;intended record length
|
||||
RRLen=6 ;real record length (after ignoring gapchrs)
|
||||
Chksum=7 ;checksum while record-building
|
||||
|
||||
Cnt=10 ;number of bytes left in file
|
||||
BP=11 ;ildb byte point to file buffer
|
||||
|
||||
TT=12 ;super temps, clobberable by all routines/macros
|
||||
TT1=13
|
||||
|
||||
p=17
|
||||
|
||||
dskf==1 ;disk channel
|
||||
ttyo==2 ;tty output channel, for typeout.
|
||||
|
||||
Call=PUSHJ P,
|
||||
Return=POPJ P,
|
||||
|
||||
PDLen==20
|
||||
JCLen==20 ;100 chars, more than enuff
|
||||
|
||||
;;offsets in filename blocks
|
||||
DEV==0
|
||||
FN1==1
|
||||
FN2==2
|
||||
SNM==3
|
||||
|
||||
define syscal op,args
|
||||
.CALL [SETZ ? SIXBIT /op/ ? args ((SETZ))]
|
||||
termin
|
||||
|
||||
define Type &string
|
||||
movei TT,<.Length string>
|
||||
move TT1,[440700,,[Ascii string]]
|
||||
.call TTYTYP
|
||||
.Lose %LsSys
|
||||
Termin
|
||||
|
||||
define Terpri chnl
|
||||
.iot chnl,CR
|
||||
.iot chnl,LF
|
||||
Termin
|
||||
|
||||
;;options variables
|
||||
RecSep: 1 ;0: nothing separates record
|
||||
;1: CRLF after each record
|
||||
;other choices as need arises.
|
||||
gapchr: -1 ;if ge 0, character which we assume gets placed
|
||||
;in gaps. Will make hex file which may have
|
||||
;gaps instead of writing out this character, if
|
||||
;that will save some room in the file.
|
||||
;if -1, write out all chars, no gaps allowed.
|
||||
|
||||
Addr: 400 ;100H - initial load addr, updated as we go
|
||||
|
||||
EAddr: -1 ;execution address (defaultly same as Addr)
|
||||
EType: 1 ;type of last, 0-length record - 0 or 1
|
||||
|
||||
RecLen: 16. ;maximum record length
|
||||
|
||||
Switch: ;;A has character
|
||||
cain A,"C ;/C - contiguous records
|
||||
jrst SwiC
|
||||
cain A,"G
|
||||
jrst SwiG ;/G - gaps allowed
|
||||
cain A,"A
|
||||
jrst SwiA ;/A - load address
|
||||
cain A,"E
|
||||
jrst SwiE ;/E - execution address
|
||||
cain A,"T
|
||||
jrst SwiT ;/T - type of last record
|
||||
cain A,"R
|
||||
jrst SwiR ;/R - record length
|
||||
Type "AUnknown switch /"
|
||||
.iot ttyo,A
|
||||
Type " ignored.
|
||||
"
|
||||
Ret1: aos (p) ;don't re-use char
|
||||
Ret: return
|
||||
|
||||
SwiC: setzm RecSep
|
||||
jrst Ret1
|
||||
|
||||
SwiG: ;;Gaps allowed. /G:hh where hh are hex digits.
|
||||
setzm GapChr ;default gap char is 0
|
||||
ildb A,BP
|
||||
caie A,":
|
||||
return
|
||||
call UnHex
|
||||
cain A,"H
|
||||
aos (p) ;don't reuse char if luser typed "H" at end
|
||||
movem TT,GapChr ;if GapChr out of range, no big deal...
|
||||
return
|
||||
|
||||
SwiA: ;;/A:hhhh - load address
|
||||
ildb A,BP
|
||||
caie A,":
|
||||
return
|
||||
call UnHex
|
||||
cain A,"H
|
||||
aos (p)
|
||||
movem TT,Addr
|
||||
return
|
||||
|
||||
SwiE: ;;/E:hhhh - execution address
|
||||
ildb A,BP
|
||||
caie A,":
|
||||
return
|
||||
call UnHex
|
||||
cain A,"H
|
||||
aos (p)
|
||||
movem TT,EAddr
|
||||
return
|
||||
|
||||
SwiT: ;;/T - type of last record is 00
|
||||
setzm EType
|
||||
jrst ret1
|
||||
|
||||
SwiR: ;;/R:hh - record length
|
||||
ildb A,BP
|
||||
caie A,":
|
||||
return
|
||||
call UnHex
|
||||
cain A,"H
|
||||
aos (p)
|
||||
andi TT,377
|
||||
jumpe TT,[Type "ARecord length must be between 1 and FF
|
||||
"
|
||||
return]
|
||||
movem TT,RecLen
|
||||
return
|
||||
|
||||
|
||||
UnHex: ;;Read Hex until get non-hex (leave in A). TT gets value
|
||||
setz TT,
|
||||
UnHex1: ildb A,BP
|
||||
cail A,140
|
||||
subi A,40
|
||||
cail A,"0
|
||||
caile A,"F
|
||||
return
|
||||
caile A,"9
|
||||
cail A,"A
|
||||
skipa
|
||||
return
|
||||
subi A,"0
|
||||
cail A,10.
|
||||
addi A,"0-"A+10.
|
||||
imuli TT,16.
|
||||
add TT,A
|
||||
jrst UnHex1
|
||||
|
||||
Begin: Move P,PDList
|
||||
Syscal OPEN,[%Clbit,,.uao\%TJDIS ;Allow ^P usage
|
||||
%Climm,,TTYo
|
||||
[Sixbit /TTY/]]
|
||||
.Lose %LsFil
|
||||
call Jcl ;parse jcl
|
||||
skipge EAddr
|
||||
jrst [move TT,Addr ? movem TT,EAddr ? jrst .+1]
|
||||
skipn ISNAME
|
||||
.suset [.rHSname,,ISNAME]
|
||||
skipn IFN1
|
||||
.suset [.rUNAME,,IFN1]
|
||||
call RdFile ;snarf file, set up BP,Cnt
|
||||
Type "AHexifying file "
|
||||
movei A,IDEV ? Call FilTyp
|
||||
Terpri ttyo
|
||||
skipn OSNAME
|
||||
.suset [.rHSname,,OSNAME]
|
||||
skipn OFN1
|
||||
jrst [move TT,IFN1 ? movem TT,OFN1 ? jrst .+1]
|
||||
call OutOpn ;open output file
|
||||
Type "ALoad Address="
|
||||
move A,Addr ? Call H2Typ
|
||||
Type "H, Execution Address="
|
||||
move A,EAddr ? Call H2Typ ?
|
||||
Type "HARecord Length="
|
||||
move A,RecLen ? Call H1Typ
|
||||
skipge A,GapChr
|
||||
jrst [Type "H, no gaps"
|
||||
jrst B1]
|
||||
jumpe A,[Type "H, gaps allowed"
|
||||
jrst B1]
|
||||
Type "H, gap char="
|
||||
call H1Typ
|
||||
B1: type ".
|
||||
"
|
||||
call Hex ;Do it (closes file)
|
||||
.close dskf,
|
||||
move A,RecNum ? Call HTyp
|
||||
type "H records written to "
|
||||
movei A,ODEV ? call FilTyp
|
||||
Die: .logout 1,
|
||||
|
||||
Help: Type "A:HEXIFY input file,output file /switch /switch /switch
|
||||
|
||||
Convert input file, which must be a 'COM' file, into Intel Hex format.
|
||||
|
||||
Input file defaults to DSK:hsname;uname COM,
|
||||
output file defaults to DSK:hsname;input_fn1 HEX.
|
||||
|
||||
Normally creates records of length 10H, each followed by CRLF, starting
|
||||
with load address of 0100H. The last record has length 0, and is of type
|
||||
01, with address same as the initial load address. Switches can be used
|
||||
to change this.
|
||||
|
||||
In the switch descriptions, 'h' stands for hex digits.
|
||||
|
||||
/C -- make records Contiguous, i.e. do not put CRLF after each one.
|
||||
/A:hhhh -- Make the initial load address hhhh
|
||||
/E:hhhh -- Make the execution address (the address on last record) be hhhh
|
||||
/T -- make the last record be of type 00
|
||||
/G -- allow 'gaps'. The program will try to save space by not writing out
|
||||
all the 0 bytes, manipulating the address field of records instead.
|
||||
/G:hh -- like /G, but do it for 'hh' bytes, rather than 00. This is if your
|
||||
loader fills gaps with something other than 0's (Huh?)
|
||||
/R:hh -- make each record (at most) hh bytes long.
|
||||
"
|
||||
jrst Die
|
||||
|
||||
Jcl: ;;BP=pointer to jcl, D=first filename block.
|
||||
;;clobbers everything in sight
|
||||
.break 12,[..rJCL,,JCLBUF]
|
||||
skipn JCLBUF
|
||||
jrst Help ;No jcl -> help
|
||||
move BP,[440700,,JCLBUF]
|
||||
JclQp: ;;check for first char being ?
|
||||
ildb A,BP
|
||||
caie A,40
|
||||
cain A,^I
|
||||
jrst JclQp
|
||||
cain A,"?
|
||||
jrst Help
|
||||
movei D,IDEV
|
||||
jrst JclReU
|
||||
JclNew: seto A, ;don't re-use last char
|
||||
JclReU: movei Cnt,6
|
||||
setz C,
|
||||
move B,[440600,,C]
|
||||
skipge A
|
||||
JclNxt: ildb A,BP
|
||||
jumpe A,JclFil
|
||||
caie A,^C
|
||||
cain A,^M
|
||||
jrst JclFil
|
||||
skipe Quote
|
||||
jrst [setzm Quote ? jrst JclAdd] ;if quoting, ok
|
||||
cain A,^Q
|
||||
jrst [setom Quote ? jrst JclNxt]
|
||||
cain A,":
|
||||
jrst [skipe C ? movem C,DEV(D)
|
||||
jrst JclNew]
|
||||
cain A,";
|
||||
jrst [skipe C ? movem C,SNM(D)
|
||||
jrst JclNew]
|
||||
caie A,",
|
||||
cain A,"/
|
||||
jrst JclFil
|
||||
caie A,40
|
||||
cain A,^I
|
||||
jrst JclFil
|
||||
JclAdd: sojl Cnt,JclNxt ;ignore extra chars if passed limit
|
||||
cail A,140
|
||||
subi A,40
|
||||
subi A,40
|
||||
idpb A,B
|
||||
jrst JclNxt
|
||||
|
||||
JclFil: ;A has ^@,^C,^M,comma,/,space,tab
|
||||
jumpe C,JclF1
|
||||
skipn FN1(D)
|
||||
jrst [movem C,FN1(D) ? jrst JclF1]
|
||||
movem C,FN2(D)
|
||||
JclF1: caie A,40
|
||||
cain A,^I
|
||||
jrst JclNew
|
||||
cain A,",
|
||||
jrst [movei D,ODEV ? jrst JclNew]
|
||||
caie A,"/
|
||||
return ;all but Space,tab,slash and comma say DONE!
|
||||
;;Ok, have a switch
|
||||
JclSwi: ildb A,BP
|
||||
cail A,140
|
||||
subi A,40
|
||||
call Switch ;skip return if don't want to reuse A
|
||||
jrst JclReU
|
||||
jrst JclNew
|
||||
|
||||
;;FilTyp(A=file block)
|
||||
FilTyp: move TT,DEV(A)
|
||||
call 6Type ;print device
|
||||
.iot ttyo,[":]
|
||||
.iot ttyo,Space
|
||||
move TT,SNM(A)
|
||||
call 6Type
|
||||
.iot ttyo,[";]
|
||||
.iot ttyo,Space
|
||||
move TT,FN1(A)
|
||||
call 6Type
|
||||
.iot ttyo,Space
|
||||
move TT,FN2(A)
|
||||
6Type: setz TT1,
|
||||
rotc TT,6
|
||||
addi TT1,40
|
||||
.iot ttyo,TT1
|
||||
jumpn TT,6TYPE
|
||||
return
|
||||
|
||||
Hexout: ;;A has byte to add to Record buffer
|
||||
move TT,A
|
||||
lsh TT,-4
|
||||
call Hexou1
|
||||
move TT,A
|
||||
Hexou1: call HToA
|
||||
idpb TT,RecBP
|
||||
return
|
||||
|
||||
HTyp: ;;A has number- type it out in full.
|
||||
move TT,A
|
||||
jffo TT,.+3
|
||||
.iot ttyo,["0]
|
||||
return
|
||||
andi TT1,74 ;TT1= 4*(number of leading zero digits)
|
||||
subi TT1,40
|
||||
HTyp1: lsh TT,(TT1)
|
||||
call HToA
|
||||
.iot ttyo,TT
|
||||
move TT,A
|
||||
addi TT1,4
|
||||
jumple TT1,HTyp1
|
||||
return
|
||||
|
||||
H2Typ: ;;A has word
|
||||
push p,A
|
||||
lsh A,-8.
|
||||
call H1Typ
|
||||
pop p,A
|
||||
H1Typ: ;;A has byte
|
||||
move TT,A
|
||||
lsh TT,-4
|
||||
call H1Typ1
|
||||
move TT,A
|
||||
H1Typ1: call HToA
|
||||
.iot ttyo,TT
|
||||
return
|
||||
|
||||
|
||||
|
||||
HToA: andi TT,17
|
||||
addi TT,"0
|
||||
caile TT,"9
|
||||
addi TT,-10.+"A-"0
|
||||
return
|
||||
|
||||
|
||||
WrRec: ;;RRLen has length of record (number of data bytes) - clobbered
|
||||
;;write stored record to disk file, reset record bp.
|
||||
add RRLen,RRLen
|
||||
addi RRLen,11. ;A:total length,in chars, of output record
|
||||
move TT,[440700,,Record]
|
||||
syscall SIOT,[%Climm,,dskf ? TT ? RRLen] ;output it
|
||||
.Lose %LsFil
|
||||
aos RecNum ;for record keeping
|
||||
move TT,[350700,,Record]
|
||||
movem TT,RecBP ;reset byte pointer
|
||||
skipg RecSep
|
||||
return
|
||||
terpri dskf
|
||||
return
|
||||
|
||||
|
||||
Hex: ;;ADDR / RecLen set up
|
||||
;;File snarfed, Cnt,BP set up. Assume Cnt greater'n 0
|
||||
ildb A,BP
|
||||
came A,gapchr
|
||||
jrst Hex1
|
||||
aos Addr
|
||||
sojle Cnt,Done
|
||||
jrst Hex
|
||||
Hex1: ;gapchrs skipped. A has first byte, BP moved over
|
||||
move RLen,RecLen ;maximum length of record
|
||||
camle RLen,Cnt
|
||||
move RLen,Cnt ;use real length if all fits
|
||||
sub Cnt,RLen ;update Cnt
|
||||
;;ok, compute real length, after removing gapchrs, into RRLen
|
||||
;;maybe leaving the new BP on stack (if there's a gapchr)
|
||||
move RRLen,RLen
|
||||
skipge gapchr
|
||||
jrst DoIt ;dont bother with this if no gapchr
|
||||
;;ok, there is a gapchr - trim off trailing gapchr's
|
||||
push p,BP
|
||||
push p,RLen
|
||||
Hex2: sojle RLen,Hex3
|
||||
ildb TT,BP
|
||||
came TT,gapchr
|
||||
move RRLen,RLen
|
||||
jrst Hex2
|
||||
Hex3: pop p,RLen
|
||||
subm RLen,RRLen ;RRLen: real record length, minus
|
||||
aoj RRLen, ;trailing gapchrs
|
||||
exch BP,(p) ;save the new BP on stack
|
||||
;;ok, RLen has claimed record len(for updating Addr),
|
||||
;;RRLen is real number of chars to send in record (having ignored gapchrs)
|
||||
;;possibly have new BP saved on stack.
|
||||
;;A has first byte
|
||||
;;Output record, update addr, BP
|
||||
DoIt: push p,A
|
||||
move Chksum,RRLen ;Chksum: checksum
|
||||
move A,RRLen ? call Hexout ;append length to record buffer
|
||||
move A,Addr ? lsh A,-10 ;A: high byte of address
|
||||
addm A,Chksum ? call Hexout ;output it
|
||||
move A,Addr ? addm A,Chksum ? call Hexout ;low byte of address
|
||||
addm RLen,Addr ;update address
|
||||
setz A, ? call Hexout ;output type (00)
|
||||
pop p,A ;get back the first byte
|
||||
move B,RRLen ;B: real record length
|
||||
HexDat: addm A,Chksum ? call Hexout ;output data bytes
|
||||
sojle B,RecOut
|
||||
ildb A,BP
|
||||
jrst HexDat
|
||||
RecOut: movn A,Chksum ;output negative of checksum
|
||||
call Hexout
|
||||
call WrRec ;Note: needs RRLen, clobbers it.
|
||||
skipl gapchr
|
||||
pop p,BP ;if doing gap stuff, get real next BP
|
||||
|
||||
jumpg Cnt,Hex ;if more to send, do it again
|
||||
|
||||
|
||||
Done: ;;send out the final record
|
||||
setz A, ? call Hexout ;0 length record
|
||||
move A,EAddr ? lsh A,-8. ? move Chksum,A ? call Hexout
|
||||
move A,EAddr ? add Chksum,A ? call Hexout
|
||||
move A,EType ? add Chksum,A ? call Hexout
|
||||
movn A,Chksum ? call Hexout
|
||||
setz RRLen,
|
||||
jrst WrRec ;write out last record and return
|
||||
|
||||
|
||||
OutOpn: ;;open output file on dskf channel
|
||||
;;ODEV,OSNAME,OFN1,OFN2 get truenames
|
||||
came OFN2,[sixbit/>/]
|
||||
camn OFN2,[sixbit/</]
|
||||
jrst OutOpY
|
||||
camn ODEV,[sixbit/TTY/]
|
||||
jrst OutOpY
|
||||
syscall OPEN,[%Clbit,,.uii ? %Climm,,dskf
|
||||
ODEV ? OFN1 ? OFN2 ? OSNAME]
|
||||
jrst OutOpY
|
||||
.call ORFNAM
|
||||
.Lose %LsFil
|
||||
.close dskf,
|
||||
syscall OPEN,[%Clbit,,.uai ? %Climm,,dskf ? [sixbit/TTY/]]
|
||||
.Lose %LsFil
|
||||
Type "File "
|
||||
movei A,ODEV
|
||||
call FilTyp
|
||||
Type " already exists. Write over it (Y or N)?"
|
||||
.iot dskf,TT
|
||||
.close dskf,
|
||||
caie TT,"Y
|
||||
cain TT,"y
|
||||
jrst OutOpY
|
||||
jrst Die
|
||||
|
||||
OutOpY: syscal OPEN,[%Clbit,,.uao ? %Climm,,dskf ? ODEV ? OFN1 ? OFN2 ? OSNAME]
|
||||
.Lose %LsFil
|
||||
.call ORFNAM
|
||||
.Lose %LsFil
|
||||
return
|
||||
|
||||
|
||||
RdFile: ;;read in file, check DSK8, set up BP and Cnt.
|
||||
call SNARF
|
||||
move TT,FILBFR
|
||||
came TT,[sixbit/DSK8/]
|
||||
jrst [Type "Not a standard COM file."
|
||||
jrst Die]
|
||||
move BP,[440800,,FILBFR+1] ;pointer into file
|
||||
soj Cnt, ? imuli Cnt,4 ;4 bytes per word
|
||||
return
|
||||
|
||||
SNARF: ;;snarf input file into memory at FILBFR. Allocates pages as needed.
|
||||
;;IDEV,IFN1,IFN2,ISNAME get updated to truenames.
|
||||
syscall OPEN,[%Clbit,,.uii ? %Climm,,dskf
|
||||
IDEV ? IFN1 ? IFN2 ? ISNAME]
|
||||
jrst [type "Can't open file "
|
||||
movei A,IDEV
|
||||
call FilTyp
|
||||
jrst Die]
|
||||
syscall RFNAME,[%Climm,,dskf ? %Clout,,IDEV
|
||||
%Clout,,IFN1 ? %Clout,,IFN2 ? %Clout,,ISNAME]
|
||||
.Lose %LsFil
|
||||
syscall fillen,[%Climm,,dskf ? %Clout,,A] ;file length
|
||||
.Lose %LsFil
|
||||
jumpe A,[type "Empty input file?"
|
||||
jrst Die]
|
||||
movem A,Cnt ;save for future use
|
||||
addi A,<FILBFR-1>+2000 ;A: last address which we need + 2000
|
||||
lsh A,-12 ;A: number of pages we need
|
||||
movei TT,<FILBFR_-12>+1 ;TT: first page we need to get
|
||||
subm TT,A ;A: -<number of pages to get>
|
||||
jumpe A,SNARF0 ;if fits in what we have, done
|
||||
hrl TT,A ;TT: -#pages to get,,first page to get
|
||||
syscal corblk,[%Climm,,%Cbprv ;Get fresh pages
|
||||
%Climm,,%Jself
|
||||
TT
|
||||
%Climm,,%Jsnew]
|
||||
jrst [Type "Can't get enough memory"
|
||||
jrst Die]
|
||||
SNARF0: move A,[444400,,FILBFR] ;A: BP to first file address
|
||||
move TT,Cnt ;number of words
|
||||
Syscal siot,[%Climm,,dskf ? A ? TT] ;Inhale file
|
||||
.Lose %LsFil
|
||||
jumpg TT,[Type "SIOT lost!?!? Couldn't read in whole file! Try again."
|
||||
jrst Die]
|
||||
.close dskf,
|
||||
return
|
||||
|
||||
|
||||
IDEV: sixbit/DSK/
|
||||
IFN1: 0
|
||||
IFN2: sixbit/COM/
|
||||
ISNAME: 0
|
||||
|
||||
ODEV: sixbit/DSK/
|
||||
OFN1: 0
|
||||
OFN2: sixbit/HEX/
|
||||
OSNAME: 0
|
||||
|
||||
;;RFNAME call for Output file
|
||||
ORFNAM: setz ? sixbit/RFNAME/ ? %Climm,,dskf
|
||||
%Clout,,ODEV ? %Clout,,OFN1 ? %Clout,,OFN2 ? %Clout,,OSNAME ((setz))
|
||||
|
||||
;;SIOT call for tty typeout - TT has length, TT1 has BP
|
||||
TTYTYP: SETZ ? SIXBIT /SIOT/ ? %Climm,,ttyo ? TT1 ? TT ((SETZ))
|
||||
|
||||
|
||||
Space: 40 ;seems to be used often enough...
|
||||
CR: ^M
|
||||
LF: ^J
|
||||
|
||||
Quote: 0 ;used inside Jcl parser
|
||||
|
||||
Record: ascii/:0000/ ;at most data bytes, so total length of
|
||||
block 150 ;record is at most 521. chars, i.e.
|
||||
;151 (105.) words
|
||||
RecBP: 350700,,Record ;pointer to next chr
|
||||
|
||||
RecNum: 0 ;number of records written. For reporting
|
||||
|
||||
JCLBuf: Block JCLen
|
||||
|
||||
PDList: -PDLen,,PDList
|
||||
Block PDLen
|
||||
|
||||
|
||||
|
||||
Variables
|
||||
Constants
|
||||
|
||||
FILBFR: 0 ;final address. File will go here.
|
||||
|
||||
END Begin
|
||||
Reference in New Issue
Block a user