mirror of https://github.com/markpmlim/EdAsm.git
4543 lines
138 KiB
ArmAsm
4543 lines
138 KiB
ArmAsm
Name : LINK.S
|
|
End of file : 91,112
|
|
This file was generated using the DiskBrowser utility with minimal editing.
|
|
It is meant for viewing purposes only.
|
|
|
|
;
|
|
; Initial code disassembled with the ORCA.DisAsm
|
|
; Source files for the Linker is of type REL
|
|
; The Linker can produce BIN, REL or SYS object files
|
|
;
|
|
; Init the Linker
|
|
;
|
|
AsmLinker EQU *
|
|
ldx #0
|
|
stx AsmLinker
|
|
php ;Save status reg
|
|
pla
|
|
sta Z9C ; here
|
|
sei ;No interrupts
|
|
;
|
|
lda #0
|
|
ZeroLoop sta Stack,x ;Zero stack area
|
|
inx
|
|
bne ZeroLoop
|
|
;
|
|
dex
|
|
txs ;=$FF
|
|
lda Z9C
|
|
pha ;Restore status reg
|
|
plp
|
|
;
|
|
lda #$00
|
|
sta MINIVERS ;minimum interpreter version
|
|
lda #$10
|
|
sta IVERSION ;interpreter version
|
|
lda #%00000011 ;Pages 6-7
|
|
sta BitMap ; are reserved
|
|
;
|
|
; Setup memory management
|
|
;
|
|
lda #%10101000
|
|
and #%00000111
|
|
tax ;(X)=0
|
|
ldy #0
|
|
tya ;(A)=0
|
|
NeverLoop ora BitsT,y ;Loop never executed?
|
|
iny
|
|
dex
|
|
bpl NeverLoop
|
|
;
|
|
eor #$FF ;(A)=%01111111
|
|
ldx #$15
|
|
and BitMap,x ;Mark page $A8
|
|
sta BitMap,x ; as free
|
|
;
|
|
lda #$00
|
|
dex
|
|
ZeroLup sta BitMap,x ;Pages $08-$A7
|
|
dex ; are free
|
|
bne ZeroLup
|
|
;
|
|
; Init various flags & variables
|
|
;
|
|
lda #$80 ;Set the following
|
|
sta MapFileF ; flags to ON
|
|
sta SortLMF
|
|
sta XRefF
|
|
sta ERefF
|
|
;
|
|
lda #$00 ;Set the following
|
|
sta PageF ;flags to OFF
|
|
sta OptDF
|
|
sta OptionsF
|
|
sta FTypeF
|
|
sta NumSortF
|
|
sta Origin ;Zero this
|
|
sta Origin+1
|
|
;
|
|
lda #1
|
|
sta LineCnt
|
|
sta PageCnt
|
|
;
|
|
; Try to open a default command (TXT)
|
|
; file named "EDASM.AUTOLINK"
|
|
;
|
|
ldy AutoLnkS
|
|
CpyLoop lda AutoLnkS,y
|
|
sta PathNameB,y
|
|
dey
|
|
bpl CpyLoop
|
|
;
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW OpCmdFP
|
|
beq DoPhase0
|
|
cmp #$46 ;fileNotFound
|
|
bne NoGood
|
|
beq FNF
|
|
;
|
|
OtherErr jsr PrtError ;(A)=err code, don't come back
|
|
;
|
|
FNF ldy #$00 ;Print Banner & prompt
|
|
jsr DspMsg ; for command filename
|
|
lda #'?'+$80
|
|
sta Prompt
|
|
jsr GetLine ;Use monitor's input rtn to get filename
|
|
stx PathNameB ;Save len byte
|
|
lda InBuf ;Did user choose to abort
|
|
cmp #CTRLC+$80 ; the linking process?
|
|
bne CpyLoop2
|
|
jmp Abort ;Yes
|
|
;
|
|
CpyLoop2 lda InBuf,x ;Copy the filename
|
|
and #$7F ; typed in & ensure all
|
|
sta PathNameB+1,x ; its chars are std ASCII
|
|
dex
|
|
bpl CpyLoop2
|
|
;
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW OpCmdFP
|
|
beq DoPhase0
|
|
;
|
|
cmp #$40 ;badPathSyntax
|
|
beq OtherErr
|
|
cmp #$44 ;pathNotFound
|
|
beq OtherErr
|
|
cmp #$45 ;volNotFound
|
|
beq OtherErr
|
|
cmp #$46 ;fileNotFound
|
|
beq OtherErr
|
|
;
|
|
NoGood jsr ErrHndlr ;Don't come back
|
|
;=================================================
|
|
; Phase 0: Setup environment for the Linker
|
|
; Each record in the Command File is a CR-terminated text line (msb off)
|
|
; Each text line is either
|
|
; a command to the Linker or
|
|
; the pathname of a source file of type REL
|
|
; Directives/Commands to the Linker must be preceded by
|
|
; at least 1 space while pathnames have no leading space(s)
|
|
;
|
|
DoPhase0 EQU *
|
|
lda OpCmdFP+c.outRef;Copy this to the fields
|
|
sta SMCmdFP+c.refNum; of other ProDOS parameter
|
|
sta NLCmdFP+c.refNum; blocks b4 we start to read
|
|
sta RdCmdFP+c.refNum; the CMD file line by line
|
|
;
|
|
; Ensure that all future READ operations on the Command
|
|
; File is terminated by a CR or an EOF
|
|
;
|
|
jsr PRODOS8 ;NEWLINE
|
|
DB $C9
|
|
DW NLCmdFP
|
|
bne NoGood
|
|
;
|
|
lda #BINtype ;Default OBJECT filetype
|
|
sta TrgtFTyp
|
|
ldy #$03 ;Display "Phase0: Commands..."
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
;
|
|
; This loop only processes directives & ignores the pathnames
|
|
;
|
|
Phs0Loop jsr PollKbd
|
|
jsr Read1Cmd ;Is 1st char is a CR/SPACE?
|
|
bne NotCmd ;No, it's a PN of a src (REL) file
|
|
jsr DspLineB ;Show cmd
|
|
cmp #CR
|
|
bne Phs01 ;1st char not CR => SPACE
|
|
jmp CmdFileErr ;CR => null cmd line
|
|
;
|
|
Phs01 jsr SkipSpcs
|
|
jsr ChkDrtv ;Is it a directive?
|
|
bcs Phs0Loop ;Not valid, ignore
|
|
;
|
|
pha ;Index into JMP table
|
|
jsr WhiteSpc
|
|
jsr AdvCP ;Ensure cp is @ 1st char of directive
|
|
pla
|
|
jsr HndlDrtv ;Process directive
|
|
jmp Phs0Loop
|
|
;
|
|
; If 1st char is not CR/SPACE, then it is a pathname of a src file
|
|
;
|
|
NotCmd bit MapFileF ;Output a LinkMAP? (default ON)
|
|
bpl EndPhs0 ;No
|
|
jsr OpLnkMap ;Open LinkMap file for output
|
|
EndPhs0 jmp DoPhase1
|
|
;=================================================
|
|
; JMP via an RTS to parse the operand
|
|
; field of a directive
|
|
;
|
|
HndlDrtv tax
|
|
lda L36F0,x ;Directive JMP table
|
|
pha
|
|
lda L36EA,x
|
|
pha
|
|
rts
|
|
;=================================================
|
|
; BIN command/directive
|
|
; Input
|
|
; FTypeF=0 OBJECT file type not set
|
|
; Output
|
|
; FTypeF=1
|
|
; TrgtFTyp=BIN
|
|
; NB. Only one BIN/REL/SYS directive
|
|
; may be declared
|
|
;
|
|
CmdBin lda FTypeF ;Has the OBJ type been set?
|
|
beq CmdBin1 ;No
|
|
jmp DupCmdErr
|
|
;
|
|
CmdBin1 lda #$01
|
|
sta FTypeF ;Flag it's set
|
|
lda #BINtype
|
|
sta TrgtFTyp
|
|
jsr GetOutFN ;Get Link OBJ/MAP filenames
|
|
rts
|
|
;=================================================
|
|
; REL command/directive
|
|
; Input
|
|
; FTypeF=0
|
|
; Output
|
|
; FTypeF=$80
|
|
; TrgtFTyp=REL
|
|
;
|
|
CmdRel lda FTypeF
|
|
beq CmdRel1
|
|
jmp DupCmdErr
|
|
;
|
|
CmdRel1 lda #$80
|
|
sta FTypeF
|
|
lda #RELtype
|
|
sta TrgtFTyp
|
|
jsr GetOutFN
|
|
rts
|
|
;=================================================
|
|
; SYS command/directive
|
|
; Input
|
|
; FTypeF=0
|
|
; Output
|
|
; FTypeF=$02
|
|
; TrgtFTyp=SYS
|
|
;
|
|
CmdSys lda FTypeF
|
|
beq CmdSys1
|
|
jmp DupCmdErr
|
|
CmdSys1 lda #$02
|
|
sta FTypeF
|
|
lda #SYStype
|
|
sta TrgtFTyp
|
|
jsr GetOutFN
|
|
rts
|
|
;=================================================
|
|
; ORG command/directive
|
|
; Input
|
|
; Output
|
|
; Origin=Value of Expression
|
|
; Only 1 ORG may be declared and it must be b4 the src pathnames
|
|
;
|
|
CmdOrg lda Origin ;Already set?
|
|
ora Origin+1
|
|
beq CmdOrg1
|
|
jmp DupCmdErr ;Yes, duplicate cmd
|
|
;
|
|
CmdOrg1 jsr SkipSpcs
|
|
jsr ChrGot
|
|
beq BadOrg ;sp/cr
|
|
jsr EvalExpr
|
|
lda Value16 ;Chk it's valid
|
|
sta Origin
|
|
lda Value16+1
|
|
beq BadOrg ; < $0100
|
|
sta Origin+1
|
|
ora Origin
|
|
beq BadOrg ; $0000
|
|
rts
|
|
BadOrg jmp CmdSynErr ;syntax err
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ALN Command/Directive
|
|
; Align Origin @ start of next mempage
|
|
; Output
|
|
; Origin=$xx00
|
|
;
|
|
; This directive is usually used after a pathname
|
|
; and may be used repeatedly
|
|
;
|
|
CmdAln lda Origin ;ORG must be set first either by a
|
|
ora Origin+1 ; directive or via src filename
|
|
bne CmdAln1
|
|
jmp CmdOrderErr ;Wrong cmd order
|
|
;
|
|
CmdAln1 lda Origin ;Align @ the beginning
|
|
beq doRTS
|
|
inc Origin+1 ; of the next mempage
|
|
lda #$00
|
|
sta Origin
|
|
doRTS rts
|
|
;=================================================
|
|
; OPT command/directive. Only allowed to be used once
|
|
; Default
|
|
; OPT +M,+E,+S,+X,-N,-D,-P
|
|
; Input
|
|
; OptionsF
|
|
; Output
|
|
; OptionsF=1 - If Directive not declared
|
|
;
|
|
; One/Some/All of the following flags may be set
|
|
; M)apFileF - Output LinkMAP file (default ON)
|
|
; E)RefF - Add ENTRY records (default ON)
|
|
; S)ortLMF - Sort LoadMap table (default ON)
|
|
; X)RefF - Cross-referenced (default ON)
|
|
; N)umSortF - Sort LoadMap numerically (default OFF)
|
|
; O)ptDF - not used (default OFF)
|
|
; P)ageF - Pagination (default OFF)
|
|
;
|
|
CmdOptn EQU *
|
|
lda OptionsF ;First time directive is declared?
|
|
beq CmdOptn1 ;Yes
|
|
jmp DupCmdErr ;Duplicate cmd
|
|
;
|
|
CmdOptn1 inc OptionsF ;Flag we have encountered this cmd
|
|
jsr SkipSpcs
|
|
;
|
|
GetOptFlg jsr ChrGot ;chrgot
|
|
beq doRTS1 ;cr/space
|
|
cmp #'+' ;ON switch flag?
|
|
bne IsOptnOff ;No
|
|
lda #$80 ;ON
|
|
sta Switch
|
|
bne WhchOptn ;always
|
|
;
|
|
IsOptnOff cmp #'-'
|
|
bne BadOptn
|
|
;
|
|
lda #$00 ;OFF
|
|
sta Switch
|
|
WhchOptn jsr ChrGet ;Get char after switch flag
|
|
beq BadOptn ;It's a cr/space
|
|
ldx #0
|
|
OptnLoop cmp OptionsT,x
|
|
beq GotOptn ;Got a hit
|
|
inx
|
|
cpx #7
|
|
bcc OptnLoop ;Next
|
|
BadOptn jmp OptnErr ;Invalid option/option syntax
|
|
;
|
|
GotOptn lda Switch
|
|
sta OptFlagT,x ;$A2-$A8
|
|
NxtOptn jsr ChrGet ;Get char
|
|
beq doRTS1 ;cr/space
|
|
cmp #',' ;delimiter
|
|
bne NxtOptn
|
|
iny ;Skip comma
|
|
jmp GetOptFlg ;Loop back for another option
|
|
doRTS1 rts
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Parse for the pathnames of the OBJ file and
|
|
; LinkMap txt file. Full and partial pathname
|
|
; are accepted. If there is no operand field
|
|
; following the BIN/REL/SYS directive/cmd then
|
|
; the default filenames are used.
|
|
;
|
|
; Output
|
|
; LinkObjS buf
|
|
;
|
|
GetOutFN jsr SkipSpcs
|
|
CpyLoop3 jsr ChrGot
|
|
beq GotWS ;cr/space
|
|
jsr ChkChar ;Is char valid?
|
|
bne IsCR ;No
|
|
iny
|
|
sta LinkObjS,y
|
|
bne CpyLoop3
|
|
;
|
|
IsCR cmp #CR ;Is it a CR?
|
|
GotWS php ;Save compare status
|
|
cpy #0 ;Is there an operand?
|
|
beq Chk4CR ;No
|
|
sty LinkObjS ;Len byte
|
|
Chk4CR plp
|
|
beq doRTS2 ;Yes, it's a CR, so done
|
|
cmp #',' ;Check for the delimiter
|
|
bne FNF2 ;Not found
|
|
;
|
|
ldx #0
|
|
iny ;Skip the comma
|
|
ChkLoop jsr ChrGot
|
|
beq GotCR ;cr/space
|
|
jsr ChkChar ;Is char valid?
|
|
bne FNF2 ;No, err
|
|
inx
|
|
iny
|
|
sta LinkMapS,x
|
|
bne ChkLoop
|
|
;
|
|
GotCR cpx #0 ;If no user-defined LinkMap
|
|
beq doRTS2 ; file use default
|
|
stx LinkMapS ;Len byte
|
|
doRTS2 rts
|
|
;
|
|
FNF2 lda #$40 ;fileNotFound
|
|
jsr ErrHndlr ;Don't come back
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Check if a char is valid
|
|
; Valid chars are: / . 0-9 A-Z
|
|
; Input
|
|
; (A)=ascii char
|
|
; Output
|
|
; Z=1 if char is valid
|
|
;
|
|
ChkChar cmp #'/'
|
|
beq doRTS3
|
|
cmp #'.'
|
|
beq doRTS3
|
|
jsr IsDecChar ;Is it a decimal digit?
|
|
bcc CharOK ;Yes
|
|
cmp #'A'
|
|
bcc doRTS3
|
|
cmp #'Z'+1
|
|
bcc CharOK
|
|
cmp #'A'
|
|
rts
|
|
;
|
|
CharOK sta Prompt
|
|
cmp Prompt ;Ensure Z=1
|
|
doRTS3 rts
|
|
;=================================================
|
|
; Set PathName buf to OBJECT file
|
|
;
|
|
MovObjFN EQU *
|
|
ldy LinkObjS ;len byte
|
|
MovLoop lda LinkObjS,y
|
|
sta PathNameB,y
|
|
dey
|
|
bpl MovLoop
|
|
rts
|
|
REP 50
|
|
; Set PathName buf to LinkMap text file
|
|
;
|
|
MovMapFN EQU *
|
|
ldy LinkMapS ;Get its len byte
|
|
MovLoop2 lda LinkMapS,y
|
|
sta PathNameB,y
|
|
dey
|
|
bpl MovLoop2
|
|
rts
|
|
REP 50
|
|
; Open for LinkMap text file for writing
|
|
; Input
|
|
; Output
|
|
;
|
|
OpLnkMap EQU *
|
|
jsr MovMapFN ;Set PN to LinkMap's
|
|
jsr PRODOS8 ;DESTROY
|
|
DB $C1
|
|
DW DestryP
|
|
;
|
|
jsr PRODOS8 ;CREATE
|
|
DB $C0
|
|
DW CrLnkMapP
|
|
bne GotErr
|
|
;
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW Open2P
|
|
beq FileOpn
|
|
GotErr jsr ErrHndlr ;Don't come back
|
|
;
|
|
FileOpn lda Open2P+c.outRef
|
|
sta WrMapFP+c.refNum
|
|
lda #0
|
|
sta WrMapFIdx ;# of bytes to write
|
|
sta WrMapFIdx+1 ;HOB=Always 0
|
|
rts
|
|
;=================================================
|
|
; Using info fr the ESD (if any) of the src files,
|
|
; build 3 arrays called ENTRY, EXTRN & SymbolicName
|
|
; tables.
|
|
; EntRecP - Point to an element of the ENTRY table of 24-byte records
|
|
; XtnRecP - Point to an element of the EXTRN table of 8-byte records
|
|
; SymP - Point to an element of the SymbolicName table of 16-byte records
|
|
; ModNbr - src file # assigned during processing
|
|
; CurrORG - starting PC of current src file
|
|
;
|
|
DoPhase1 ldy #$04 ;Building ENTRY/EXTERN tables
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
ldy #$04
|
|
jsr StorMsgY ;Store same msg to LinkMap
|
|
;
|
|
lda #>EntTbl
|
|
sta EntRecP ;ENTRY table @ $4700
|
|
lda #<EntTbl
|
|
sta EntRecP+1
|
|
lda #>XtnTbl ;XTRN table @ $7100
|
|
sta XtnRecP
|
|
lda #<XtnTbl
|
|
sta XtnRecP+1
|
|
lda #>SymTbl ;SymbolicName table @ $9200
|
|
sta SymP
|
|
lda #<SymTbl
|
|
sta SymP+1
|
|
;
|
|
lda #0
|
|
sta ModNbr ;module #
|
|
lda Origin
|
|
sta CurrORG
|
|
lda Origin+1
|
|
sta CurrORG+1
|
|
jmp Phs11
|
|
;
|
|
; Process a src file. The only directive allowed
|
|
; is ALN which instructs the Linker to adjust
|
|
; the PC to the start of next mem page
|
|
;
|
|
Phs1Loop EQU *
|
|
jsr PollKbd
|
|
jsr Read1Cmd
|
|
bne Phs11 ;Not a cr/space => we've a PN
|
|
cmp #CR
|
|
beq GoPhase2 ;Empty line -> no more cmds
|
|
jsr IsALN ;Is it Align directive?
|
|
bcc GotAln ;Yes -> align mem
|
|
jmp DoBreak ;Abort!
|
|
;
|
|
GotAln beq AlignMem ;ALN option
|
|
jmp CmdOrderErr ;No, invalid cmd order
|
|
;
|
|
AlignMem lda CurrORG ;Already @ a mempage bdry?
|
|
beq Phs1Loop ;Yes
|
|
inc CurrORG+1 ;Next mempage
|
|
lda #$00
|
|
sta CurrORG
|
|
beq Phs1Loop ;always
|
|
;
|
|
GoPhase2 jmp DoPhase2
|
|
;
|
|
; The name of a src file is already in CmdLine buffer
|
|
; Open the src file and setup some variables
|
|
; using the info fr the opened src file.
|
|
;
|
|
; CmdLineB - Pathname of src file
|
|
; EntRecP - ptr to a rec of ENTRY table
|
|
; XtnRecP - ptr to a rec of EXTRN table
|
|
; SymP - ptr to a rec of SymbolicName table
|
|
;
|
|
; Origin - ORG of 1st src file (if not) set by an ORG directive
|
|
; CurrORG - Starting PC assigned to curr src file
|
|
; SMSrcFP+c.mark - file posn of source file
|
|
; SrcP - pointer into a chunk of source file
|
|
;
|
|
; Z80 - End of chunk of RLD data read
|
|
; Z82 - Start of RLD data read
|
|
;
|
|
Phs11 jsr DspLineB
|
|
jsr OpenSrc ;Open src file and get info
|
|
bcc Phs12
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
Phs12 lda Origin ;Was it set?
|
|
ora Origin+1
|
|
bne OrgSet ;Yes
|
|
;
|
|
lda SrcORG ;Use the ORG as recorded
|
|
sta Origin ; in the 1st src file
|
|
sta CurrORG ; as our origin & use it as
|
|
lda SrcORG+1 ; the starting PC as well
|
|
sta Origin+1 ;NB. Once set, it will remain unchanged
|
|
sta CurrORG+1 ; throughout linking process
|
|
;
|
|
OrgSet lda #2
|
|
clc
|
|
adc SrcCodeLen ;Len of code image
|
|
sta SMSrcFP+c.mark ;Set file posn to src file's
|
|
lda #0 ; relocation dictionary (RLD)
|
|
adc SrcCodeLen+1
|
|
sta SMSrcFP+c.mark+1; which is just after the code image
|
|
lda OpSrcFP+c.outRef
|
|
sta SMSrcFP+c.refNum
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMSrcFP
|
|
bne GotErr2
|
|
;
|
|
jsr L3348 ;Read max chunk of RLD/ESD
|
|
bcc FinalData ;=> The entire RLD/ESD was read
|
|
cmp #$10 ;Did we encounter an EOF?
|
|
beq MoreData ;No, more data chunks
|
|
GotErr2 jsr ErrHndlr ;(A)=$4C, so let EI take care of it
|
|
;
|
|
; A fixed chunk (of 5K) had been read so there may be more
|
|
; data to be read. There seems to be no provision dealing
|
|
; with files in which the END of RLD is not within
|
|
; the first 5K of RLD/ESD data i.e. the RLD is very big.
|
|
; The code below doesn't seem to be able to handle this
|
|
; situation. Is there a bug here?
|
|
; The code below will never be executed if sizeof RLD+ESD < 5K
|
|
;
|
|
MoreData jsr GetEndRLD ;Scan for end of RLD
|
|
lda SrcP+1 ;Is SrcP still at the BO
|
|
cmp #<SrcDBuf ; the srcfile data buffer?
|
|
bne L2353 ;No
|
|
lda SrcP ;(Should SrcP be compared to $2000?)
|
|
cmp #>SrcDBuf ; which is EO SrcDBuf+1
|
|
bne L2353
|
|
BigESD jmp RldEsdErr ;Src file's ESD too large
|
|
;
|
|
; This code is only executed if the size of the RLD is less
|
|
; than the size of the SrcDBuf located @ $0C00 (which is 5K)
|
|
; SrcP is pointing @ EO RLD
|
|
; The code below is definitely buggy.
|
|
;
|
|
L2353 lda #>SrcDBuf ;Start addr
|
|
clc
|
|
adc RWFileP+c.transCnt;Actual # of bytes read
|
|
sta Z80 ;Point @ EO data chunk + 1
|
|
lda #<SrcDBuf
|
|
adc RWFileP+c.transCnt+1; (or EO file data buf + 1=$2000)
|
|
sta Z80+1 ;END addr
|
|
;
|
|
lda #>SrcDBuf
|
|
sta Z82 ;DEST addr
|
|
lda #<SrcDBuf
|
|
sta Z82+1
|
|
;
|
|
; Calc the size of ESD data in FileData buf
|
|
;
|
|
lda Z80
|
|
sec
|
|
sbc SrcP ;Pointing @ EO RLD
|
|
sta RWFileP+c.transCnt;=len of ESD already in buf + 1 (EO RLD marker)
|
|
lda Z80+1 ;(should SrcP be incr 1 more?)
|
|
sbc SrcP+1
|
|
sta RWFileP+c.transCnt;Bug! Should be sta RWFileP+c.transCnt+1
|
|
;
|
|
; Move ESD block forward in filedata buf (incl EO RLD marker)
|
|
;
|
|
jsr MovData
|
|
lda #>SrcDBuf ;Prepare to append more ESD data
|
|
clc
|
|
adc RWFileP+c.transCnt; fr src file by reading 'em
|
|
sta RWFileP+c.dataBuf; into this starting location
|
|
lda #<SrcDBuf
|
|
adc RWFileP+c.transCnt;Bug! Should be adc RWFileP+c.transCnt+1
|
|
sta RWFileP+c.dataBuf+1
|
|
;
|
|
; Calculate # of bytes to be read in
|
|
; order to fill the rest of FileData
|
|
; buf with more ESD records
|
|
;
|
|
lda #>FileDBSiz
|
|
sec
|
|
sbc RWFileP+c.transCnt
|
|
sta RWFileP+c.reqCnt;=$1400-(# of bytes of
|
|
lda #<FileDBSiz
|
|
sbc RWFileP+c.transCnt+1; data currently in mem)
|
|
sta RWFileP+c.reqCnt+1
|
|
jsr ReadCode ;Attempt to read another chunk
|
|
bcc FinalData ;Last chunk so that's ok
|
|
cmp #$10 ;More to go?
|
|
beq BigESD ;Yes, ESD too large
|
|
bne GotErr2 ;Always-error
|
|
;
|
|
; Last chunk of RLD/ESD data had been read
|
|
; The code below seems ok
|
|
;
|
|
FinalData jsr GetEndRLD ;Point to end of RLD
|
|
lda OpSrcFP+c.outRef;Close src file
|
|
jsr ClsFile
|
|
inc SrcP ;Skip the EO RLD marker which
|
|
bne Bump1 ; is a $00 to point @ appended ESD
|
|
inc SrcP+1
|
|
;
|
|
Bump1 ldy ModNbr ;Current file module #
|
|
lda XtnRecP ;Ptr to 1st EXTRN record
|
|
sta SrcModTLo,y ;for this module
|
|
lda XtnRecP+1
|
|
sta SrcModTHi,y
|
|
;
|
|
; Add records to the SymbolicName, ENTRY/EXTRN
|
|
; tables using information from ESD
|
|
;
|
|
ScanESD jsr PollKbd
|
|
;
|
|
ldy #15 ;FOR Y= 15 to 1
|
|
lda #SPACE
|
|
BlnkLoop sta (EntRecP),y
|
|
sta (SymP),y
|
|
dey
|
|
bne BlnkLoop
|
|
;
|
|
; Y=0 on fall thru
|
|
; NB: All chars of SymbolicName record will have their msb off
|
|
; The SymbolicName record is a p-string (may be a
|
|
; truncation of the original symbolic name in ESD)
|
|
;
|
|
MakeRecs lda (SrcP),y ;Get 1st char of symbolicname
|
|
bne MkRecs1
|
|
jmp DoneESD ;EO ESD => Done processing this file
|
|
MkRecs1 php ;save msb
|
|
and #$7F
|
|
iny
|
|
sta (EntRecP),y ;Copy char to both ENTRY and
|
|
sta (SymP),y ; SymbolicName records
|
|
plp ;Is msb off?
|
|
bpl CkSymTyp ;Yes, last char of symbolic name
|
|
cpy #15 ;max len of linker symbol
|
|
bcc MakeRecs ;Next char
|
|
;
|
|
; Only first 15 chars are copied. We skip the rest of chars.
|
|
; However, we still need to locate the eo the symbolicname
|
|
; in order to get @ the symbol-type flag etc.
|
|
;
|
|
SkipLoop lda (SrcP),y ;Get symbolicname's char
|
|
iny
|
|
tax ;Is this the last char?
|
|
bmi SkipLoop ;No
|
|
;
|
|
CkSymTyp tya
|
|
ldy #0
|
|
sta (EntRecP),y ;Set the len byte
|
|
sta (SymP),y
|
|
tay
|
|
lda (SrcP),y
|
|
sta ESDRec ;Symbol-type flag
|
|
iny
|
|
lda (SrcP),y ;If EXTRN, this is the symbol #
|
|
sta ESDRec+1 ; referred to by an RLD entry
|
|
iny
|
|
lda (SrcP),y ;Hibyte of addr if
|
|
sta ESDRec+2 ; symbol-type is ENTRY
|
|
;
|
|
lda ESDRec ;Chk symbol-type
|
|
and #%00001000 ;Is it EXTRN symbol-type?
|
|
bne DoEntry ;No, it's ENTRY symbol-type
|
|
;
|
|
ldx #XtnRecP
|
|
bit Z9E ;Include code fr this file?
|
|
bpl DoXtrn ;Yes
|
|
jmp NxtEntryZ ;No recs will be added to the 3 tables
|
|
;
|
|
; Process an EXTRN symbol-type rec in ESD of a src file
|
|
;
|
|
DoXtrn lda #0 ;Zero the curr ENTRY slot
|
|
ldy #24
|
|
ZeroLup2 sta (EntRecP),y ; which was partially
|
|
dey ; filled with the symbolicname
|
|
bpl ZeroLup2
|
|
;
|
|
; Create a EXTRN record in table @ $7100
|
|
; Each record is 8 bytes
|
|
; Initial Layout of each record is as follows:
|
|
; offset Description
|
|
; 0 DW ptr to a record in SymbolicName table ($9200)
|
|
; ptr to another EXTRN rec if the SymbolicName
|
|
; matched with that in one of the ENTRY recs
|
|
; 2 DW Ptr to an ENTRY record; NIL initially
|
|
; 4 DB file # of src file (also called module #)
|
|
; 5 DB FlagByte
|
|
; 6 DB symbol # referred to by an RLD record
|
|
; 7 DB 0
|
|
;
|
|
ldy #0
|
|
lda SymP
|
|
sta (XtnRecP),y ;Ptr to the corr record of
|
|
lda SymP+1 ; symbolicname table @ $9200
|
|
iny
|
|
sta (XtnRecP),y
|
|
iny ;=2
|
|
lda #$00
|
|
sta (XtnRecP),y ;Set to NIL
|
|
iny
|
|
sta (XtnRecP),y
|
|
iny ;=4
|
|
lda ModNbr ;file # of the src module
|
|
sta (XtnRecP),y
|
|
lda ESDRec ;symbol-type flag byte
|
|
ora #%11000000 ;Set undefined, unref'd bits
|
|
iny ;=5
|
|
sta (XtnRecP),y
|
|
iny ;=6
|
|
lda ESDRec+1
|
|
sta (XtnRecP),y ;Symbol # referred to by an RLD record
|
|
iny ;=7
|
|
lda #$00
|
|
sta (XtnRecP),y ;hibyte=0 - Not used
|
|
jsr ScanEntTbl ;Is this symbol already in ENTRY table?
|
|
bne ChkSymTbl ;No
|
|
jsr L2668 ;Yes, add this EXTRN rec to singly-link list
|
|
jmp DoneXtrn ;Add this EXTRN rec to its table
|
|
;
|
|
ChkSymTbl jsr L2629 ;Is symbol already in SymbolicName table?
|
|
bne AddSymName ;No => add the SymbolicName rec to its table
|
|
;
|
|
ldy #0
|
|
lda Z88 ;Set this link to point
|
|
sta (XtnRecP),y ; to SymbolicName record
|
|
iny
|
|
lda Z88+1 ; already in table
|
|
sta (XtnRecP),y
|
|
jmp DoneXtrn ;=> Don't add new SymbolicName rec to its table
|
|
;
|
|
; We are adding a new SymbolicName rec to the its table
|
|
; This is done by incrementing SymP by the appropiate
|
|
; # of bytes i.e. SymP++ (in C Syntax)
|
|
;
|
|
AddSymName jsr IncrSymP ;Adv to next empty slot of SymbolicName table
|
|
lda SymP+1 ;Is SymbolicName table full?
|
|
cmp #<XA8E0 ;(Linker's HiMem)
|
|
bcc DoneXtrn
|
|
bne SymTblFull
|
|
lda SymP
|
|
cmp #>XA8E0
|
|
bcc DoneXtrn
|
|
SymTblFull jmp TableFull ;Yes
|
|
;
|
|
; Do a XtnP++ to point @ the next empty slot in EXTRN table
|
|
;
|
|
DoneXtrn jsr IncrXtnP
|
|
jmp NxtEntryZ ;Prepare to process next rec in appended ESD
|
|
;
|
|
; Process an ENTRY symbol-type record in ESD of src file
|
|
; The 1st field is already done
|
|
; Layout of 24-byte records in ENTRY table @ $4700
|
|
; offset
|
|
; 0 STR up to 16 chars including len byte
|
|
; 16 DB file # of src file (start fr 0)
|
|
; 17 DB symbol-type
|
|
; 18 DW relocated addr
|
|
; 20 DW 0 (Ptr to EXTRN record) - first/head
|
|
; 22 DW 0 (Ptr to EXTRN record) - last/tail
|
|
;
|
|
DoEntry bit Z9E ;Include code fr this file?
|
|
bmi DoEntry1 ;No
|
|
;
|
|
lda ESDRec+2 ;Hibyte of addr as recorded in src file
|
|
cmp SrcORG+1 ;Origin as recorded in src file
|
|
bcc DoEntry1
|
|
lda L3806+1 ;addr+1 of last byte of code image
|
|
sec
|
|
sbc ESDRec+2 ;Hibyte of addr
|
|
bmi DoEntry1 ;Is addr to be relocated btwn
|
|
bne CalcAddr
|
|
lda ESDRec+1 ; addrs of 1st & last byte of image?
|
|
cmp L3806
|
|
bcs DoEntry1 ;Out of range
|
|
;
|
|
; Calc relocated addr of the instruction
|
|
; First do an equivalent to a subtraction
|
|
; to obtain the inst' offset wrt
|
|
; the src file's origin
|
|
;
|
|
CalcAddr lda ESDRec+1
|
|
clc
|
|
adc NegSrcOrg ;2's complement of
|
|
sta ESDRec+1
|
|
lda ESDRec+2
|
|
adc NegSrcOrg+1 ; src file's Origin
|
|
sta ESDRec+2 ;Got the offset
|
|
;
|
|
lda ESDRec+1 ;Calc the relocated addr
|
|
clc
|
|
adc CurrORG
|
|
sta ESDRec+1
|
|
lda ESDRec+2
|
|
adc CurrORG+1
|
|
sta ESDRec+2
|
|
;
|
|
DoEntry1 ldy #16
|
|
lda ModNbr ;src file #
|
|
sta (EntRecP),y
|
|
iny
|
|
lda ESDRec ;symbol type
|
|
ora #%01000000 ;Set not-referenced bit
|
|
sta (EntRecP),y
|
|
iny
|
|
lda ESDRec+1 ;Relocated addr lo
|
|
sta (EntRecP),y
|
|
iny
|
|
lda ESDRec+2 ;Relocated addr hi
|
|
sta (EntRecP),y
|
|
;
|
|
lda #0 ;FOR Y=20 TO 24
|
|
ZeroLup1 iny
|
|
cpy #24
|
|
sta (EntRecP),y ;Set both links to NIL
|
|
bcc ZeroLup1
|
|
;
|
|
ldy #0
|
|
tya ;Zero len byte so that search will
|
|
sta (EntRecP),y ;not include this ENTRY rec
|
|
jsr ScanEntTbl ;Is this symbol already in ENTRY table?
|
|
php ;Save for later
|
|
lda (SymP),y ;Get a copy of len byte
|
|
sta (EntRecP),y ; & restore it
|
|
plp
|
|
bne NxtEntry ;Not in ENTRY table
|
|
jsr StorDupSym ;Record duplicate symbol
|
|
;
|
|
; Do a EntP++ to point @ the next empty slot in ENTRY table
|
|
;
|
|
NxtEntry jsr IncrEntP
|
|
;
|
|
NxtEntryZ jsr NxtESDRec ;Point @ next rec in appended ESD
|
|
lda $01,x ;(X)=$8A,$8C => (A)=$60,$00 (hi-byte of table?)
|
|
cmp GoShowMsgZ,x ;Locations $360D+$8A=$3697 or $3699
|
|
beq TableFull ;A bug here & in the table
|
|
jmp ScanESD ;Scan next ESD record
|
|
;
|
|
TableFull ldy #$0A ;symtbl full
|
|
jsr GoShowMsg
|
|
;
|
|
; We have finishing processing the ESD of the curr file
|
|
; Do some housekeeping b4 processing the next file
|
|
; NB. If a src PN is preceded by an asterik,
|
|
; its SymbolicNames will be referenced but no
|
|
; object code will be incorporated into the
|
|
; final OBJ file.
|
|
;
|
|
DoneESD EQU *
|
|
bit Z9E ;Was src PN preceded by a ;?
|
|
bmi NxtSrc ;Yes => its code will not be incorporated in OBJ file
|
|
;
|
|
lda SrcCodeLen
|
|
clc
|
|
adc CurrORG ;Starting PC for
|
|
sta CurrORG ; the next src file
|
|
lda SrcCodeLen+1
|
|
adc CurrORG+1
|
|
sta CurrORG+1
|
|
;
|
|
NxtSrc inc ModNbr
|
|
lda ModNbr
|
|
cmp #50 ;max # of src files
|
|
bcs TooMany
|
|
jmp Phs1Loop ;Process next src file
|
|
;
|
|
TooMany ldy #$0B ;Too many src files
|
|
jsr GoShowMsg
|
|
;=================================================
|
|
; Get the end of RLD
|
|
; Each record in the Relocation Dictionary is 4 bytes long
|
|
; Input
|
|
; SrcP - ptr to beginning of RLD chunk
|
|
; Output
|
|
; (Y)=0
|
|
; SrcP - End of RLD if found
|
|
; Z=1
|
|
; X - not used
|
|
;
|
|
; Possible bug here. The code should check that SrcP
|
|
; should not exceed upper limit of SrcDBuf ($2000)
|
|
; unless it's assumed that RLD is always < 5K. For
|
|
; this case, since each RLD record is 4 bytes, the max #
|
|
; of RLD records in a src file = (5x1024)/4 -1 = 1279
|
|
; This rtn should be re-written to handle files with huge RLDs
|
|
; When the EO RLD is not found, it should check that
|
|
; SrcP == (SrcDBuf+FileDBSiz) by returning a flag to the caller
|
|
;
|
|
RLDEntSiz EQU 4 ;size of an RLD entry
|
|
GetEndRLD EQU *
|
|
ldy #0
|
|
ScanLoop lda (SrcP),y ;Get RLD-flag byte
|
|
and #$01 ;Is it EO RLD?
|
|
beq doRTS4 ;Yes
|
|
lda #RLDEntSiz ;Point @ next RLD record
|
|
clc
|
|
adc SrcP
|
|
sta SrcP
|
|
lda #0
|
|
adc SrcP+1
|
|
sta SrcP+1
|
|
jmp ScanLoop ;Continue scanning
|
|
doRTS4 rts
|
|
;=================================================
|
|
; Phase 2 of the Linking process
|
|
; This rtn will attempt to resolve EXTRN's by checking
|
|
; if its symbolic name is in the ENTRY table
|
|
; NB. After phase 1, some recs in EXTRN table are
|
|
; already in a singly-linked list. Their SymbolicName
|
|
; fields would have been changed to point to another
|
|
; EXTRN rec or is set to NIL if they happen to be
|
|
; the last node of the list.
|
|
; The msb of their flagbyte would be 0 (symbol is defined)
|
|
;
|
|
DoPhase2 EQU *
|
|
lda #0
|
|
ldy #0
|
|
sta (EntRecP),y ;Zero the len byte of ENTRY record
|
|
ldy #5 ; and flag byte of EXTRN record
|
|
sta (XtnRecP),y ;These recs are empty slots
|
|
ldy #$05 ;Resolving REF/EXTRN...
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
ldy #$05
|
|
jsr StorMsgY ;Store same msg
|
|
;
|
|
lda #>XtnTbl
|
|
sta XtnRecP ;Point to start
|
|
lda #<XtnTbl
|
|
sta XtnRecP+1 ; of EXTRN table
|
|
lda #0
|
|
sta XtnNbr ;EXTRN cnt (or EXTRN #)
|
|
;
|
|
; Phase2 main loop
|
|
;
|
|
Phs2Loop jsr PollKbd
|
|
ldy #5
|
|
lda (XtnRecP),y ;Get flag byte
|
|
beq DonePhs2 ;Done w/all recs in EXTRN table
|
|
and #%10000000 ;Is symbol undefined?
|
|
beq L25AD ;No, skip this EXTRN rec
|
|
;
|
|
ldy #0
|
|
lda (XtnRecP),y ;Get ptr to its symbolicname
|
|
sta SymP
|
|
iny
|
|
lda (XtnRecP),y
|
|
sta SymP+1
|
|
jsr ScanEntTbl ;Is symbol already in ENTRY table?
|
|
bne L2598 ;No
|
|
jsr L2668 ;Add to singly-linked nodes of EXTRN recs
|
|
jmp L25AD ;Prepare to process next record
|
|
;
|
|
; The EXTRN symbol was not found in ENTRY table
|
|
;
|
|
L2598 ldy #5
|
|
lda (XtnRecP),y ;Get flag byte fr EXTRN record
|
|
ora #%00000010 ;No such label
|
|
sta (XtnRecP),y
|
|
bit FTypeF ;Is OBJECT file of type REL?
|
|
bpl L25AA ;No
|
|
;
|
|
jsr L25C6 ;Modify SymbolicName & update EXTRN recs
|
|
jmp L25AD
|
|
;
|
|
L25AA jsr L2856 ;Report undefined symbol
|
|
;
|
|
L25AD jsr IncrXtnP ;Next EXTRN record
|
|
jmp Phs2Loop ;Loop back
|
|
;
|
|
; We have finished scanning through all EXTRN recs
|
|
;
|
|
DonePhs2 bit FTypeF ;Is OBJECT file of type REL?
|
|
bpl GoPhase3 ;No
|
|
;
|
|
; Write a tempESD file for unreferenced ENTRY
|
|
; & unresolved EXTRN recs
|
|
;
|
|
jsr L26DE ;Open tempESD file for writing
|
|
jsr L2763 ;Use info fr unresolved EXTRNs &
|
|
jsr L2719 ; unreferenced ENTRYs to write file
|
|
jsr L27AC ;Mark EO ESD and close tempESD file
|
|
;
|
|
GoPhase3 jmp DoPhase3
|
|
REP 50
|
|
;
|
|
; An EXTRN Symbol cannot be found in ENTRY table
|
|
; Modify its EXTRN rec & related SymbolicName rec
|
|
; Input
|
|
; XtnRecP - Ptr to a record of EXTRN table
|
|
; XtnNbr - EXTRN count
|
|
; Output
|
|
; SymP - Ptr to a record of SymbolicName table
|
|
; (Y)=0
|
|
; The structure of SymbolicName table will be modified.
|
|
; Only 2 bytes are used viz.
|
|
; offset 0 - len byte -> EXTRN #
|
|
; offset 1 - 1st char whose msb is off -> msb on
|
|
;
|
|
L25C6 EQU *
|
|
ldy #0
|
|
lda (XtnRecP),y ;Get ptr to the SymbolicName rec
|
|
sta SymP
|
|
iny
|
|
lda (XtnRecP),y
|
|
sta SymP+1
|
|
ldy #1 ;Skip its len byte
|
|
lda (SymP),y ;Is msb of 1st char off?
|
|
bpl L25DD ;Yes
|
|
dey
|
|
lda (SymP),y ;No, get EXTRN #
|
|
jmp L25EA
|
|
;
|
|
L25DD inc XtnNbr ;EXTRN #
|
|
bne L25E4
|
|
jmp ExtrnErr ;>255 EXTRN's in REL output ESD
|
|
;
|
|
L25E4 ora #$80 ;Set 1st char's msb to 1
|
|
sta (SymP),y
|
|
lda XtnNbr ;EXTRN #
|
|
L25EA ldy #7
|
|
sta (XtnRecP),y
|
|
ldy #0
|
|
sta (SymP),y ;Overwrite len byte w/EXTRN #
|
|
rts
|
|
REP 50
|
|
;
|
|
; Check if a SymbolicName is present in
|
|
; one of the recs of ENTRY table ($4700)
|
|
; Input
|
|
; SymP - ptr to a SymbolicName rec
|
|
;
|
|
; Output
|
|
; Z=1 - Yes
|
|
; Z88 - Ptr to the ENTRY record
|
|
; (Y)=0
|
|
; Uses a brute force method to search for the key
|
|
; The search is conducted record by record until
|
|
; no more records are left to be processed
|
|
;
|
|
ScanEntTbl EQU *
|
|
lda #>EntTbl ;Start search fr BO ENTRY table
|
|
sta Z88
|
|
lda #<EntTbl
|
|
sta Z88+1
|
|
;
|
|
ScanEntLup ldy #0
|
|
lda (SymP),y ;Get len byte of symbolicname
|
|
cmp (Z88),y
|
|
bne NoHit ;Definitely no match
|
|
cmp #15+1
|
|
bcc DoCmp
|
|
lda #15 ;At most 15 chars to be compared
|
|
DoCmp tax
|
|
CmpLoop iny
|
|
lda (SymP),y ;Compare symbolic name
|
|
cmp (Z88),y
|
|
bne NoHit ;No match
|
|
dex
|
|
bne CmpLoop
|
|
;
|
|
ldy #0 ;Z=1 ==> hit
|
|
rts
|
|
;
|
|
NoHit lda #24 ;Pointer size = 24 bytes
|
|
ldx #Z88 ;Ptr to be adjusted
|
|
jsr IncRecPZ ;Adv to next ENTRY record (Z88++)
|
|
ldy #0
|
|
lda (Z88),y ;Get symbol's len byte fr ENTRY rec
|
|
bne ScanEntLup ;No EOT, so try again
|
|
ldy #0
|
|
lda #1 ;Z=0 ==> Not found
|
|
rts
|
|
;=================================================
|
|
; Search if EXTRN symbol's name is in SymbolicName table ($9200)
|
|
; Input
|
|
; Output
|
|
; On return
|
|
; (Y)=0
|
|
; Z=1 match
|
|
; (Z88) - ptr to symbolicname record
|
|
;
|
|
L2629 EQU *
|
|
lda #>SymTbl ;SymbolicName table
|
|
sta Z88
|
|
lda #<SymTbl
|
|
sta Z88+1
|
|
jmp L2657
|
|
;
|
|
L2634 ldy #0
|
|
lda (SymP),y ;Get len byte
|
|
cmp (Z88),y
|
|
bne L2650
|
|
cmp #16
|
|
bcc L2642
|
|
;
|
|
lda #15
|
|
L2642 tax
|
|
L2643 iny
|
|
lda (SymP),y
|
|
cmp (Z88),y
|
|
bne L2650 ;No match
|
|
dex
|
|
bne L2643
|
|
;
|
|
ldy #0 ;Z=1
|
|
rts
|
|
;
|
|
L2650 lda #16 ;Pointer size
|
|
ldx #Z88
|
|
jsr IncRecPZ ;Adv to next SymbolicName record
|
|
;
|
|
L2657 lda Z88 ;Is EOT?
|
|
cmp SymP ;NB. This rec has yet to be "added"
|
|
bne L2634
|
|
lda Z88+1 ; to the SymbolicName table
|
|
cmp SymP+1
|
|
bne L2634 ;No, keep searching
|
|
;
|
|
ldy #0
|
|
lda #1 ;Z=0
|
|
rts
|
|
;=================================================
|
|
; Modify the ENTRY and EXTRN records by setting up
|
|
; the necessary links.
|
|
; If more than one EXTRN records refer to the ENTRY
|
|
; rec, then we setup a singly-linked list to link
|
|
; all the EXTRN recs. The field "first" will
|
|
; point to the first EXTRN rec & the field "last"
|
|
; point to the last EXTRN rec in the singly-linked list
|
|
;
|
|
; Input
|
|
; (XtnRecP) - Ptr to a EXTRN record
|
|
; (Z88) - Ptr to an ENTRY record
|
|
; Output
|
|
;
|
|
; Prepare to add a new node (in the form of an EXTRN rec)
|
|
; to the singly-linked list. The link to a SymbolicName
|
|
; rec in the EXTRN rec is now called "next" (variant rec
|
|
; in Pascal, union in C)
|
|
;
|
|
L2668 EQU *
|
|
ldy #0
|
|
lda #$00
|
|
sta (XtnRecP),y ;Set "next" link to NIL
|
|
iny
|
|
sta (XtnRecP),y
|
|
iny ;2
|
|
lda Z88 ;Ptr to ENTRY record whose symbolicname
|
|
sta (XtnRecP),y ; matches that of the XtnRecP
|
|
iny ;3
|
|
lda Z88+1
|
|
sta (XtnRecP),y
|
|
;
|
|
ldy #5
|
|
lda (XtnRecP),y ;Get symbol-type flag byte
|
|
and #$7F ;Now symbol is defined
|
|
sta (XtnRecP),y
|
|
and #%00000001 ;Has the meaning of bit0 changed?
|
|
ldy #17
|
|
eor (Z88),y ;Symbol-type flag byte of ENTRY rec
|
|
and #%00000001
|
|
beq L2690 ;Yes
|
|
jsr L287B ;size mismatch
|
|
;
|
|
L2690 ldy #17
|
|
lda (Z88),y
|
|
and #%01000000 ;unreferenced?
|
|
beq L26B2 ;No => already referenced
|
|
eor (Z88),y ;Clear unreferenced bit
|
|
sta (Z88),y ; but retain the other bits
|
|
;
|
|
; The ENTRY rec is referenced the 1st time
|
|
; so create a singly-linked list by
|
|
; setting the first and last link to point
|
|
; to the same EXTRN rec
|
|
;
|
|
ldy #20 ;first link
|
|
lda XtnRecP
|
|
sta (Z88),y ;Ptr to EXTRN record
|
|
iny
|
|
lda XtnRecP+1
|
|
sta (Z88),y ;Store in ENTRY rec
|
|
;
|
|
iny ;last link
|
|
lda XtnRecP ;Ptr to same EXTRN record
|
|
sta (Z88),y
|
|
iny ;23
|
|
lda XtnRecP+1
|
|
sta (Z88),y
|
|
rts
|
|
;
|
|
; The ENTRY symbol has been referenced more than once
|
|
; We add the new node to the end of the singly-linked list
|
|
;
|
|
L26B2 ldy #22
|
|
lda (Z88),y ;Get ptr to "last" EXTRN record
|
|
sta Z82 ;Save it for later (prev)
|
|
lda XtnRecP
|
|
sta (Z88),y ;Set the "last" link to point
|
|
iny ;23
|
|
lda (Z88),y ; to this EXTRN record
|
|
sta Z82+1
|
|
lda XtnRecP+1 ; which now the last node
|
|
sta (Z88),y ;in the singly-linked list
|
|
;
|
|
ldy #0
|
|
lda XtnRecP ;(Z82) - previously the "last" EXTRN record
|
|
sta (Z82),y ;Replace its "next" link (which was NIL)
|
|
iny
|
|
lda XtnRecP+1 ; with ptr to this EXTRN record
|
|
sta (Z82),y
|
|
rts
|
|
REP 50
|
|
;
|
|
; Copy to pathame buf
|
|
;
|
|
L26D1 ldy TempESD ;len byte
|
|
L26D4 lda TempESD,y
|
|
sta PathNameB,y
|
|
dey
|
|
bpl L26D4
|
|
rts
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Open a temporary binary ESD file for output
|
|
; This rtn will be called if there are unresolved
|
|
; EXTRN symbols
|
|
;
|
|
; Output
|
|
; (Z86) - ptr to tmpESD data buffer
|
|
; Write1P+c.refNum - EXTRN # used to write tempESD file
|
|
;
|
|
L26DE EQU *
|
|
jsr L26D1 ;Set PN to "EDASM.TEMPESD"
|
|
jsr PRODOS8 ;DESTROY
|
|
DB $C1
|
|
DW DestryP
|
|
;
|
|
lda #0
|
|
sta CreateP+c.auxId ;auxtype
|
|
sta CreateP+c.auxId+1
|
|
lda #BINtype
|
|
sta CreateP+c.fileId
|
|
jsr PRODOS8 ;CREATE
|
|
DB $C0
|
|
DW CreateP
|
|
beq L26FF
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L26FF jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW Open3P
|
|
beq L270A
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L270A lda Open3P+c.outRef
|
|
sta Write1P+c.refNum;write RN for tempESD file
|
|
L2710 lda #>X9100 ;Reset to BO data buf
|
|
sta Z86 ; b4 next ESD rec is created
|
|
lda #<X9100
|
|
sta Z86+1
|
|
rts
|
|
REP 50
|
|
;
|
|
; Scan through the ENTRY table for recs whose
|
|
; SymboliName remained unreferenced. Output info
|
|
; to tempESD file
|
|
; Input
|
|
; Output
|
|
;
|
|
L2719 EQU *
|
|
lda #>EntTbl
|
|
sta Z8E ;Point @ BO ENTRY table
|
|
lda #<EntTbl
|
|
sta Z8E+1 ;=> re-cycled zp loc
|
|
;
|
|
L2721 jsr PollKbd
|
|
ldy #17
|
|
lda (Z8E),y ;Get ENTRY record's flag byte
|
|
bit ERefF ;Include ENTRY records in tempESD file?
|
|
bmi L2733 ;Yes
|
|
and #$40 ;Is its SymbolicName still unreferenced?
|
|
bne L2733 ;Yes
|
|
jmp L2755
|
|
;
|
|
L2733 jsr L27DE ;Copy symbolicname to tmpESD area
|
|
tya ;Save len of symbolicname name
|
|
pha
|
|
ldy #17
|
|
lda (Z8E),y ;Get ENTRY record's flag byte again
|
|
and #%00111111 ;Clear undefined/unreferenced bits
|
|
sta ESDRec
|
|
iny
|
|
lda (Z8E),y
|
|
sta ESDRec+1 ;Relocated addr
|
|
iny
|
|
lda (Z8E),y
|
|
sta ESDRec+2
|
|
pla
|
|
tay ;Restore Y
|
|
jsr L2818 ;Add ENTRY data to tempESD data buf
|
|
jsr L27C1 ;Write out to tempESD file
|
|
;
|
|
L2755 lda #24 ;Pointer size
|
|
ldx #Z8E
|
|
jsr IncRecPZ ;Next ENTRY record
|
|
ldy #0
|
|
lda (Z8E),y ;Is EOT?
|
|
bne L2721 ;No
|
|
rts
|
|
REP 50
|
|
;
|
|
; Scan through the EXTRN table for recs whose
|
|
; SymboliName remained undefined. Output info
|
|
; to tempESD file
|
|
; Input
|
|
; Output
|
|
;
|
|
L2763 EQU *
|
|
lda #>XtnTbl
|
|
sta XtnRecP
|
|
lda #<XtnTbl
|
|
sta XtnRecP+1
|
|
;
|
|
L276B jsr PollKbd
|
|
ldy #5
|
|
lda (XtnRecP),y ;flag byte
|
|
beq L27AB
|
|
and #$80 ;Undefined?
|
|
beq L27A5 ;No
|
|
;
|
|
ldy #0
|
|
lda (XtnRecP),y ;Ptr to symbolicname
|
|
sta SymP
|
|
iny
|
|
lda (XtnRecP),y
|
|
sta SymP+1
|
|
ldy #1 ;Unnecessary instruction
|
|
lda (SymP),y ;Get its 1st char
|
|
bpl L27A5
|
|
and #$7F
|
|
sta (SymP),y ;reset its msb
|
|
;
|
|
lda #SPACE
|
|
L278F iny
|
|
cmp (SymP),y ;Look for 1st trailing blank
|
|
beq L2799 ;Got it
|
|
cpy #15
|
|
bcc L278F
|
|
;
|
|
iny ;No trailing blanks
|
|
L2799 dey
|
|
tya ;len of symbolicname
|
|
ldy #0
|
|
sta (SymP),y ;Overwrite the EXTRN # with len byte
|
|
jsr L27FC ;Create a ESD rec (variable in size)
|
|
jsr L27C1 ;Write ESD data to file
|
|
L27A5 jsr IncrXtnP ;Next EXTRN record
|
|
jmp L276B
|
|
L27AB rts
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Input
|
|
; (Z86) - ptr to tmpESD buffer
|
|
; Output
|
|
;
|
|
L27AC EQU *
|
|
lda #$00 ;Marks eo ESD
|
|
tay
|
|
sta (Z86),y
|
|
inc Z86
|
|
bne L27B7
|
|
inc Z86+1
|
|
L27B7 jsr L27C1 ;Flush the tempESD file
|
|
lda Write1P+c.refNum;Close tempESD file
|
|
jsr ClsFile
|
|
rts
|
|
;=================================================
|
|
; Write out data to tempESD binary file
|
|
; Input
|
|
; (Z86)-ptr to record in tempESD table
|
|
; Output
|
|
;
|
|
L27C1 EQU *
|
|
lda Z86
|
|
sec
|
|
sbc #>X9100 ;Start of buffer
|
|
sta Write1P+c.reqCnt;writelen
|
|
lda Z86+1
|
|
sbc #<X9100
|
|
sta Write1P+c.reqCnt+1
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write1P
|
|
beq L27DB
|
|
jsr ErrHndlr ;Don't come back
|
|
L27DB jmp L2710
|
|
REP 50
|
|
;
|
|
; Copy symbolicname to tmpESD data buffer
|
|
; Input
|
|
; (SymP) - ptr to symbolicname record
|
|
; (Z86) - ptr to tempESD buffer ($9100)
|
|
; Output
|
|
; (Y) - len of symbolicname
|
|
;
|
|
L27DE EQU *
|
|
ldy #0
|
|
lda (SymP),y ;Get len byte of symbolicname
|
|
cmp #16
|
|
bcc L27E8
|
|
;
|
|
; Transfer a p-string to the temp ESD data buf
|
|
; The chars of the resulting string will
|
|
; have msbs on except the last one
|
|
;
|
|
lda #15
|
|
L27E8 tax ;Make into a counter
|
|
L27E9 iny
|
|
lda (SymP),y ;Get char
|
|
ora #$80 ;Set msb on
|
|
dey
|
|
sta (Z86),y
|
|
iny
|
|
dex
|
|
bne L27E9
|
|
;
|
|
dey
|
|
and #$7F
|
|
sta (Z86),y ;msb of last char is off
|
|
iny ;len of symbolicname
|
|
rts
|
|
REP 50
|
|
;
|
|
; Make a ESD record for output (of unresolved EXTRNS)
|
|
; Input
|
|
; XtnRecP - ptr to record in EXTRN table
|
|
; Z86 - ptr to record in tempESD table
|
|
; Output
|
|
;
|
|
L27FC EQU *
|
|
jsr L27DE ;Copy symbolicname
|
|
tya ;len of symbolicname
|
|
pha
|
|
ldy #5
|
|
lda (XtnRecP),y
|
|
and #%00111101
|
|
sta ESDRec ;flag byte
|
|
ldy #7
|
|
lda (XtnRecP),y ;EXTRN #
|
|
sta ESDRec+1
|
|
lda #0
|
|
sta ESDRec+2 ;Not used
|
|
pla
|
|
tay
|
|
;
|
|
; Common code for appending an ESD rec using
|
|
; info fr a rec of EXTRN/ENTRY table
|
|
; (Y) = len of symbolicname
|
|
;
|
|
L2818 EQU *
|
|
lda ESDRec
|
|
sta (Z86),y
|
|
iny
|
|
lda ESDRec+1
|
|
sta (Z86),y
|
|
iny
|
|
lda ESDRec+2
|
|
sta (Z86),y
|
|
iny
|
|
tya ;total size of ESD rec
|
|
ldx #Z86
|
|
jsr IncRecPZ ;Adv the ptr
|
|
rts
|
|
REP 50
|
|
; Input
|
|
; Output
|
|
; Store duplicate ENTRY symbol associated messages
|
|
;
|
|
StorDupSym jsr StorERR
|
|
ldy #$12 ;dup ENTRY symbol
|
|
jsr StorMsg
|
|
jsr StorName
|
|
ldy #$13 ;of module #
|
|
jsr StorMsg
|
|
jsr StorRFNbr
|
|
ldy #$14 ;in module #
|
|
jsr StorMsg
|
|
ldy #16
|
|
lda (EntRecP),y ;REL file #
|
|
ldy #0 ;zero ten's digit
|
|
jsr L3079 ;Store 2-byte ASC char in LinkMap
|
|
jsr StorCR
|
|
rts
|
|
REP 50
|
|
; Input
|
|
; Output
|
|
; Store undefined EXTERN symbol associated messages
|
|
;
|
|
L2856 jsr StorERR
|
|
ldy #$15 ;undef EXTRN symbol
|
|
jsr StorMsg
|
|
lda SymP ;ptr to symbolicname
|
|
sta Z88
|
|
lda SymP+1
|
|
sta Z88+1
|
|
jsr StorName ;Store symbolic name
|
|
;
|
|
ldy #$14 ;in mod #
|
|
jsr StorMsg
|
|
ldy #4
|
|
lda (XtnRecP),y ;Get src file #
|
|
ldy #0 ;Zero ten's digit
|
|
jsr L3079 ;Convert to 2-byte ASCII char
|
|
jsr StorCR
|
|
rts
|
|
REP 50
|
|
; Input
|
|
; Output
|
|
L287B jsr StorERR
|
|
ldy #$1D ;mismatch REF-DEF size
|
|
jsr StorMsg
|
|
jsr StorName
|
|
ldy #$14 ;in mode #
|
|
jsr StorMsg
|
|
ldy #4
|
|
lda (XtnRecP),y ;Get REL file #
|
|
ldy #0 ;Zero ten's digit
|
|
jsr L3079 ;Convert
|
|
jsr StorCR
|
|
rts
|
|
REP 50
|
|
; Store "ERR:" to LinkMap file
|
|
; Input
|
|
; Output
|
|
;
|
|
StorERR lda #'E'
|
|
jsr StorChar
|
|
lda #'R'
|
|
jsr StorChar
|
|
jsr StorChar
|
|
lda #':'
|
|
jmp StorChar
|
|
REP 50
|
|
; Store to LinkMap file
|
|
; Input
|
|
; Output
|
|
;
|
|
StorMsgY bit MapFileF ;Store in file LinkMAP
|
|
bpl L28CD ;No, ret
|
|
jsr StorMsg
|
|
jmp StorCR
|
|
REP 50
|
|
; ($28B4) Write Message to LinkMap file
|
|
; Input
|
|
; Output
|
|
; (Y)-index into message sub-tables
|
|
;
|
|
StorMsg lda MsgTLo,y
|
|
sta MsgP
|
|
lda MsgTHi,y
|
|
sta MsgP+1
|
|
ldy #0
|
|
L28C0 lda (MsgP),y
|
|
cmp #'\' ;eol
|
|
beq L28CD
|
|
jsr StorChar
|
|
iny
|
|
jmp L28C0 ;next char
|
|
L28CD rts
|
|
;=================================================
|
|
; Phase 3 of the Linking process
|
|
; Relocate the object code. The RLD of each src file
|
|
; is used to relocate the code from each file. Code
|
|
; fr src files whose names are preceded by an ; in
|
|
; the cmd file are not included in the OBJECT file.
|
|
; Mem reserved for the SymbolicName table is re-used
|
|
; as a data buf. 256 bytes of the code image of
|
|
; a src file are read into this area first b4
|
|
; being move forward into previous mem page
|
|
; for patching.
|
|
;
|
|
; Input
|
|
; Output
|
|
; ModNbr - # of src files
|
|
; CurrORG - Starting PC for curr src file
|
|
; (Z96)
|
|
; (LwrBound)
|
|
; (UprBound,9C)
|
|
;
|
|
DoPhase3 EQU *
|
|
ldy #$06 ;Relocating objcode...
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
ldy #$06
|
|
jsr StorMsgY
|
|
;
|
|
lda #0
|
|
sta ModNbr
|
|
sta Z96 ;EO REL-type OBJECT file
|
|
sta Z96+1
|
|
;
|
|
lda Origin
|
|
sta CurrORG ;Starting PC
|
|
lda Origin+1
|
|
sta CurrORG+1
|
|
jsr MovObjFN ;Set to "EDASM.LINKOBJ"
|
|
jsr PRODOS8 ;DESTROY
|
|
DB $C1
|
|
DW DestryP
|
|
;
|
|
lda Origin
|
|
sta CreateP+c.auxId
|
|
lda Origin+1
|
|
sta CreateP+c.auxId+1;auxtype
|
|
lda TrgtFTyp ;filetype of OBJECT file
|
|
sta CreateP+c.fileId
|
|
jsr PRODOS8 ;CREATE
|
|
DB $C0
|
|
DW CreateP
|
|
bne L2919
|
|
;
|
|
jsr PRODOS8 ;OPEN the OBJECT file
|
|
DB $C8
|
|
DW Open3P
|
|
beq L291C
|
|
;
|
|
L2919 jsr ErrHndlr ;Don't come back
|
|
;
|
|
L291C lda Open3P+c.outRef ;OBJECT file
|
|
sta Write1P+c.refNum;RN to write OBJECT file
|
|
bit FTypeF ;What is the OBJECT file type?
|
|
bpl L294A ;=>BIN/SYS
|
|
;
|
|
lda #$00 ;REL OBJECT file
|
|
sta X9100
|
|
sta X9100+1
|
|
sta Write1P+c.reqCnt+1;Write 2 zeroes for
|
|
lda #$02 ; the code image len
|
|
sta Write1P+c.reqCnt
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write1P
|
|
beq L2941
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2941 lda WrMapFP+c.refNum
|
|
jsr ClsFile
|
|
jsr OpTmpRLD ;Open a tempRLD file 4 writing
|
|
;
|
|
L294A jsr L343B ;Set file posn to BO cmd file
|
|
;
|
|
; Skip all directives at the BO cmd file
|
|
; to get at the src pathnames
|
|
;
|
|
L294D jsr Read1Cmd ;Get a src filename
|
|
bne Phs3Loop ;Not cr/space => pathname
|
|
cmp #CR
|
|
bne L294D ;A leading space, skip to the directive
|
|
jmp CmdOrderErr ;Invalid cmd order
|
|
;
|
|
; Mainloop for phase 3
|
|
;
|
|
Phs3Loop jsr DspLineB ;Show PN of the curr src
|
|
jsr OpenSrc ;Open it 4 reading
|
|
bit Z9E ;Is src PN preceded by ;?
|
|
bpl L296C ;No
|
|
;
|
|
lda OpSrcFP+c.outRef;Close it
|
|
jsr ClsFile
|
|
jmp L2B55 ;Skip reading fr it
|
|
;
|
|
L296C lda #2
|
|
clc
|
|
adc SrcCodeLen ;Set file posn to BO
|
|
sta SMSrcFP+c.mark
|
|
lda #0
|
|
adc SrcCodeLen+1
|
|
sta SMSrcFP+c.mark+1; Relocation Dictionary
|
|
;
|
|
lda OpSrcFP+c.outRef
|
|
sta SMSrcFP+c.refNum
|
|
sta RdCodeImgP+c.refNum
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMSrcFP
|
|
beq L2991
|
|
L298E jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2991 jsr L3348 ;Have we read entire RLD?
|
|
bcc L2999 ;Yes
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2999 lda #2 ;Set file posn to BO
|
|
sta SMSrcFP+c.mark ; code image of src file
|
|
lda #0
|
|
sta SMSrcFP+c.mark+1
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMSrcFP
|
|
bne L298E
|
|
;
|
|
lda #0
|
|
sta LwrBound
|
|
sta LwrBound+1
|
|
sta UprBound
|
|
sta UprBound+2
|
|
jsr Rd1PgImg ;Read the first $100 bytes of code image
|
|
;
|
|
; Loop to process all recs in the RLD of curr src file
|
|
;
|
|
L29B8 jsr PollKbd
|
|
ldy #0
|
|
lda (SrcP),y ;Get flag byte fr RLD record
|
|
sta RLDFlags
|
|
bne L29C7
|
|
jmp L2B13 ;EO RLD => done w/this src file
|
|
;
|
|
; The code below doesn't check for overflow
|
|
; What happens if field offset is a #
|
|
; > $6EFF?
|
|
;
|
|
L29C7 ldy #1
|
|
lda (SrcP),y
|
|
sta Z80 ;Field offset in code image
|
|
clc
|
|
adc #>X9100
|
|
sta Z86
|
|
iny
|
|
lda (SrcP),y
|
|
sta Z80+1
|
|
adc #<X9100
|
|
sta Z86+1 ;$9100-$FFFF?
|
|
;
|
|
; Check if the field offset is within the "window"
|
|
; bounds LwrBound and UprBound. Since no effort is made
|
|
; to check the lower bound, it is assumed that the
|
|
; field offset is past this when (Z80) < UprBound
|
|
; It is also assumed that all records (in the RLD) have been
|
|
; arranged with field offsets in ascending order
|
|
;
|
|
L29DB lda Z80 ;Is field offset < upper bounds?
|
|
cmp UprBound
|
|
lda Z80+1
|
|
sbc UprBound+2
|
|
bcc L29EB ;Yes, within the "window"
|
|
jsr L2AA0 ;No, read another page of code
|
|
jmp L29DB ; and check again
|
|
;
|
|
; The ptr Z86 could be calculated by
|
|
; (Z86)=(Z80) - (LwrBound) + $9100
|
|
;
|
|
L29EB sec
|
|
lda Z86
|
|
sbc LwrBound
|
|
sta Z86 ;Z86 -= LwrBound
|
|
lda Z86+1 ;If there is no overflow above,
|
|
sbc LwrBound+1
|
|
sta Z86+1 ; then $9100 =< (Z86) =< $91FF
|
|
;
|
|
bit FTypeF ;REL OBJECT file?
|
|
bpl L2A0E ;No => BIN/SYS
|
|
;
|
|
ldy #2
|
|
lda Z80 ;Field offset
|
|
clc
|
|
adc Z96 ;Len of Code Image of
|
|
pha
|
|
lda Z80+1 ; REL OBJECT file excluding
|
|
adc Z96+1 ; that of curr src file
|
|
sta (SrcP),y ;Patch field offset of RLD record
|
|
dey ;Y=1
|
|
pla
|
|
sta (SrcP),y
|
|
;
|
|
L2A0E bit RLDFlags ;Is size of relocatable field 2?
|
|
bmi L2A54 ;Yes
|
|
;
|
|
ldy #0 ;Get original addr (lo/hi)
|
|
lda (Z86),y ; byte fr the code image
|
|
bit RLDFlags ;Is it hi-8 of addr?
|
|
bvs L2A31 ;Yes
|
|
;
|
|
; (A) has the lo-8 of the addr (fr a > byte operator)
|
|
; Since only the lobyte is used to patch the code
|
|
; any value for the hibyte can be used. So let's
|
|
; use 0 as RelAdrHi
|
|
;
|
|
sta RelAdr
|
|
lda #$00
|
|
sta RelAdr+1
|
|
jsr L30D9 ;Calc/get relocated addr
|
|
ldy #0
|
|
lda RelAdr ;Use the lo 8-bit to
|
|
sta (Z86),y ; patch the code image
|
|
jmp L2A96 ;Skip code below
|
|
;
|
|
; (A) has the hi-8 of the addr (fr a < byte operator)
|
|
; For this case, we need both the low & high bytes
|
|
; of the original addr if relocation rec is not
|
|
; flagged as EXTRN symbol-type
|
|
;
|
|
L2A31 sta RelAdr+1 ;hi-byte
|
|
ldy #3
|
|
lda (SrcP),y ;lo 8-bits/EXTRN symbol #
|
|
sta RelAdr
|
|
lda RLDFlags ;Get RLD flag byte
|
|
and #$10 ;EXTRN symbol-type?
|
|
beq L2A47 ;No
|
|
;
|
|
lda #$00
|
|
sta RelAdr ;Overwrite EXTRN symbol #
|
|
;
|
|
; On fall thru, the relocated addr will not be
|
|
; calculated but obtained fr an ENTRY rec if
|
|
; it is available.
|
|
;
|
|
L2A47 jsr L30D9 ;Calc/get the relocated addr
|
|
ldy #0
|
|
lda RelAdr+1
|
|
sta (Z86),y ;Patch code image
|
|
jmp L2A96 ;Skip code below
|
|
;
|
|
; Size of relocatable field is 2
|
|
; Get relocated addr fr the RLD rec
|
|
;
|
|
L2A54 ldy #0
|
|
lda RLDFlags ;Get RLD rec's flag byte
|
|
and #$20 ;Normal/Reversed order?
|
|
bne L2A7B
|
|
lda (Z86),y ;Little Endian (reversed order)
|
|
sta RelAdr
|
|
iny
|
|
lda (Z86),y
|
|
sta RelAdr+1
|
|
jsr L30D9 ;Calc/get relocated addr
|
|
;
|
|
ldy #0
|
|
lda RelAdr
|
|
sta (Z86),y ;Patch the code
|
|
iny
|
|
lda RelAdr+1
|
|
sta (Z86),y
|
|
jmp L2A96 ;=>next RLD
|
|
;
|
|
; Handle a Big Endian
|
|
;
|
|
L2A7B lda (Z86),y
|
|
sta RelAdr+1 ;hiaddr
|
|
iny
|
|
lda (Z86),y
|
|
sta RelAdr ;loaddr
|
|
jsr L30D9 ;Calc/get relocated addr
|
|
ldy #0
|
|
lda RelAdr+1
|
|
sta (Z86),y ;Patch the code
|
|
iny
|
|
lda RelAdr
|
|
sta (Z86),y
|
|
;
|
|
L2A96 lda #4 ;Pointer size
|
|
ldx #SrcP
|
|
jsr IncRecPZ ;Adv SrcP to next RLD rec
|
|
jmp L29B8 ; loop back to process it
|
|
REP 50
|
|
;
|
|
; Flush object code if neccessary. Move buffered
|
|
; code forward into "window" so that another page
|
|
; of code image can be read into the $9200 data buffer
|
|
; The variables LwrBound & UprBound gives a "window"
|
|
; into the code image.
|
|
; Normally (UprBound - LwrBound) = $100 except when
|
|
; the last (partial) page of code is read. In this
|
|
; case (UprBound - LwrBound) < $100
|
|
; Input
|
|
; LwrBound -
|
|
; UprBound -
|
|
; Output
|
|
; UprBound -
|
|
;
|
|
L2AA0 EQU *
|
|
lda UprBound ;Do we need to flush OBJECT code b4
|
|
ora UprBound+2 ; b4 we "move" our window forward?
|
|
beq L2AA9 ;No, we are still @ BO of src file
|
|
jsr L2AD8 ;Yes
|
|
;
|
|
L2AA9 ldy #0 ;Move buffered Code Image
|
|
L2AAB lda X9200,y ; forward into our "window"
|
|
sta X9100,y ; @ $9100-$91FF so we can
|
|
iny
|
|
bne L2AAB
|
|
jsr Rd1PgImg ; load another page @ $9200
|
|
;
|
|
lda UprBound
|
|
sta LwrBound
|
|
lda UprBound+2
|
|
sta LwrBound+1
|
|
inc UprBound+2 ; Incr by 1 page
|
|
;
|
|
lda UprBound
|
|
cmp SrcCodeLen ;Has the entire code
|
|
lda UprBound+2
|
|
cmp SrcCodeLen+1 ; image been read?
|
|
bcc L2AD7 ;No
|
|
;
|
|
lda SrcCodeLen
|
|
sta UprBound ;This may no longer be
|
|
lda SrcCodeLen+1
|
|
sta UprBound+2 ; 1 mempage > LwrBound
|
|
L2AD7 rts
|
|
REP 50
|
|
; Write object code @ $9100
|
|
; Input
|
|
; Output
|
|
;
|
|
L2AD8 EQU *
|
|
sec
|
|
lda UprBound
|
|
sbc LwrBound
|
|
sta Write1P+c.reqCnt;# of bytes to write
|
|
lda UprBound+2
|
|
sbc LwrBound+1
|
|
sta Write1P+c.reqCnt+1; usually $100 bytes
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write1P
|
|
beq L2AD7
|
|
;
|
|
L2AEF jsr ErrHndlr ;Don't come back
|
|
;
|
|
; Read $100 bytes of data into buf starting @ $9200
|
|
; fr src file. The symbolicname table @ $9200 is
|
|
; re-used as a Read data buf
|
|
; Output
|
|
; Z=1
|
|
; (A) = $4C if EOF or
|
|
; = $00 read succeeded
|
|
;
|
|
Rd1PgImg EQU *
|
|
lda #0
|
|
sta RdCodeImgP+c.reqCnt
|
|
lda #1
|
|
sta RdCodeImgP+c.reqCnt+1
|
|
lda #>X9200 ;Read Data Buf
|
|
sta RdCodeImgP+c.dataBuf
|
|
lda #<X9200
|
|
sta RdCodeImgP+c.dataBuf+1
|
|
jsr PRODOS8 ;READ
|
|
DB $CA
|
|
DW RdCodeImgP
|
|
beq L2AD7 ;If no errs, just ret
|
|
;
|
|
cmp #$4C ;EOF?
|
|
bne L2AEF ;No -> err handler
|
|
rts
|
|
;
|
|
; Skip rest of code image
|
|
;
|
|
L2B13 EQU *
|
|
lda UprBound
|
|
cmp SrcCodeLen
|
|
bne L2B21
|
|
lda UprBound+2
|
|
cmp SrcCodeLen+1
|
|
beq L2B27 ;Done w/this src file
|
|
L2B21 jsr L2AA0 ;Keep flushing objcode N reading code image
|
|
jmp L2B13 ; until we are done
|
|
;
|
|
L2B27 jsr L2AD8 ;Append rest of OBJECT code
|
|
lda RdCodeImgP+c.refNum
|
|
jsr ClsFile
|
|
jsr Add2TmpRLD ;Append patched RLD @ SrcDBuf
|
|
;
|
|
ldx ModNbr
|
|
lda CurrORG ;Starting posn counter
|
|
sta OrgAdrLo,x ; for this src file
|
|
lda CurrORG+1
|
|
sta OrgAdrHi,x
|
|
jsr L2BA2 ;adj pc?
|
|
;
|
|
lda CurrORG+1
|
|
sta EndAdrHi,x
|
|
lda CurrORG
|
|
sta EndAdrLo,x
|
|
bne L2B52
|
|
dec EndAdrHi,x ;End posn counter
|
|
L2B52 dec EndAdrLo,x ; for this src file
|
|
;
|
|
L2B55 inc ModNbr ;Next src module
|
|
L2B58 jsr Read1Cmd ;Is it a pathname?
|
|
bne L2B9C ;Yes, prepare to loop back
|
|
cmp #CR
|
|
beq DonePhs3 ;Empty line => Finish all cmds
|
|
jsr IsALN ;Is it Align directive?
|
|
bcc L2B69 ;Possible
|
|
jmp DoBreak ;Don't comeback
|
|
;
|
|
L2B69 beq L2B6E ;Align option
|
|
jmp CmdOrderErr ;cmd order err
|
|
;
|
|
L2B6E lda CurrORG ;Already aligned @ start of mempage?
|
|
beq L2B58 ;Yes, read another cmd line
|
|
;
|
|
ldx #0
|
|
txa
|
|
L2B75 sta X9100,x
|
|
inx
|
|
bne L2B75
|
|
;
|
|
lda #0
|
|
sec
|
|
sbc CurrORG
|
|
sta Write1P+c.reqCnt;# of zero bytes to fill
|
|
sta SrcCodeLen ; Re-used
|
|
lda #0
|
|
sta Write1P+c.reqCnt+1
|
|
sta SrcCodeLen+1 ;Used by $2BA2
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write1P
|
|
bne L2B9F
|
|
;
|
|
jsr L2BA2 ;Adj PC
|
|
jmp L2B58 ;Read next cmd line
|
|
;
|
|
L2B9C jmp Phs3Loop ;Loop back to process new src file
|
|
;
|
|
L2B9F jsr ErrHndlr ;Don't come back
|
|
REP 50
|
|
; Adjust file posn
|
|
; Input
|
|
; Output
|
|
; (Z96) - curr val of code image len
|
|
;
|
|
L2BA2 lda SrcCodeLen
|
|
clc
|
|
adc CurrORG
|
|
sta CurrORG ;CurrORG += SrcCodeLen
|
|
lda SrcCodeLen+1
|
|
adc CurrORG+1
|
|
sta CurrORG+1
|
|
bit FTypeF ;REL OBJECT file?
|
|
bpl L2BC4 ;No -> exit
|
|
;
|
|
clc
|
|
lda SrcCodeLen
|
|
adc Z96
|
|
sta Z96 ;Z96 += SrcCodeLen
|
|
lda SrcCodeLen+1
|
|
adc Z96+1
|
|
sta Z96+1
|
|
L2BC4 rts
|
|
;
|
|
; Prepare to exit Phase 3
|
|
;
|
|
DonePhs3 bit FTypeF ;REL OBJECT file?
|
|
bpl L2BD8 ;No
|
|
;
|
|
ldy #0
|
|
sty SrcDBuf
|
|
sty Write2P+c.reqCnt+1
|
|
iny ;=1
|
|
sty Write2P+c.reqCnt;# of bytes to write=1
|
|
jsr L31C1 ;Marks EO RLD file
|
|
;
|
|
L2BD8 bit FTypeF ;Is REL OBJECT file?
|
|
bmi DoPhase4 ;Yes
|
|
jmp L2C8E
|
|
;=================================================
|
|
; Phase 4 of the Linking process done only if
|
|
; the OBJECT file is of type REL
|
|
; Contents of TempRLD and TempESD files are appended
|
|
; to the relocatable OBJECT file
|
|
; Input
|
|
; Output
|
|
;
|
|
DoPhase4 ldy #$07
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
lda Write2P+c.refNum;RN of tempRLD file
|
|
sta SMarkP+c.refNum
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMarkP ;Set file posn to BO tempRLD file
|
|
beq L2BF8
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2BF8 jsr L2C5A ;Append tempRLD to REL OBJECT file
|
|
lda Write2P+c.refNum
|
|
jsr ClsFile ;Now close tempRLD file
|
|
jsr PollKbd
|
|
jsr L26D1 ;Set PN to TempESD
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW Open2P
|
|
beq L2C12
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2C12 lda Open2P+c.outRef
|
|
sta Write2P+c.refNum
|
|
jsr L2C5A ;Append TempESD to REL OBJECT file
|
|
lda Write2P+c.refNum
|
|
jsr ClsFile ;Now close tempESD
|
|
;
|
|
lda Open3P+c.outRef
|
|
sta SMarkP+c.refNum ;Posn to BO REL OBJECT file
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMarkP
|
|
beq L2C32
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2C32 lda Z96 ;Write the CodeImage Len
|
|
sta X9100
|
|
lda Z96+1 ; of REL OBJECT file
|
|
sta X9100+1
|
|
lda #0
|
|
sta Write1P+c.reqCnt+1
|
|
lda #2
|
|
sta Write1P+c.reqCnt;2 bytes only
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write1P
|
|
beq L2C51
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2C51 jsr PollKbd
|
|
jsr L31CD ;Open LinkMap file for appending
|
|
jmp L2C8E
|
|
REP 50
|
|
;
|
|
; ($2C5A) Read entire contents of tempRLD/tempESD
|
|
; and append it to the OBJECT file (which is of
|
|
; type REL)
|
|
; Input
|
|
; Output
|
|
;
|
|
L2C5A lda Write2P+c.refNum;RN of tempRLD/tempESD file
|
|
sta RWFileP+c.refNum
|
|
jsr L334E ;Read data chunk fr file
|
|
php ;Save for later
|
|
bcc L2C6D
|
|
cmp #$10
|
|
beq L2C6D ;Not EOF
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2C6D lda Open3P+c.outRef ;OBJECT file's RN
|
|
sta RWFileP+c.refNum;Write same data chunk
|
|
lda RWFileP+c.transCnt
|
|
sta RWFileP+c.reqCnt
|
|
lda RWFileP+c.transCnt+1
|
|
sta RWFileP+c.reqCnt+1;to the OBJECT file
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW RWFileP
|
|
beq L2C8A
|
|
jsr ErrHndlr ;Don't come back
|
|
L2C8A plp ;Has last chunk been read?
|
|
bcs L2C5A ;No, do another chunk
|
|
rts
|
|
;
|
|
L2C8E EQU *
|
|
lda Open3P+c.outRef ;Finally, close OBJECT file
|
|
jsr ClsFile
|
|
bit FTypeF ;Was it relocatable OBJECT file?
|
|
bpl L2C9D ;No
|
|
;
|
|
ldy #$07 ;Phase 4...
|
|
jsr StorMsgY
|
|
L2C9D bit MapFileF ;Output to LinkMap?
|
|
bmi L2CA4 ;Yes
|
|
jmp L2E10
|
|
;
|
|
L2CA4 bit SortLMF ;Sort LoadMap table?
|
|
bmi DoPhase5 ;Yes
|
|
jmp L2E10
|
|
;=================================================
|
|
; Phase 5 of the Linking process
|
|
; Sort Relocated Adr table
|
|
; First create a LoadMap table of 4-byte records
|
|
; The LoadMap table starts @ $9100
|
|
; Layout of each record is:
|
|
; DW ptr to an ENTRY table rec
|
|
; DW relocated addr stored in the ENTRY table rec
|
|
;
|
|
; Output:
|
|
; (EntRecP) - ptr to a rec in ENTRY table
|
|
; (Z86) - ptr to a rec in LoadMap table
|
|
; (Z80) - ptr to EO LoadMap table
|
|
;
|
|
DoPhase5 ldy #$08
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
ldy #$08
|
|
jsr StorMsgY
|
|
;
|
|
lda #>EntTbl ;ENTRY table is still in mem
|
|
sta EntRecP ;Set up a ptr to its beginning
|
|
lda #<EntTbl
|
|
sta EntRecP+1
|
|
lda #>X9100 ;4-byte records in LoadMap table
|
|
sta Z86
|
|
lda #<X9100
|
|
sta Z86+1
|
|
lda #0 ;Total # of records in
|
|
sta NumRecs ; ENTRY table to be sorted
|
|
sta NumRecs+1
|
|
;
|
|
; The code below builds the unsorted LoadMap table
|
|
;
|
|
L2CCE jsr PollKbd
|
|
ldy #0
|
|
lda (EntRecP),y ;EO ENTRY table?
|
|
beq L2D03 ;Yes
|
|
;
|
|
lda EntRecP
|
|
sta (Z86),y ;Points to record in ENTRY table
|
|
iny
|
|
lda EntRecP+1
|
|
sta (Z86),y
|
|
;
|
|
ldy #18
|
|
lda (EntRecP),y ;Get relocated addr associated with
|
|
pha
|
|
iny
|
|
lda (EntRecP),y ; the SymbolicName of the ENTRY rec
|
|
ldy #3
|
|
sta (Z86),y ; and store in LoadMap record
|
|
pla
|
|
dey
|
|
sta (Z86),y
|
|
;
|
|
lda #4 ;Pointer size
|
|
ldx #Z86
|
|
jsr IncRecPZ ;Adv to next LoadMap rec
|
|
jsr IncrEntP ;Adv to next ENTRY record
|
|
inc NumRecs ;rec count
|
|
bne L2D00
|
|
inc NumRecs+1
|
|
L2D00 jmp L2CCE ;Continue to build LoadMap table
|
|
;
|
|
; Initial LoadMap table has been build
|
|
;
|
|
L2D03 ldy #0
|
|
tya ;(A)=0
|
|
sta (Z86),y ;Mark EO LoadMap table
|
|
iny
|
|
sta (Z86),y ;with a NIL ptr
|
|
;
|
|
lda Z86
|
|
sta Z80 ;(Z80)=EO LoadMap table
|
|
lda Z86+1
|
|
sta Z80+1
|
|
jsr SortLM ;Sort it
|
|
jmp L2E10
|
|
REP 50
|
|
; Sort the Load (addr) Map
|
|
; Shell-Metzner Sort
|
|
; Input
|
|
; Output
|
|
;
|
|
SortLM EQU *
|
|
lda NumRecs ;Jump=# of elements N
|
|
sta Jump
|
|
lda NumRecs+1
|
|
sta Jump+1
|
|
;
|
|
; While Jump <> 0
|
|
;
|
|
WhileLoop lsr Jump+1 ;Jump=Jump div 2
|
|
ror Jump
|
|
lda Jump
|
|
ora Jump+1
|
|
bne L2D2C
|
|
rts
|
|
;
|
|
L2D2C sec
|
|
lda NumRecs
|
|
sbc Jump
|
|
sta EndIdx
|
|
lda NumRecs+1
|
|
sbc Jump+1
|
|
sta EndIdx+1
|
|
;
|
|
ldx #0
|
|
stx StrtIdx+1
|
|
inx
|
|
stx StrtIdx
|
|
ForLoop jsr PollKbd
|
|
;
|
|
; FOR JJJ := 1 to NumRecs-Jump
|
|
;
|
|
lda StrtIdx
|
|
sta JJJ
|
|
lda StrtIdx+1
|
|
sta JJJ+1
|
|
;
|
|
; REPEAT
|
|
;
|
|
RptLoop clc
|
|
lda JJJ
|
|
adc Jump
|
|
sta III ;I=J+Jump
|
|
lda JJJ+1
|
|
adc Jump+1
|
|
sta III+1
|
|
;
|
|
ldx #3
|
|
L2D5A lda JJJ,x
|
|
sta J.TH,x
|
|
dex
|
|
bpl L2D5A
|
|
;
|
|
; Mulby4 and add to X9100-4
|
|
; Calc indices to the elements to be compared
|
|
; (J.TH) - Ptr to j-th element
|
|
; (I.TH) - Ptr to i-th element
|
|
;
|
|
ldx #2
|
|
L2D63 asl J.TH,x ;x4
|
|
rol J.TH+1,x
|
|
asl J.TH,x
|
|
rol J.TH+1,x
|
|
;
|
|
clc
|
|
lda #>X9100-4
|
|
adc J.TH,x
|
|
sta J.TH,x
|
|
lda #<X9100-4
|
|
adc J.TH+1,x
|
|
sta J.TH+1,x
|
|
dex
|
|
dex
|
|
beq L2D63
|
|
;
|
|
bit NumSortF
|
|
bpl L2D98
|
|
;
|
|
; Sort load addresses numerically in ascending order
|
|
;
|
|
ldy #3
|
|
lda (J.TH),y ;Get load addr (Hibyte)
|
|
cmp (I.TH),y
|
|
beq L2D8D
|
|
bcs L2D94 ;Greater than
|
|
L2D8A jmp NextJ ;Less than
|
|
L2D8D dey
|
|
lda (I.TH),y ;Get load addr (lobyte)
|
|
cmp (J.TH),y
|
|
bcs L2D8A ;Less than
|
|
L2D94 ldy #3
|
|
bne L2DD3 ;Always -> Swap the records
|
|
;
|
|
; Sort SymbolicName alphabetically
|
|
; IF ENTRY[J].name > ENTRY[I].name then SWAP(Ary[J], Ary[I])
|
|
; The 1st field of an ENTRY rec is a 16-byte p-string
|
|
;
|
|
L2D98 ldy #0
|
|
lda (J.TH),y ;Get ptr to j-th
|
|
tax ; ENTRY rec
|
|
iny
|
|
lda (J.TH),y
|
|
sta EntRPJ+1
|
|
stx EntRPJ
|
|
lda (I.TH),y
|
|
tax
|
|
dey ;=0
|
|
lda (I.TH),y ;Get ptr to i-th
|
|
sta EntRPI ; ENTRY rec
|
|
stx EntRPI+1
|
|
lda (EntRPJ),y ;Get len byte of symbolic name
|
|
cmp (EntRPI),y
|
|
beq L2DB8
|
|
bcc L2DB8
|
|
;
|
|
lda (EntRPI),y ;The len of this symbolic name is shorter
|
|
L2DB8 tax ;# of chars to compare
|
|
iny ;=1
|
|
L2DBA lda (EntRPJ),y ;Get char fr symbolic name
|
|
cmp (EntRPI),y
|
|
bne L2DCF ;Not match
|
|
iny
|
|
cpy #16 ;At most 15 chars will be compared
|
|
bcs NextJ ;All chars matched
|
|
dex
|
|
bne L2DBA
|
|
lda #SPACE
|
|
cmp (EntRPJ),y
|
|
beq NextJ
|
|
sec ;Flag we have to do a swap
|
|
L2DCF bcc NextJ ;C=0 -> 1st symbolic name < 2nd
|
|
;
|
|
; Swap the records in LoadMap
|
|
; Too costly to swap those in ENTRY table
|
|
;
|
|
ldy #3
|
|
L2DD3 lda (J.TH),y ;Swap the ptrs as
|
|
tax
|
|
lda (I.TH),y
|
|
sta (J.TH),y ; well as the corr addrs
|
|
txa
|
|
sta (I.TH),y
|
|
dey
|
|
bpl L2DD3
|
|
;
|
|
sec
|
|
lda JJJ ;J > Jump
|
|
sbc Jump
|
|
sta JJJ
|
|
lda JJJ+1
|
|
sbc Jump+1 ;J := J - Jump
|
|
sta JJJ+1 ;Is J > Jump?
|
|
bmi NextJ ;No, less than
|
|
ora JJJ
|
|
beq NextJ ;No, J=Jump
|
|
jmp RptLoop
|
|
;
|
|
; UNTIL JJJ =< Jump
|
|
;
|
|
NextJ inc StrtIdx
|
|
bne L2DFC
|
|
inc StrtIdx+1
|
|
;
|
|
L2DFC lda StrtIdx+1 ;Finis w/FOR loop
|
|
cmp EndIdx+1
|
|
bcc L2E0D
|
|
beq L2E07
|
|
L2E04 jmp WhileLoop ;No
|
|
L2E07 lda EndIdx
|
|
cmp StrtIdx
|
|
bcc L2E04
|
|
L2E0D jmp ForLoop
|
|
;-----
|
|
L2E10 bit MapFileF ;Write LinkMap?
|
|
bmi DoPhase6 ;Yes
|
|
jmp OK2Exit
|
|
;=================================================
|
|
; Phase 6 of the Linking process
|
|
; Makes use of LoadMap table to store info
|
|
; into the LinkMap txtfile
|
|
;
|
|
DoPhase6 ldy #$09
|
|
jsr DspMsg
|
|
jsr DspCR
|
|
ldy #$09
|
|
jsr StorMsg
|
|
jsr StorCR
|
|
jsr L343B ;Reset to BO cmd line file
|
|
jsr StorCR
|
|
jsr StorCR
|
|
lda #0
|
|
sta ModNbr
|
|
sta L380F ;counter
|
|
sta PageF ;Don't output to printer
|
|
;
|
|
L2E3A jsr PollKbd
|
|
jsr Read1Cmd
|
|
bne L2E4F ;If non-blank & not cr, it's a PN
|
|
cmp #CR ;Is 1st char a CR?
|
|
bne L2E49 ;No, a leading space, ignore it
|
|
jmp L2ED3 ;No more directives
|
|
L2E49 jsr StorCmd ;Just store cmd in LinkMap file
|
|
jmp L2E3A ;Get another command
|
|
;
|
|
; Got the Pathname of a src file
|
|
;
|
|
L2E4F jsr StorCR
|
|
jsr StorCR
|
|
ldy #$18 ;MOD ORG etc
|
|
jsr StorMsg
|
|
ldy #$19 ;# ADR ADR etc
|
|
jsr StorMsg
|
|
jsr StorCR
|
|
jmp L2E76 ;-> proceed to start storing info
|
|
;
|
|
; Loop to get the PN of another src file
|
|
;
|
|
L2E65 jsr PollKbd
|
|
jsr Read1Cmd
|
|
bne L2E76 ;Not cr/space
|
|
cmp #CR
|
|
beq L2ED3 ;No more commands => done
|
|
jsr L2F43 ;Set module's Addr Range
|
|
beq L2E88 ;always
|
|
;
|
|
; Start writing info into LinkMap file
|
|
;
|
|
L2E76 jsr StorSpc
|
|
lda ModNbr
|
|
jsr StorByte
|
|
jsr StorSpc
|
|
jsr StorSpc
|
|
;
|
|
ldx L380F ;Get src file index
|
|
L2E88 lda OrgAdrHi,x ;Start Addr
|
|
jsr StorByte
|
|
lda OrgAdrLo,x ; of this src module
|
|
jsr StorByte
|
|
;
|
|
lda #'-'
|
|
jsr StorChar
|
|
lda EndAdrHi,x ;Its End Addr
|
|
jsr StorByte
|
|
lda EndAdrLo,x
|
|
jsr StorByte
|
|
jsr StorSpc
|
|
jsr StorSpc
|
|
;
|
|
ldy #0
|
|
L2EAD jsr ChrGot ;Store PN
|
|
cmp #CR
|
|
beq L2EBA
|
|
jsr StorChar
|
|
iny
|
|
bne L2EAD
|
|
;
|
|
L2EBA jsr StorCR
|
|
cpx L380F
|
|
bne L2ED0
|
|
;
|
|
sed
|
|
lda ModNbr
|
|
clc
|
|
adc #1
|
|
sta ModNbr
|
|
cld
|
|
inc L380F
|
|
L2ED0 jmp L2E65 ;Loop back for next module
|
|
;
|
|
L2ED3 bit XRefF ;Did user ask for xferencing?
|
|
bpl ExitPhs6 ;No
|
|
;
|
|
lda #$80
|
|
sta PageF
|
|
jsr L2FE4 ;Store header details etc...
|
|
bit SortLMF ;Did we sort the LoadMap table?
|
|
bpl L2F09 ;No
|
|
;
|
|
; Use Sorted LoadMap table
|
|
;
|
|
lda #>X9100
|
|
sta Z86
|
|
lda #<X9100 ;Points to BO LoadMap table
|
|
sta Z86+1
|
|
L2EEA jsr PollKbd
|
|
ldy #0
|
|
lda (Z86),y ;Get ptr to ENTRY record
|
|
sta Z88
|
|
iny
|
|
lda (Z86),y
|
|
sta Z88+1 ; and store it here
|
|
ora Z88 ;EO ENTRY table?
|
|
beq ExitPhs6 ;Yes
|
|
;
|
|
jsr L2F74 ;Write details of ENTRY rec into LinkMap
|
|
lda #4 ;Pointer size
|
|
ldx #Z86 ; Z86++
|
|
jsr IncRecPZ ;Next LoadMap record
|
|
jmp L2EEA
|
|
;
|
|
; Use ENTRY table instead of LoadMap table
|
|
;
|
|
L2F09 lda #>EntTbl ;Points to BO of ENTRY table
|
|
sta Z88
|
|
lda #<EntTbl
|
|
sta Z88+1
|
|
;
|
|
L2F11 jsr PollKbd
|
|
ldy #0
|
|
lda (Z88),y ;EOT?
|
|
beq ExitPhs6 ;Yes
|
|
jsr L2F74 ;Store details of ENTRY rec into LinkMap
|
|
ldx #Z88
|
|
lda #24 ;Pointer size
|
|
jsr IncRecPZ ;Next ENTRY record
|
|
jmp L2F11 ;Continue until EO ENTRY Table
|
|
REP 50
|
|
; Prepare to exit Linker
|
|
; Input
|
|
; Output
|
|
;
|
|
ExitPhs6 EQU *
|
|
lda #FF
|
|
jsr StorChar
|
|
jsr StorCR
|
|
lda WrMapFP+c.refNum;Close LinkMap txt file
|
|
sta CloseP+c.refNum
|
|
jsr PRODOS8 ;CLOSE
|
|
DB $CC
|
|
DW CloseP
|
|
beq OK2Exit
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
OK2Exit jmp DoExit ;Do an orderly exit
|
|
REP 50
|
|
; Get ORG and END addrs of the module
|
|
; Z=0, (X)=0
|
|
;
|
|
L2F43 EQU *
|
|
ldy #$05 ;Write 5 blanks to LinkMap
|
|
jsr StorSpcsY
|
|
ldx L380F ;Get src file index (1-49)
|
|
dex ;Index previous src module
|
|
ldy EndAdrHi,x
|
|
lda EndAdrLo,x
|
|
tax
|
|
inx
|
|
bne L2F57
|
|
iny
|
|
L2F57 stx OrgAdrLo
|
|
sty OrgAdrHi
|
|
;
|
|
ldx L380F
|
|
ldy OrgAdrHi,x
|
|
lda OrgAdrLo,x
|
|
tax
|
|
bne L2F6A
|
|
dey
|
|
L2F6A dex
|
|
stx EndAdrLo
|
|
sty EndAdrHi
|
|
ldx #$00
|
|
rts
|
|
REP 50
|
|
; Store info from ENTRY record
|
|
; Input
|
|
; Output
|
|
;
|
|
L2F74 EQU *
|
|
jsr L300B ;Store space/?
|
|
jsr StorAdr ;Relocated addr
|
|
jsr StorRFNbr ;File #
|
|
jsr StorSpc
|
|
jsr StorName ;Symbolicname
|
|
jsr StorSpc
|
|
jsr L3029 ;list of references
|
|
jsr StorCR
|
|
rts
|
|
REP 50
|
|
;
|
|
; Store a byte as a couple of ASC Hex digits
|
|
; Input
|
|
; (A)=byte
|
|
;
|
|
StorByte EQU *
|
|
pha
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
jsr StorHex
|
|
pla
|
|
and #$0F
|
|
jsr StorHex
|
|
rts
|
|
REP 50
|
|
; Store char into LinkMap buf. If char is CR,
|
|
; the text line will be written out to file
|
|
; Input
|
|
; WrMapFIdx - Write Map file buf index
|
|
; Output
|
|
; A,X preserved
|
|
; Y may not be used
|
|
;
|
|
StorChar and #$7F
|
|
sta Z9C ;Save A,X regs
|
|
stx Z9C+1
|
|
ldx WrMapFIdx
|
|
sta MapFDB,x ;store in buf
|
|
inc WrMapFIdx ;incr # of chars/buf index
|
|
cmp #CR
|
|
bne L2FBD
|
|
;
|
|
; Flush it
|
|
;
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW WrMapFP
|
|
beq L2FBA
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L2FBA sta WrMapFIdx ;Zero write buf index
|
|
L2FBD ldx Z9C+1
|
|
lda Z9C
|
|
rts
|
|
REP 50
|
|
;
|
|
; Convert a 8-bit binary value into its
|
|
; ASCII representation of 1's and 0's
|
|
; Input
|
|
; Output
|
|
;
|
|
L2FC2 EQU *
|
|
ldx #8
|
|
L2FC4 asl a ;Get bit into Carry
|
|
pha
|
|
lda #$00
|
|
rol a ;Catch the bit
|
|
adc #'0' ;'0' or '1'
|
|
jsr StorChar
|
|
pla
|
|
dex
|
|
bne L2FC4 ;Next bit
|
|
rts
|
|
REP 50
|
|
; ($2FD3) Store a CR to LinkMap file
|
|
; Input
|
|
; Output
|
|
;
|
|
StorCR lda #CR
|
|
jsr StorChar
|
|
inc LineCnt
|
|
lda LineCnt
|
|
cmp #60
|
|
bne L2FE3
|
|
jsr L2FE4 ;Write subtitle
|
|
L2FE3 rts
|
|
REP 50
|
|
; Store subtitle into LinkMap file
|
|
; Input
|
|
; Output
|
|
;
|
|
L2FE4 lda #FF ;Output a formfeed char
|
|
jsr StorChar
|
|
lda #3
|
|
sta LineCnt
|
|
sed
|
|
clc
|
|
lda #1
|
|
adc PageCnt
|
|
sta PageCnt
|
|
cld
|
|
bit PageF
|
|
bpl L3004
|
|
;
|
|
ldy #$1A ;Write 'ADR M# SYMBOL...' string
|
|
jsr StorMsg ; to LinkMap txt file
|
|
lda PageCnt
|
|
jsr StorByte
|
|
;
|
|
L3004 jsr StorCR
|
|
jsr StorCR
|
|
rts
|
|
REP 50
|
|
; Input
|
|
; Output
|
|
;
|
|
L300B EQU *
|
|
ldy #17
|
|
lda (Z88),y ;Get flag byte
|
|
and #%01000000 ;Was symbol referenced?
|
|
beq StorSpc ;Yes, use a space
|
|
lda #'?'
|
|
bne L3019 ;Use a Qn mark
|
|
REP 50
|
|
; Store a space into LinkMap txt file buffer
|
|
;
|
|
StorSpc EQU *
|
|
lda #SPACE
|
|
L3019 jsr StorChar
|
|
rts
|
|
REP 50
|
|
; Input
|
|
; (A)=$00-$0F
|
|
; Output
|
|
;
|
|
StorHex EQU *
|
|
ora #'0'
|
|
cmp #'9'+1
|
|
bcc L3025
|
|
adc #$06
|
|
L3025 jsr StorChar
|
|
rts
|
|
REP 50
|
|
; Store list of references to the relocated addr
|
|
; $40 set -> not referenced by any module
|
|
; Input
|
|
; Output
|
|
;
|
|
L3029 EQU *
|
|
ldy #17
|
|
lda (Z88),y ;Get flag byte
|
|
and #%01000000
|
|
beq L3037
|
|
ldy #$16 ;unreferenced
|
|
jsr StorMsg
|
|
rts
|
|
;
|
|
L3037 lda Z88 ;Ptr to ENTRY record
|
|
sta XtnRecP
|
|
lda Z88+1
|
|
sta XtnRecP+1
|
|
;
|
|
ldy #20
|
|
L3041 lda (XtnRecP),y ;Ptr to linked list
|
|
pha
|
|
iny
|
|
lda (XtnRecP),y ; of EXTRN records
|
|
sta XtnRecP+1
|
|
pla
|
|
sta XtnRecP
|
|
ora XtnRecP+1
|
|
beq L3072 ;NIL => end of linked list
|
|
;
|
|
ldy #4
|
|
lda (XtnRecP),y ;(A)=# to be converted
|
|
ldy #0 ;ten's digit
|
|
jsr L3079
|
|
jsr StorSpc
|
|
lda WrMapFIdx ;# of bytes in Map file's data buf
|
|
ldy #0
|
|
cmp #77 ; must not exceed this number
|
|
bcc L3041 ;Next node
|
|
;
|
|
jsr StorCR
|
|
ldy #26 ;# of spaces
|
|
jsr StorSpcsY
|
|
ldy #0
|
|
jmp L3041 ;Next Node in linked list
|
|
L3072 rts
|
|
REP 50
|
|
; Store REL file # as a 2-byte ASC char in LinkMap file
|
|
; Input
|
|
; Output
|
|
;
|
|
StorRFNbr ldy #16
|
|
lda (Z88),y ;REL file #
|
|
ldy #0
|
|
L3079 cmp #10
|
|
bcc L3084
|
|
sec
|
|
sbc #10
|
|
iny ;ten's digit
|
|
jmp L3079
|
|
;
|
|
L3084 pha ;unit's digit
|
|
tya
|
|
ora #'0'
|
|
jsr StorChar
|
|
pla
|
|
ora #'0'
|
|
jsr StorChar
|
|
rts
|
|
REP 50
|
|
; Store ENTRY record's name
|
|
; Input
|
|
; (Z88) - ptr to ENTRY record
|
|
; Output
|
|
;
|
|
StorName EQU *
|
|
ldy #0
|
|
lda (Z88),y ;len byte
|
|
cmp #16
|
|
bcc L309C
|
|
;
|
|
lda #15 ;At most 15
|
|
L309C tax
|
|
L309D iny
|
|
lda (Z88),y ;symbolname
|
|
jsr StorChar
|
|
dex
|
|
bne L309D
|
|
;
|
|
sty SymLen ;# of chars stored so far
|
|
sec
|
|
lda #16
|
|
sbc SymLen
|
|
tay ;# of spaces to store
|
|
;
|
|
; Enter here with (Y)=# of space to store
|
|
;
|
|
StorSpcsY EQU *
|
|
lda #SPACE
|
|
jsr StorChar
|
|
dey
|
|
bne StorSpcsY
|
|
rts
|
|
REP 50
|
|
; Store Relocated address in LinkMap file
|
|
; Input
|
|
; (Z88)-ptr to ENTRY record
|
|
; Output
|
|
;
|
|
StorAdr EQU *
|
|
ldy #19
|
|
lda (Z88),y ;Relocated Addr
|
|
jsr StorByte
|
|
dey
|
|
lda (Z88),y ;of this ENTRY record
|
|
jsr StorByte
|
|
jsr StorSpc
|
|
rts
|
|
REP 50
|
|
; Store cmd line incl terminating CR
|
|
; Input
|
|
; (cp)
|
|
; Output
|
|
;
|
|
StorCmd EQU *
|
|
ldy #0
|
|
L30CC lda (cp),y
|
|
and #$7F
|
|
jsr StorChar
|
|
iny
|
|
cmp #CR
|
|
bne L30CC
|
|
rts
|
|
REP 50
|
|
; If an RLD entry of src file flag its an
|
|
; (a) ENTRY symbol, calc relocated addr
|
|
; (b) EXTRN symbol, get relocated addr
|
|
; fr its associated ENTRY rec &
|
|
; we must modify the
|
|
; RLD & EXTRN recs
|
|
; Input
|
|
; RLDFlags
|
|
; Output
|
|
; RelAdr - value of relocated addr
|
|
;
|
|
L30D9 EQU *
|
|
lda RLDFlags
|
|
and #$10 ;Is EXTERN symbol?
|
|
bne L3105 ;Yes
|
|
;
|
|
lda RelAdr ;This is equiv to a subtraction
|
|
clc
|
|
adc NegSrcOrg ;2's complement of
|
|
sta RelAdr
|
|
lda RelAdr+1
|
|
adc NegSrcOrg+1 ; origin in src file
|
|
sta RelAdr+1
|
|
;
|
|
lda RelAdr
|
|
clc
|
|
adc CurrORG
|
|
sta RelAdr
|
|
lda RelAdr+1
|
|
adc CurrORG+1
|
|
sta RelAdr+1
|
|
rts
|
|
;
|
|
; EXTRN symbol
|
|
;
|
|
L3105 ldy ModNbr ;Get ptr to the
|
|
lda SrcModTLo,y ; first EXTRN rec
|
|
sta XtnRecP ; of curr src file
|
|
lda SrcModTHi,y
|
|
sta XtnRecP+1
|
|
;
|
|
; Search thru the EXTRN recs for the EXTRN symbol #
|
|
; NB. A hit is guaranteed during the search
|
|
; through the sub-array of EXTRN recs
|
|
;
|
|
lda #0
|
|
sta RelAdr
|
|
sta RelAdr+1
|
|
ldy #3 ;Get the EXTRN symbol #
|
|
lda (SrcP),y ; fr RLD record of src file
|
|
L311E ldy #6
|
|
cmp (XtnRecP),y
|
|
beq L312A ;Matched
|
|
jsr IncrXtnP
|
|
jmp L311E ;Try next EXTRN rec
|
|
;
|
|
L312A ldy #5
|
|
lda (XtnRecP),y ;symbol type
|
|
and #%10111111 ;Clear unreferenced bit
|
|
sta (XtnRecP),y
|
|
and #$80 ;Is the symbolicname still undefined?
|
|
bne L316D ;Yes
|
|
;
|
|
ldy #2
|
|
lda (XtnRecP),y ;Get ptr to associated
|
|
sta Z82 ; ENTRY record
|
|
iny
|
|
lda (XtnRecP),y
|
|
sta Z82+1
|
|
;
|
|
ldy #18
|
|
lda (Z82),y ;Get relocated addr fr ENTRY record
|
|
sta RelAdr ;lo
|
|
iny
|
|
lda (Z82),y
|
|
sta RelAdr+1 ;hi
|
|
;
|
|
bit FTypeF ;Is it OBJECT file relocatable?
|
|
bpl L3179 ;No, just ret
|
|
;
|
|
; The OBJECT file is of type REL
|
|
; We need to patch the curr RLD rec
|
|
;
|
|
ldy #0 ;Get flag byte fr
|
|
lda (SrcP),y ; RLD rec of src file
|
|
and #%11101111 ;Mark symbol is no
|
|
sta (SrcP),y ; longer EXTRN-type since
|
|
ldy #3 ; symbolicname is defined
|
|
and #%11000000
|
|
cmp #$40 ;lo 8 bits?
|
|
bne L3166 ;=>hi 8 bits
|
|
;
|
|
lda RelAdr ; Use lo 8-bits to patch
|
|
DB $2C
|
|
L3166 lda #0 ;Use 0 to patch
|
|
sta (SrcP),y ; the RLD record
|
|
jmp L3179 ;Done
|
|
;
|
|
; The symbolicname had not been defined
|
|
;
|
|
L316D bit FTypeF
|
|
bpl L3179
|
|
;
|
|
; If the target OBJECT file is REL then
|
|
; patch the RLD entry of the src file
|
|
; Once again we assume the RLD is < 5K
|
|
; since the patched RLD was written out only
|
|
; when processing of the src file is complete
|
|
;
|
|
ldy #7 ;Get the EXTRN # that
|
|
lda (XtnRecP),y ; was assigned by the Linker
|
|
ldy #3 ; & replace that in the RLD rec which
|
|
sta (SrcP),y ; was assigned by the Assembler
|
|
L3179 rts
|
|
REP 50
|
|
; Setup to open and write a TempRLD binary file
|
|
; Input
|
|
; Output
|
|
; Write2P+c.refNum - RN to write tempRLD file
|
|
;
|
|
OpTmpRLD EQU *
|
|
ldy TempRLD
|
|
L317D lda TempRLD,y
|
|
sta PathNameB,y
|
|
dey
|
|
bpl L317D
|
|
;
|
|
jsr PRODOS8 ;DESTROY
|
|
DB $C1
|
|
DW DestryP
|
|
lda #BINtype
|
|
sta CreateP+c.fileId
|
|
jsr PRODOS8 ;CREATE
|
|
DB $C0
|
|
DW CreateP
|
|
beq L319C
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L319C jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW Open2P
|
|
beq L31A7
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L31A7 lda Open2P+c.outRef
|
|
sta Write2P+c.refNum;write RN of tempRLD file
|
|
rts
|
|
REP 50
|
|
; Append patched RLD of curr src file to the tempRLD file
|
|
; Input
|
|
; Output
|
|
;
|
|
Add2TmpRLD EQU *
|
|
bit FTypeF ;Is OBJECT file of type REL?
|
|
bpl L31CC ;No
|
|
;
|
|
sec
|
|
lda SrcP
|
|
sbc #>SrcDBuf
|
|
sta Write2P+c.reqCnt;writelen
|
|
lda SrcP+1
|
|
sbc #<SrcDBuf
|
|
sta Write2P+c.reqCnt+1
|
|
;
|
|
; Write to tempRLD file
|
|
;
|
|
L31C1 EQU *
|
|
jsr PRODOS8 ;WRITE
|
|
DB $CB
|
|
DW Write2P
|
|
beq L31CC
|
|
jsr ErrHndlr ;Don't come back
|
|
L31CC rts
|
|
REP 50
|
|
; Open the LinkMap file and set the
|
|
; file posn to its EOF
|
|
;
|
|
; Input
|
|
; Output
|
|
;
|
|
L31CD EQU *
|
|
jsr MovMapFN ;Set PN to LinkMap
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW Open2P
|
|
beq L31DB
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L31DB lda Open2P+c.outRef
|
|
sta WrMapFP+c.refNum
|
|
sta GeofP+c.refNum
|
|
jsr PRODOS8 ;GET_EOF
|
|
DB $D1
|
|
DW GeofP
|
|
beq L31EF
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L31EF jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW GeofP ;Set to EO LinkMap file
|
|
beq L31FA
|
|
jsr ErrHndlr ;Don't come back
|
|
L31FA rts
|
|
REP 50
|
|
; Check if cmd line is Align Command/Directive
|
|
; Input
|
|
; Output
|
|
; Z=1 & C=0 - yes
|
|
;
|
|
IsALN EQU *
|
|
jsr DspLineB
|
|
jsr SkipSpcs
|
|
jsr ChkDrtv ;Check directive
|
|
bcs L3209 ;Unknown cmd
|
|
cmp #5 ;ALN directive
|
|
clc
|
|
L3209 rts
|
|
;=================================================
|
|
; ($320A) Load EDASM's Editor
|
|
;=================================================
|
|
LoadED EQU *
|
|
jsr PfxEdAsm ;Set prefix to EdAsm's dir
|
|
bcc LoadED2
|
|
lda #$FE
|
|
jsr PrtError
|
|
;
|
|
ldy #0
|
|
ldx EdAsmDir
|
|
PrtLoop lda EdAsmDir+1,y
|
|
jsr DspChar
|
|
iny
|
|
dex
|
|
bne PrtLoop
|
|
;
|
|
jsr DspCR
|
|
lda #$FD ;Output thru Interpreter's
|
|
jsr PrtError
|
|
;
|
|
KeyLoop lda KBD
|
|
bpl KeyLoop
|
|
bit KBDSTROBE ;Clear it
|
|
cmp #CR+$80
|
|
bne KeyLoop
|
|
jsr DspCR
|
|
jmp LoadED ;Try again
|
|
;
|
|
LoadED2 lda #>LoadAdrEd
|
|
sta EdLoadAdr
|
|
lda #<LoadAdrEd
|
|
sta EdLoadAdr+1
|
|
;
|
|
lda #>$2000
|
|
sta EdRdLen
|
|
lda #<$2000
|
|
sta EdRdLen+1
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW OpenEdP
|
|
beq Opened1
|
|
jsr FatalErr
|
|
;
|
|
Opened1 lda EdRefNbr
|
|
sta RdEdRefNbr
|
|
jsr PRODOS8 ;READ
|
|
DB $CA
|
|
DW RdEdP
|
|
beq Loaded1
|
|
jsr FatalErr
|
|
;
|
|
Loaded1 lda RdEdRefNbr
|
|
sta CloseP+c.refNum
|
|
jsr PRODOS8 ;CLOSE
|
|
DB $CC
|
|
DW CloseP
|
|
beq Closed1
|
|
jmp FatalErr
|
|
;
|
|
Closed1 jsr S2CurrPfx
|
|
bcs FatalErr
|
|
;=================================================
|
|
; Setup memory map for Editor/Command Interpreter
|
|
;=================================================
|
|
lda #%11111111 ;$FF
|
|
sta BitMap+20
|
|
lda #%00011111 ;$1F
|
|
sta BitMap+19
|
|
lda #%01111111 ;$7F
|
|
sta BitMap+22
|
|
lda #%10000001 ;$81
|
|
sta BitMap+23
|
|
;
|
|
; TxtBgn=$0801
|
|
;
|
|
lda #CR
|
|
dec TxtBgn ;Put a CR @ $0800
|
|
ldy #$00
|
|
sta (TxtBgn),y
|
|
inc TxtBgn ; and @ $0801
|
|
sta (TxtBgn),y
|
|
rts
|
|
;=================================================
|
|
FatalErr EQU *
|
|
sta $FE ;Save err code
|
|
tsx
|
|
stx $FF ;Save stack ptr
|
|
;
|
|
ldx #$80
|
|
txs
|
|
lda RDROM2 ;Read ROM; no write
|
|
jsr SETKBD ;reset input to keyboard
|
|
jsr SETVID ;reset output to screen
|
|
jsr HOME ;home cursor and clear screen
|
|
jsr PRERR ;print "ERR"
|
|
jmp MON ;std monitor entry w/beep
|
|
;=================================================
|
|
; Set prefix to EDASM's dir
|
|
;=================================================
|
|
PfxEdAsm EQU *
|
|
jsr PRODOS8 ;SET_PREFIX
|
|
DB $C6
|
|
DW EdAsmPfxP
|
|
rts
|
|
;=================================================
|
|
; Set prefix to current prefix
|
|
;=================================================
|
|
S2CurrPfx EQU *
|
|
jsr PRODOS8 ;SET_PREFIX
|
|
DB $C6
|
|
DW SCurrPfx
|
|
rts
|
|
;=================================================
|
|
; EDASM Editor's parameter blocks
|
|
;=================================================
|
|
EditorS STR 'EDASM.ED'
|
|
DB $00
|
|
;
|
|
OpenEdP DB $03
|
|
DW EditorS
|
|
DW XA900 ;1024-byte buffer
|
|
EdRefNbr DB $CB
|
|
;
|
|
RdEdP DB $04
|
|
RdEdRefNbr DB $D0
|
|
EdLoadAdr DW $A0A0
|
|
EdRdLen DW $A0D3 ;Caller must set this
|
|
DW $CBA0 ;actual len read
|
|
;
|
|
EdAsmPfxP DB $01
|
|
DW EdAsmDir
|
|
;
|
|
SCurrPfx DB $01
|
|
DW CurrPfxB
|
|
;=================================================
|
|
; Move a block of src code fr one mem location to
|
|
; another mem location (not including byte @
|
|
; location (Z80)
|
|
; Input
|
|
; SrcP - Start addr of data
|
|
; Z80 - End addr of data
|
|
; Z82 - Destination addr
|
|
; Output
|
|
; (Z82)
|
|
; (SrcP)
|
|
; (Y)=0
|
|
;
|
|
MovData EQU *
|
|
ldy #0
|
|
MovLoop3 lda (SrcP),y
|
|
sta (Z82),y
|
|
inc Z82
|
|
bne Bump2
|
|
inc Z82+1
|
|
Bump2 lda SrcP ;Copy until
|
|
cmp Z80
|
|
lda SrcP+1
|
|
sbc Z80+1 ; (Z80)=(SrcP)
|
|
inc SrcP
|
|
bne Bump3
|
|
inc SrcP+1
|
|
Bump3 bcc MovLoop3
|
|
rts
|
|
;=================================================
|
|
; This rtns adjust the ptrs to the next
|
|
; element of their respective arrays
|
|
;
|
|
IncrXtnP EQU *
|
|
pha ;Save
|
|
lda #8 ;rec size
|
|
ldx #XtnRecP ;EXTRN table
|
|
jmp IncRecP
|
|
;
|
|
IncrEntP EQU *
|
|
pha
|
|
lda #24
|
|
ldx #EntRecP ;ENTRY table
|
|
jmp IncRecP
|
|
;
|
|
IncrSymP EQU *
|
|
pha ;Save
|
|
lda #16
|
|
ldx #SymP ;SymbolicName table
|
|
;
|
|
; (A)=# to add to pointer stored in 2 consecutive mem locations
|
|
; (X)=offset into zero page
|
|
;
|
|
IncRecP EQU *
|
|
clc
|
|
adc $00,x
|
|
sta $00,x
|
|
lda #0
|
|
adc $01,x
|
|
sta $01,x
|
|
pla ;Restore
|
|
rts
|
|
REP 50
|
|
;
|
|
; Input
|
|
; (A)=# to add to pointer stored in 2 consecutive mem locations
|
|
; (X)=offset into zero page
|
|
; Output
|
|
; Same logic as above except (X) can be an index into
|
|
; ANY zeropage location
|
|
;
|
|
IncRecPZ pha
|
|
jmp IncRecP
|
|
REP 50
|
|
;
|
|
; Advance SrcP to next ESD record
|
|
; Input
|
|
; Output
|
|
; X - unchanged
|
|
;
|
|
NxtESDRec EQU *
|
|
ldy #0
|
|
BumpLoop lda (SrcP),y ;symbolicname
|
|
bpl GotLastCh ;Got last char
|
|
iny
|
|
jmp BumpLoop
|
|
;
|
|
GotLastCh iny
|
|
iny
|
|
iny
|
|
iny
|
|
tya
|
|
clc
|
|
adc SrcP ;SrcP now pointing @ next ESD
|
|
sta SrcP
|
|
lda #0
|
|
adc SrcP+1 ; record in the curr src file
|
|
sta SrcP+1
|
|
rts
|
|
;=================================================
|
|
; There are 3 entry points in this part of the code
|
|
; Input
|
|
; OpSrcFP+c.outRef - file ref # of src (REL) file
|
|
; Output
|
|
; C=0 - Last chunk of data had been read
|
|
; C=1 & (A)=$10 - Not EOF
|
|
; C=1 & (A)=$4C - EOF
|
|
; (SrcP) points to BO SrcDBuf
|
|
;=================================================
|
|
L3348 EQU *
|
|
lda OpSrcFP+c.outRef
|
|
sta RWFileP+c.refNum
|
|
;
|
|
; Use this entry point to attempt to read a fixed chunk
|
|
; of data (equal to the size of the data buffer) fr a
|
|
; ANY file into the beginning of the Data Buffer ($0C00)
|
|
; (SrcP) points to BO of this data buf (SrcDBuf)
|
|
;
|
|
L334E EQU *
|
|
lda #>SrcDBuf
|
|
sta RWFileP+c.dataBuf
|
|
lda #<SrcDBuf
|
|
sta RWFileP+c.dataBuf+1
|
|
;
|
|
lda #>FileDBSiz ;# of bytes to be read=5K
|
|
sta RWFileP+c.reqCnt
|
|
lda #<FileDBSiz
|
|
sta RWFileP+c.reqCnt+1
|
|
;
|
|
; Use this entry point to read a chunk of data fr ANY file.
|
|
; Caller must set the # of bytes to read (reqCnt) in
|
|
; RWFile parm block.
|
|
; (SrcP) is set to point to BO SrcDBuf ($0C00)
|
|
;
|
|
ReadCode EQU *
|
|
lda #>SrcDBuf
|
|
sta SrcP
|
|
lda #<SrcDBuf
|
|
sta SrcP+1
|
|
jsr PRODOS8 ;READ
|
|
DB $CA
|
|
DW RWFileP
|
|
bne ReadErrs ;If EOF, (A)=$4C and C=1
|
|
;
|
|
; After a successful read, at most NumRead = ReqLen
|
|
; For this case, there may be more data to be read
|
|
;
|
|
lda RWFileP+c.transCnt+1;If actual # of bytes read
|
|
cmp RWFileP+c.reqCnt+1; = requested len then
|
|
bne L3382 ; it may not be EOF since
|
|
lda RWFileP+c.transCnt
|
|
cmp RWFileP+c.reqCnt
|
|
beq L3384 ; there may be more data to be read
|
|
;
|
|
L3382 clc ;Not =, ==> last chunk of data read
|
|
rts ; since NumRead < ReqLen
|
|
L3384 lda #$10 ;= but not EOF, so use $10 to flag it
|
|
ReadErrs sec
|
|
rts
|
|
;=================================================
|
|
; Print Message
|
|
; The terminating char of each message in
|
|
; this table is a backslash
|
|
; Input
|
|
; Output
|
|
; (Y)=index into Message Table whose addresses
|
|
; are split into 2 sub-tables
|
|
;
|
|
DspMsg EQU *
|
|
lda MsgTLo,y
|
|
sta MsgP
|
|
lda MsgTHi,y
|
|
sta MsgP+1
|
|
ldy #0
|
|
DspLoop lda (MsgP),y
|
|
cmp #'\' ;terminator
|
|
beq DspMsgX
|
|
jsr CharOut
|
|
iny
|
|
jmp DspLoop
|
|
DspMsgX rts
|
|
;=================================================
|
|
; Setup the filename using a cmd line
|
|
; Input
|
|
; Output
|
|
;
|
|
GetSrcPN EQU *
|
|
ldy #-1
|
|
MovLoop4 iny
|
|
lda (cp),y
|
|
and #$7F
|
|
sta PathNameB+1,y
|
|
cmp #CR ;CR
|
|
bne MovLoop4
|
|
sty PathNameB ;len byte
|
|
rts
|
|
;=================================================
|
|
; Open a src file by getting its filename from
|
|
; the command file
|
|
; Get len of its code image and compute the
|
|
; addr past its last byte.
|
|
; Input
|
|
; Output
|
|
; C=1 - err
|
|
; (A)=err code
|
|
; (Z9E)=$80 - src file will be read but EXTRN records will
|
|
; not be created fr its ESD. Its code will not be included into
|
|
; the OBJECT file. ENTRY and SymbolicName records are created.
|
|
; This may be used to facilitate overlays rather than
|
|
; hand-patching JSR/JMP etc addresses
|
|
; Todo: Check it
|
|
; NB: SymbolicName records are created fr info in the
|
|
; appended ESD of all src files.
|
|
;
|
|
OpenSrc EQU *
|
|
ldy #0
|
|
sty Z9E
|
|
lda (cp),y
|
|
cmp #'*'
|
|
bne L33C8
|
|
inc cp ;Skip to next char
|
|
bne L33C4
|
|
inc cp+1
|
|
L33C4 lda #$80 ;Flag code from src file
|
|
sta Z9E ; will NOT be included in OBJ file
|
|
;
|
|
L33C8 jsr GetSrcPN ;First get the src file's name
|
|
jsr PRODOS8 ;OPEN
|
|
DB $C8
|
|
DW OpSrcFP
|
|
bne L341F
|
|
;
|
|
jsr PRODOS8 ;GET_FILE_INFO
|
|
DB $C4
|
|
DW GFISrcFP
|
|
bne L341F
|
|
;
|
|
lda #$11 ;Check filetype
|
|
ldy SrcType
|
|
cpy #RELtype
|
|
bne L341F ;filetype mismatch
|
|
;
|
|
lda OpSrcFP+c.outRef;Prepare to read 1st 2 bytes of this
|
|
sta RCodeLenP+c.refNum; file which is len of code image
|
|
jsr PRODOS8 ;READ
|
|
DB $CA
|
|
DW RCodeLenP
|
|
bne L341F
|
|
;
|
|
lda SrcCodeLen
|
|
clc
|
|
adc SrcORG ;Value of last ORG in this src file
|
|
sta L3806 ; Addr+1 of last byte of code image
|
|
lda SrcCodeLen+1
|
|
adc SrcORG+1
|
|
sta L3806+1
|
|
;
|
|
lda SrcORG ;Perform 2's complement of the
|
|
eor #$FF
|
|
sta NegSrcOrg ; the Last ORG adr of src file
|
|
lda SrcORG+1
|
|
eor #$FF
|
|
sta NegSrcOrg+1
|
|
inc NegSrcOrg
|
|
bne L341D
|
|
inc NegSrcOrg+1
|
|
L341D clc
|
|
rts
|
|
L341F sec
|
|
rts
|
|
REP 50
|
|
; ($3421) Read in a line of text from command file
|
|
; See description below
|
|
;
|
|
Read1Cmd EQU *
|
|
jsr PRODOS8 ;READ
|
|
DB $CA
|
|
DW RdCmdFP
|
|
beq L3446
|
|
;
|
|
cmp #$4C ;Is it EOF?
|
|
beq L3430 ;Yes
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L3430 jsr L343B ;Reset file posn to BO src file
|
|
lda #CR ;Store CR @ BO buffer to
|
|
sta CmdLineB ; denote an empty (blank) line
|
|
jmp L3446 ;Set cp to point @ cmd line buf
|
|
REP 50
|
|
; ($343B) Reset file position to BO of command file
|
|
; Output
|
|
; cp - ptr to 1st char of Cmd Line
|
|
; (A) - 1st char
|
|
; Z=1 - 1st char is CR/SPACE
|
|
; Z=0 - Otherwise
|
|
;
|
|
L343B EQU *
|
|
jsr PRODOS8 ;SET_MARK
|
|
DB $CE
|
|
DW SMCmdFP
|
|
beq L3446
|
|
jsr ErrHndlr ;Don't come back
|
|
;
|
|
L3446 EQU *
|
|
lda #>CmdLineB
|
|
sta cp
|
|
lda #<CmdLineB
|
|
sta cp+1
|
|
;
|
|
ldy #0
|
|
lda (cp),y ;Get 1st char of cmd line
|
|
cmp #SPACE
|
|
beq L3458
|
|
cmp #CR ;Z=1
|
|
L3458 rts
|
|
;=================================================
|
|
; ($3459)
|
|
; Input
|
|
; (A)=file ref #
|
|
; Output
|
|
;
|
|
ClsFile EQU *
|
|
sta CloseP+c.refNum
|
|
jsr PRODOS8 ;CLOSE
|
|
DB $CC
|
|
DW CloseP
|
|
beq L3467
|
|
jsr ErrHndlr ;Don't come back
|
|
L3467 rts
|
|
REP 50
|
|
; Display contents of Command Line Buffer
|
|
; Input
|
|
; cp - ptr to the cmdline buf
|
|
; (A) & (P) are preserved
|
|
;
|
|
DspLineB EQU *
|
|
php ;Save Status reg
|
|
pha ;Save char
|
|
lda #SPACE
|
|
jsr CharOut
|
|
jsr CharOut
|
|
jsr CharOut
|
|
jsr CharOut
|
|
jsr CharOut
|
|
;
|
|
ldy #0
|
|
DspLoop2 lda (cp),y
|
|
and #$7F
|
|
jsr CharOut
|
|
iny
|
|
cmp #CR ;If not terminating cr,
|
|
bne DspLoop2 ; get next char
|
|
pla
|
|
plp
|
|
rts
|
|
;=================================================
|
|
; Parse directive field
|
|
; Input
|
|
; cp - pointing @ 1st char of cmdline's
|
|
; directive field
|
|
; Output
|
|
; C=0, (A)-index into JMP table
|
|
; C=1 - Unknown command
|
|
;=================================================
|
|
ChkDrtv EQU *
|
|
ldx #-1
|
|
NxtDrtv ldy #0
|
|
CmpLoop2 inx
|
|
lda DirectvT,x
|
|
beq CmdError ;EOT
|
|
lda (cp),y
|
|
cmp DirectvT,x
|
|
beq Bump5 ;Got a match
|
|
cpy #3 ;Did we have a 3-char match?
|
|
bne SkipEntry ;No, try next entry
|
|
cmp #CR ;EO cmd line?
|
|
beq GotEntry ;Yes
|
|
Bump5 iny ;Bump index to next char
|
|
cpy #4
|
|
bcc CmpLoop2
|
|
beq GotEntry ;All chars match including trailing space
|
|
;
|
|
SkipEntry cpy #3
|
|
beq NxtDrtv ;Loop back to check another entry
|
|
inx
|
|
iny
|
|
bne SkipEntry ;Skip rest of entry
|
|
;
|
|
CmdError ldy #$1B ;Unknown cmd
|
|
jsr DspMsg
|
|
sec
|
|
rts
|
|
;
|
|
GotEntry txa ;Compute index
|
|
lsr a
|
|
lsr a
|
|
clc
|
|
rts
|
|
;=================================================
|
|
; Start fr beginning of Cmd Line, skip blanks
|
|
; Output
|
|
; Z=1 - CR/SPACE
|
|
;
|
|
SkipSpcs EQU *
|
|
ldy #0
|
|
SkipLoop2 lda (cp),y
|
|
cmp #SPACE
|
|
bne AdvCP
|
|
iny
|
|
bne SkipLoop2
|
|
;
|
|
; In case we can't find a non-blank, fall
|
|
; thru to start searching fr the 2nd char
|
|
; Output
|
|
; (Y) - indexing the 1st non-blank
|
|
; (A) - non-blank char
|
|
;
|
|
WhiteSpc EQU *
|
|
ldy #0
|
|
EatLoop iny
|
|
lda (cp),y
|
|
cmp #SPACE
|
|
beq L34D8
|
|
cmp #CR
|
|
bne EatLoop
|
|
L34D8 rts ;Z=1 if CR/SPACE
|
|
;
|
|
; Advance cmd line buffer pointer (cp)
|
|
; Input
|
|
; (Y) - # of chars to advance
|
|
; Output
|
|
; (Y) = 0
|
|
;
|
|
AdvCP EQU *
|
|
tya
|
|
clc
|
|
adc cp
|
|
sta cp
|
|
bcc Bump4
|
|
inc cp+1
|
|
Bump4 ldy #0
|
|
rts
|
|
REP 50
|
|
;
|
|
; These rtns transfer control
|
|
; the monitor's I/O handlers
|
|
;
|
|
GetLine bit RDROM2 ;Read ROM; no write
|
|
jmp GETLN ;Input line w/prompt
|
|
;
|
|
DspCR bit RDROM2 ;Read ROM; no write
|
|
jmp CROUT ;Issue a carriage return
|
|
;
|
|
DspChar bit RDROM2 ;Read ROM; no write
|
|
jmp COUT ;As set by user
|
|
;=================================================
|
|
; Input
|
|
; (A)=char to display
|
|
; Preserved
|
|
; (A)
|
|
;
|
|
CharOut EQU *
|
|
pha ;Save char
|
|
cmp #'a'
|
|
bcc CharOut1
|
|
cmp #'z'+1
|
|
bcs CharOut1
|
|
and #$DF ;to uppercase
|
|
;
|
|
CharOut1 ora #$80 ;msb on
|
|
jsr DspChar ;Calls actual output rtn
|
|
pla
|
|
pha
|
|
cmp #CR
|
|
bne CharOut2
|
|
jsr PollKbd
|
|
CharOut2 pla
|
|
rts
|
|
REP 50
|
|
; ($3513) Evaluate operand field
|
|
; No fancy stuff
|
|
;
|
|
EvalExpr EQU *
|
|
ldy #0
|
|
sty Value16 ;Zero the value
|
|
sty Value16+1
|
|
dey ;=-1
|
|
jsr ChrGet ;Incr Y b4 getting char fr buf
|
|
cmp #'$'
|
|
bne Dec2Int ;Decimal str
|
|
;
|
|
; Convert str representing a hexdec
|
|
; value into an integer
|
|
;
|
|
Hex2Int jsr ChrGet
|
|
beq L3532 ;cr/space
|
|
jsr IsHexChar ;Is char hexdec?
|
|
bcs SynErr1 ;No
|
|
jsr ShiftHex ;Accomodate the incoming digit
|
|
bcc Hex2Int ;Process next char
|
|
bcs SynErr1
|
|
L3532 rts
|
|
; Not referenced
|
|
pla ;what's this?
|
|
;
|
|
SynErr1 jsr CmdSynErr ;Syntax err
|
|
REP 50
|
|
; ($3537) Convert string representing a
|
|
; decimal value to an integer
|
|
; Input
|
|
; Output
|
|
;
|
|
Dec2Int EQU *
|
|
dey
|
|
CnvLoop2 jsr ChrGet
|
|
beq L3532 ;If cr/space, ret
|
|
jsr IsDecChar ;Is it numeric?
|
|
bcs SynErr1 ;No, err
|
|
jsr ShiftDec ;Accomodate the incoming digit
|
|
bcc CnvLoop2 ;Get next char
|
|
bcs SynErr1
|
|
;
|
|
ShiftDec jsr Mul2
|
|
bcs OvrFlow3 ;Overflow
|
|
lda Value16+1
|
|
pha
|
|
lda Value16
|
|
jsr Mul2
|
|
bcs OvrFlow1 ;Overflow
|
|
jsr Mul2
|
|
bcs OvrFlow1 ;Overflow
|
|
adc Value16
|
|
sta Value16
|
|
pla
|
|
adc Value16+1
|
|
sta Value16+1
|
|
bcs OvrFlow3 ;Overflow
|
|
;
|
|
jsr ChrGot
|
|
sec
|
|
sbc #'0'
|
|
clc
|
|
adc Value16
|
|
sta Value16
|
|
bcc OvrFlow3
|
|
inc Value16+1
|
|
beq OvrFlow2 ;Overflow
|
|
clc
|
|
rts
|
|
;
|
|
OvrFlow1 pla
|
|
OvrFlow2 sec
|
|
OvrFlow3 rts
|
|
;
|
|
Mul2 asl Value16
|
|
rol Value16+1
|
|
rts
|
|
;=================================================
|
|
; Shift in the hex value into running value
|
|
; Input
|
|
; (A) = '0'-'9' or $3A-$3F
|
|
; Output
|
|
; (Value) = running hex value
|
|
;=================================================
|
|
ShiftHex EQU *
|
|
sec
|
|
sbc #'0' ;$00-$0F
|
|
asl a
|
|
asl a
|
|
asl a
|
|
asl a
|
|
;
|
|
ldx #4
|
|
RotLoop asl a
|
|
rol Value16
|
|
rol Value16+1
|
|
dex
|
|
bne RotLoop
|
|
rts
|
|
;=================================================
|
|
; ($3595) This rtn has 2 entry points
|
|
; Input
|
|
; cp = ptr into cmd line buffer
|
|
; Output
|
|
; Z=1 - char is space or cr
|
|
; (A) - char (converted to uppercase)
|
|
;=================================================
|
|
ChrGet EQU *
|
|
iny ;Bump index first
|
|
ChrGot EQU *
|
|
lda (cp),y
|
|
and #$7F ;Strip msb of char
|
|
cmp #'a'
|
|
bcc AsIs ;Don't convert to ucase
|
|
and #$DF ;ucase
|
|
AsIs cmp #SPACE
|
|
beq L35A6
|
|
cmp #CR
|
|
L35A6 rts
|
|
;=================================================
|
|
; Is char btwn '0'-'9'
|
|
; Input
|
|
; Output
|
|
; C=0 yes
|
|
;=================================================
|
|
IsDecChar EQU *
|
|
cmp #'9'+1
|
|
bcs NotHex
|
|
cmp #'0'
|
|
bcc NotHex
|
|
clc
|
|
rts
|
|
NotHex sec
|
|
rts
|
|
;=================================================
|
|
; Check for hexdec char '0'-'9' and 'A'-'F'
|
|
; If char is 'A'-'F', convert to a value
|
|
; btwn $3A-$3F and return with C=0
|
|
; Input
|
|
; Output
|
|
;=================================================
|
|
IsHexChar EQU *
|
|
cmp #'A'
|
|
bcc IsDecChar ;chk for numeric char
|
|
cmp #'F'
|
|
bcs NotHex
|
|
sbc #$06 ;$3A-$3F
|
|
clc
|
|
rts
|
|
;=================================================
|
|
; Check for a keypress
|
|
; Ctrl-C - Abort of linking process
|
|
; spacebar - Pause
|
|
;
|
|
PollKbd EQU *
|
|
lda KBD
|
|
bpl L35E1
|
|
bit KBDSTROBE ;turn off keypressed flag
|
|
cmp #CTRLC+$80
|
|
bne IsSpcBar
|
|
;
|
|
ldy #$1C ;abort
|
|
jsr DspMsg
|
|
ldy #$1C
|
|
jsr StorMsg
|
|
jmp DoBreak
|
|
;
|
|
IsSpcBar cmp #SPACE+$80 ;Is space bar depressed?
|
|
bne L35E1
|
|
WaitZ lda KBD ;Yes
|
|
bpl WaitZ ;Wait for any keypress
|
|
L35E1 rts
|
|
;=================================================
|
|
; Output thru EdAsm Interpreter Print Error rtn
|
|
; Don't return to the caller
|
|
; Input
|
|
; (A) - error code
|
|
;
|
|
ErrHndlr jsr PrtError
|
|
jmp DoBreak
|
|
;=================================================
|
|
DupCmdErr ldy #$10
|
|
jmp GoShowMsg
|
|
;
|
|
OptnErr ldy #$0F
|
|
jmp GoShowMsg
|
|
;
|
|
CmdFileErr ldy #$0E
|
|
jmp GoShowMsg
|
|
;
|
|
CmdOrderErr ldy #$02
|
|
jmp GoShowMsg
|
|
;
|
|
UnknownCmdErr ldy #$1B
|
|
jmp GoShowMsg
|
|
;
|
|
RldEsdErr ldy #$11
|
|
jmp GoShowMsg
|
|
;
|
|
ExtrnErr ldy #$17 ;>255 EXTRN's
|
|
jmp GoShowMsg
|
|
;
|
|
CmdSynErr ldy #$01
|
|
GoShowMsgZ jmp GoShowMsg
|
|
;
|
|
GoShowMsg jsr DspMsg
|
|
;
|
|
; All errors above will come here
|
|
; Close all files. Check for a ctrl-B
|
|
; If so, exit to monitor else re-load EdAsm.ED
|
|
; & transfer control to the editor
|
|
; ($3613)
|
|
; Input
|
|
; Output
|
|
;
|
|
DoBreak EQU *
|
|
lda CMDADR ;last MLI call return address
|
|
pha
|
|
lda CMDADR+1
|
|
pha
|
|
;
|
|
lda #$01
|
|
sta ClsAllP
|
|
lda #$00
|
|
sta ClsAllP+c.refNum
|
|
jsr PRODOS8 ;CLOSE
|
|
DB $CC
|
|
DW ClsAllP
|
|
;
|
|
pla
|
|
sta CMDADR+1
|
|
pla
|
|
sta CMDADR ;last MLI call return address
|
|
;
|
|
bit KBDSTROBE ;turn off keypressed flag
|
|
bit RDROM2 ;Read ROM; no write
|
|
jsr RDKEY ;Input char with cursor
|
|
cmp #CTRLB+$80
|
|
bne Abort
|
|
;
|
|
tsx
|
|
stx StackP
|
|
ldx #$80
|
|
txs
|
|
lda ROMIN2 ;read ROM/write LCbank2 (RR)
|
|
lda ROMIN2
|
|
jmp MON ;std monitor entry w/beep
|
|
;
|
|
Abort jsr SetupED ;Proceed to load & xfer control to EdAsm.Ed
|
|
jmp USRADR ;ctl-Y vector
|
|
;=================================================
|
|
; Put everything back in order
|
|
; Input
|
|
; Output
|
|
; Currently EI's ctrl-Y vector points @ $B198
|
|
; If exec mode is on, the entry is modified to
|
|
; $B1AB
|
|
;
|
|
;=================================================
|
|
DoExit EQU *
|
|
lda OpCmdFP+c.outRef
|
|
jsr ClsFile ;Close the command file
|
|
jsr SetupED
|
|
bit ExecMode ;Was cmd file EXEC fr Editor?
|
|
bmi L3665 ;Yes (Qn: how to do this since we have to enter MON)
|
|
jmp USRADR ;Exit via ctl-Y vector
|
|
;
|
|
L3665 clc
|
|
lda USRADR+1 ;ctl-Y vector
|
|
adc #$13 ;$B1AB-$B198
|
|
sta L367F+1 ;Self-modifying code
|
|
lda USRADR+2
|
|
adc #$00
|
|
sta L367F+2
|
|
bit ROMIN2 ;read ROM/write LCbank2 (RR)
|
|
bit ROMIN2
|
|
ldx #$F8
|
|
txs
|
|
L367F jmp USRADR ;ctl-Y vector
|
|
REP 50
|
|
; Input
|
|
; Output
|
|
; Load EDASM's Editor
|
|
;
|
|
SetupED EQU *
|
|
jsr LoadED ;Load EDASM.ED
|
|
lda #%01111111 ;$7F
|
|
sta BitMap+22 ;P8 memory bitmap
|
|
lda #%10000001 ;$81
|
|
sta BitMap+23 ;P8 memory bitmap
|
|
lda TxtBgn ;No file in mem
|
|
sta TxtEnd
|
|
lda TxtBgn+1
|
|
sta TxtEnd+1
|
|
rts
|
|
REP 50
|
|
;
|
|
; Phase 1 use 2 bytes of this table. However, the
|
|
; locations accessed should be $3698 and $369A
|
|
; & not $3697 and $3699. The bytes should be
|
|
; addr hi of the EXTRN & ENTRY tables
|
|
;
|
|
L3698 DB $71 ;ENTRY table must be < $7100
|
|
DB $00
|
|
DB $91 ;EXTRN table must be < $9100
|
|
;
|
|
BitsT DB $80,$40,$20,$10,$08,$04,$02,$01
|
|
;
|
|
; Default filenames of workfiles
|
|
;
|
|
AutoLnkS STR 'EDASM.AUTOLINK'
|
|
DB $00
|
|
TempESD STR 'EDASM.TEMPESD'
|
|
DB $00
|
|
TempRLD STR 'EDASM.TEMPRLD'
|
|
DB $00
|
|
;=================================================
|
|
DirectvT EQU *
|
|
ASC 'BIN '
|
|
ASC 'REL '
|
|
ASC 'SYS '
|
|
ASC 'ORG '
|
|
ASC 'OPT '
|
|
ASC 'ALN '
|
|
DB $00 ;Marks end of table
|
|
;
|
|
; JMP table
|
|
;
|
|
L36EA DB >CmdBin-1 ;Lo
|
|
DB >CmdRel-1
|
|
DB >CmdSys-1
|
|
DB >CmdOrg-1
|
|
DB >CmdOptn-1
|
|
DB >CmdAln-1
|
|
;
|
|
L36F0 DB <CmdBin-1 ;Hi
|
|
DB <CmdRel-1
|
|
DB <CmdSys-1
|
|
DB <CmdOrg-1
|
|
DB <CmdOptn-1
|
|
DB <CmdAln-1
|
|
;=================================================
|
|
OptionsT ASC 'MESXNDP'
|
|
DB $00
|
|
;
|
|
LinkObjS STR 'EDASM.LINKOBJ' ;65-byte buffer for pathname
|
|
DS $33,0 ;51
|
|
;
|
|
LinkMapS STR 'EDASM.LINKMAP' ;65-byte buffer for pathname
|
|
DS $33,0 ;51
|
|
;
|
|
CmdLineB DS 128,SPACE ;Command Line Buffers
|
|
;
|
|
Origin DW $A0B0 ;Set by cmd/AuxType of 1st src file
|
|
SrcCodeLen DW $A0A0 ;len of code image of src file
|
|
NegSrcOrg DW $A0CC ;2's complement of src ORiGin
|
|
L3806 DW $A0BE ;Addr+1 of code image
|
|
RelAdr DW $A0FF ;Relocated Adr
|
|
;
|
|
; 3-byte work area for ESD records
|
|
; The layout of this work area
|
|
; offset Meaning
|
|
; 0 DB symbol flag's byte
|
|
; If ENTRY
|
|
; 1 DW offset fr BO code image
|
|
; If EXTRN
|
|
; 1 DB symbol number referred to by RLD record
|
|
; 2 DB 0
|
|
;
|
|
ESDRec DB $A0
|
|
DB $A0
|
|
DB $FE
|
|
;
|
|
RLDFlags DB $A0 ;RLD flag-byte
|
|
;
|
|
ModNbr DB $A0 ;source file count/Module Number
|
|
L380F DB $A0 ;Counter
|
|
TrgtFTyp DB $00 ;OBJECT filetype
|
|
;
|
|
; Table of ptrs to BO 1st EXTRN rec of each src file
|
|
;
|
|
SrcModTLo DS 50,0
|
|
SrcModTHi DS 50,0
|
|
;
|
|
; Posn counter of beginning of code image (ORG ADRS)
|
|
; within the OBJECT file for src file module #s 0-49
|
|
;
|
|
OrgAdrLo DS 50,0
|
|
OrgAdrHi DS 50,0
|
|
;
|
|
; Posn counter of end of code image (END ADRS) within
|
|
; the OBJECT file for src file module #s 0-49
|
|
;
|
|
EndAdrLo DS 50,0
|
|
EndAdrHi DS 50,0
|
|
;=================================================
|
|
; ($393D) General purpose pathname work area
|
|
; Set this b4 opening a disk file
|
|
;
|
|
PathNameB DS 64,0 ;Should be 65!
|
|
;
|
|
MapFDB DS 90,SPACE ;data buf for LinkMap
|
|
;
|
|
SymLen DB $A0 ;temp store for len of symbolicname
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to open source file(s)
|
|
;
|
|
OpSrcFP DB $03
|
|
DW PathNameB
|
|
DW SrcIOAdr ;1024-byte buf for ProDOS
|
|
DB $00
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ProDOS parameter blocks for Command File which
|
|
; is a TXT file. Each text line is terminated by a CR
|
|
;
|
|
OpCmdFP DB $03 ;OPEN
|
|
DW PathNameB ;PathName
|
|
DW XA900 ;1024-byte buf
|
|
DB $00
|
|
;
|
|
RdCmdFP DB $04 ;READ
|
|
DB $00
|
|
DW CmdLineB
|
|
DW 128 ;At most 128 chars/line
|
|
DW 0 ;# actual read (not referenced)
|
|
;
|
|
NLCmdFP DB $03 ;NEWLINE
|
|
DB $00
|
|
DB $7F ;AND mask=ignore msb i.e. both $0D/$8D are accepted
|
|
DB CR ;newline char
|
|
;
|
|
; ($39F0) Use to set file posn to beginning of Command File
|
|
;
|
|
SMCmdFP DB $02 ;SETMARK
|
|
DB $00
|
|
DS 3,0 ;This doesn't get changed
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Used to destroy
|
|
; 1) old LinkMap
|
|
; 2) old tempESD
|
|
; 3) old OBJECT file (if any)
|
|
; 4) old tempRLD
|
|
; PathNameB must be filled w/the filename
|
|
;
|
|
DestryP DB $01
|
|
DW PathNameB
|
|
;
|
|
CloseP DB $01 ;Use by anybody
|
|
DB $00
|
|
;
|
|
ClsAllP DB $01
|
|
DB $00
|
|
;
|
|
; Not used
|
|
;
|
|
L39FC DB $04 ;whats this?
|
|
DB $00
|
|
DB $00
|
|
DB $00
|
|
DB $00
|
|
DB $00
|
|
DB $00
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Used to get File Info of a source (REL) file
|
|
;
|
|
GFISrcFP DB 10
|
|
DW PathNameB
|
|
DB 0
|
|
SrcType DB 0
|
|
SrcORG DW 0 ;auxtype
|
|
DB 0
|
|
DW 0
|
|
DW 0
|
|
DW 0
|
|
DW 0
|
|
DW 0
|
|
;
|
|
; Used to set the file position of a src file
|
|
;
|
|
SMSrcFP DB $02 ;SETMARK
|
|
DB $00
|
|
DS 3,0 ;Caller must set this
|
|
;
|
|
; Used to read the first 2 bytes of src file
|
|
; which is the length of its code image
|
|
;
|
|
RCodeLenP DB $04
|
|
DB $00
|
|
DW SrcCodeLen ;SrcCodeLen (2-byte data buf)
|
|
DW $0002 ;# of bytes to be read
|
|
DW $A080 ;actual # read (unused)
|
|
;
|
|
; ($3A22) For reading SRC, tempRLD, tempESD
|
|
; For appending to OBJECT file
|
|
;
|
|
RWFileP DB $04
|
|
DB $00
|
|
DW SrcDBuf ;data buf
|
|
DW 0 ;Set this b4 calling PRODOS
|
|
DW 0 ;actual # of bytes read
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to open a 1) tempESD 2) OBJECT file
|
|
;
|
|
Open3P DB $03 ;OPEN
|
|
DW PathNameB
|
|
DW X3F00 ;1024-byte buf for PRODOS
|
|
DB 0
|
|
;
|
|
; Use to write 1) TempESD 2) OBJECT files
|
|
;
|
|
Write1P DB $04 ;WRITE
|
|
DB 0
|
|
DW X9100 ;Data Buf
|
|
DW $A0A0 ;write len
|
|
DW $B1A0 ;Actually written
|
|
;
|
|
; Read one page of code img of current src file
|
|
;
|
|
RdCodeImgP DB $04 ;READ
|
|
DB 0
|
|
DW X9100 ;Data Buf
|
|
DW $0000
|
|
DW $A0D5
|
|
;
|
|
; Use to create BIN/REL/SYS OBJECT files
|
|
; Also use to create TempESD/TempRLD binary files
|
|
; The filetype & auxtype must be set first
|
|
;
|
|
CreateP DB 7 ;CREATE
|
|
DW PathNameB
|
|
DB $E3 ;full access
|
|
DB $00 ;filetype
|
|
DW $0000 ;auxtype
|
|
DB $01 ;seedling
|
|
DW 0
|
|
DW 0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Used to open 1) LinkMap text file
|
|
; 2) tempRLD 3) tempESD BIN file
|
|
;
|
|
Open2P DB $03
|
|
DW PathNameB
|
|
DW X4300 ;1024-byte buf
|
|
DB $00
|
|
;
|
|
; Use to create LinkMap text file
|
|
;
|
|
CrLnkMapP DB 7
|
|
DW PathNameB
|
|
DB $E3
|
|
DB TXTtype
|
|
DW 0
|
|
DB $01 ;storage type
|
|
DW 0
|
|
DW 0
|
|
;=================================================
|
|
; Use to write the LinkMap text file
|
|
; WrMapFIdx doubles as # of bytes to write
|
|
; besides being used as an index to store the
|
|
; chars into the Map File's Data Buf (MapFDB)
|
|
;
|
|
WrMapFP DB $04 ;WRITE
|
|
DB $00
|
|
DW MapFDB ;data buf addr
|
|
WrMapFIdx DW $A0C3 ;at most 128 bytes (hi-byte=0)
|
|
DW $A080
|
|
;=================================================
|
|
; Use to
|
|
; 1) get eof of LinkMap file, then
|
|
; 2) set to file posn to its EOF
|
|
;
|
|
GeofP DB $02 ;GET_EOF/SETMARK
|
|
DB $00
|
|
DS 3,0
|
|
;
|
|
; Use to write 1) TempRLD 2) TempESD files
|
|
;
|
|
Write2P DB $04 ;WRITE
|
|
DB $00
|
|
DW SrcDBuf ;source data buffer
|
|
DW 0 ;# of bytes to write
|
|
DW $A0A0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Use to move file posn to beginning
|
|
; 1) of the tempRLD file
|
|
; 2) OBJECT file
|
|
;
|
|
SMarkP DB $02 ;SETMARK
|
|
DB $00
|
|
DS 3,0 ;Not changed
|
|
;=================================================
|
|
; Message pointers sub-tables
|
|
;
|
|
MsgTLo DB >L3ADE
|
|
DB >L3B02
|
|
DB >L3B1F
|
|
DB >L3BB7
|
|
DB >L3BDD
|
|
DB >L3BFF
|
|
DB >L3C1E
|
|
DB >L3C3F
|
|
DB >L3C63
|
|
DB >L3C83
|
|
DB >L3CA0
|
|
DB >L3CB7
|
|
DB >L3CCF
|
|
DB >L3CEB
|
|
DB >L3B55
|
|
DB >L3B7B
|
|
DB >L3BA0
|
|
DB >L3D06
|
|
DB >L3D22
|
|
DB >L3D3F
|
|
DB >L3D4B
|
|
DB >L3D58
|
|
DB >L3D8D
|
|
DB >L3D9A
|
|
DB >L3DBE
|
|
DB >L3DD6
|
|
DB >L3DEE
|
|
DB >L3B3A
|
|
DB >L3AB4
|
|
DB >L3D75
|
|
;
|
|
MsgTHi DB <L3ADE ;0
|
|
DB <L3B02 ;1
|
|
DB <L3B1F ;2
|
|
DB <L3BB7 ;3
|
|
DB <L3BDD ;4
|
|
DB <L3BFF ;5
|
|
DB <L3C1E ;6
|
|
DB <L3C3F ;7
|
|
DB <L3C63 ;8
|
|
DB <L3C83 ;9
|
|
DB <L3CA0 ;10
|
|
DB <L3CB7 ;11
|
|
DB <L3CCF ;12
|
|
DB <L3CEB ;13
|
|
DB <L3B55 ;14
|
|
DB <L3B7B ;15
|
|
DB <L3BA0 ;16
|
|
DB <L3D06 ;17
|
|
DB <L3D22 ;18
|
|
DB <L3D3F ;19
|
|
DB <L3D4B ;20
|
|
DB <L3D58 ;21
|
|
DB <L3D8D ;22
|
|
DB <L3D9A ;23
|
|
DB <L3DBE ;24
|
|
DB <L3DD6 ;25
|
|
DB <L3DEE ;26
|
|
DB <L3B3A ;27
|
|
DB <L3AB4 ;28
|
|
DB <L3D75 ;29
|
|
;
|
|
; Messages starts here
|
|
;
|
|
L3AB4 ASC 'LINKER ABORTED'
|
|
DB CR
|
|
ASC 'PRESS RETURN TO CONTINUE\'
|
|
DB CR
|
|
ASC '\'
|
|
L3ADE ASC 'ProDOS Linker 1.0'
|
|
DB CR,CR
|
|
ASC 'Command Filename'
|
|
ASC '\' ;end of msg
|
|
L3B02 ASC 'ERR: Syntax error in command'
|
|
ASC '\'
|
|
L3B1F ASC 'ERR: Invalid Command order'
|
|
ASC '\'
|
|
L3B3A ASC 'ERR: Unknown command found'
|
|
ASC '\'
|
|
L3B55 ASC 'ERR: Empty or incomplete command'
|
|
ASC ' file'
|
|
ASC '\'
|
|
L3B7B ASC 'ERR: Invalid option or option syntax'
|
|
ASC '\'
|
|
L3BA0 ASC 'ERR: Duplicate command'
|
|
ASC '\'
|
|
L3BB7 ASC 'Phase 0 : Commands & Options Selected'
|
|
ASC '\'
|
|
L3BDD ASC 'Phase 1 : Building DEF/REF tables'
|
|
ASC '\'
|
|
L3BFF ASC 'Phase 2 : Resolving REF-EXTRNs'
|
|
ASC '\'
|
|
L3C1E ASC 'Phase 3 : Relocating Object code'
|
|
ASC '\'
|
|
L3C3F ASC 'Phase 4 : Generating Object RLD-ESD'
|
|
ASC '\'
|
|
L3C63 ASC 'Phase 5 : Sorting loadmap index'
|
|
ASC '\'
|
|
L3C83 ASC 'Phase 6 : Generating loadmap'
|
|
ASC '\'
|
|
L3CA0 ASC 'ERR: Symbol table full'
|
|
ASC '\'
|
|
L3CB7 ASC 'ERR: Too many REL files'
|
|
ASC '\'
|
|
L3CCF ASC 'ERR: File is not a REL file'
|
|
ASC '\'
|
|
L3CEB ASC 'ERR: REL file is too large'
|
|
ASC '\'
|
|
L3D06 ASC 'ERR: REL file ESD too large'
|
|
ASC '\'
|
|
L3D22 ASC 'Duplicate DEF-ENTRY symbol, '
|
|
ASC '\'
|
|
L3D3F ASC 'of module #'
|
|
ASC '\'
|
|
L3D4B ASC ' in module #'
|
|
ASC '\'
|
|
L3D58 ASC 'Undefined REF-EXTRN symbol, '
|
|
ASC '\'
|
|
L3D75 ASC 'REF-DEF SIZE mismatch, '
|
|
ASC '\'
|
|
L3D8D ASC 'UNREFERENCED'
|
|
ASC '\'
|
|
L3D9A ASC |ERR: >255 EXTRN's in REL output ESD|
|
|
ASC '\'
|
|
L3DBE ASC 'MOD ORG END MODULE'
|
|
DB CR
|
|
ASC '\'
|
|
L3DD6 ASC ' # ADRS ADRS NAME '
|
|
DB CR
|
|
ASC '\'
|
|
L3DEE ASC ' ADRS M# SYMBOL MODULE'
|
|
ASC ' X-REF LIST '
|
|
ASC ' PAGE '
|
|
ASC '\'
|
|
ASC '14-MAR-84'
|
|
ASC '23:42 '
|
|
;
|
|
FileDBSiz EQU AsmLinker-SrcDBuf;20 mempages=5K
|