mirror of https://github.com/dschmenk/VM02.git
833 lines
18 KiB
Plaintext
Executable File
833 lines
18 KiB
Plaintext
Executable File
CONST FALSE = 0
|
|
CONST TRUE = NOT FALSE
|
|
CONST OK = 0
|
|
CONST ERROR = -1
|
|
CONST INPUTSTR = $01FF
|
|
CONST INBUFF = $0800
|
|
CONST OUTBUFF = $0C00
|
|
CONST SYMTABLE = $1000
|
|
CONST SYMSIZE = $1000
|
|
CONST MODFILES = $7F00
|
|
CONST DATABUFF = $8000
|
|
WORD NEXTENTRY = SYMTABLE
|
|
BYTE PLASMASTR[] = "PLASMA LINKER 0.8"
|
|
BYTE NULLSTR[] = ""
|
|
BYTE BADMODSTR[] = "MODULE NOT FOUND"
|
|
BYTE ASMADR[] = "ASM ADDRESS: $"
|
|
BYTE LOADADR[] = "LOAD ADDRESS: $"
|
|
BYTE DATASZ[] = "DATA SIZE: $"
|
|
BYTE RELOFSTSTR[] = "REL OFFSET: $"
|
|
BYTE FIX16STR[] = "FIXUP 16-BIT ADDRESS: $"
|
|
BYTE FIX8STR[] = "FIXUP 8-BIT ADDRESS: $"
|
|
BYTE RLDLBL[] = "RELOCATION DIRECTORY:"
|
|
BYTE ESDLBL[] = "SYMBOL TABLE:"
|
|
BYTE MATCHEXTRNSTR = "MATCH EXTRN: "
|
|
BYTE INPUTFILESTR = "INPUT FILE"
|
|
BYTE OUTPUTFILESTR = "OUTPUT FILE"
|
|
BYTE BADEXT[] = "UNRESOLVED EXTERNAL SYMBOL: "
|
|
BYTE DUPSYMERR[] = "DUPLICATE EXTERNAL SYMBOL: "
|
|
BYTE ERROUTSTR = "ERROR CREATING OUTPUT FILE"
|
|
BYTE PRESSANYKEY[] = "PRESS ANY KEY TO CONTINUE..."
|
|
BYTE BINFILESTR[80]
|
|
BYTE MODCOUNT, MODI
|
|
BYTE BINREF, BINTYPE
|
|
WORD MODFILE,MODBUFF,MODLEN,MODADDR,LINKADDR
|
|
BYTE PERR
|
|
;
|
|
; Defines for ASM routines
|
|
;
|
|
ASM EQUATES
|
|
TMP EQU $F0
|
|
TMPL EQU TMP
|
|
TMPH EQU TMP+1
|
|
SRC EQU TMP
|
|
SRCL EQU SRC
|
|
SRCH EQU SRC+1
|
|
DST EQU SRC+2
|
|
DSTL EQU DST
|
|
DSTH EQU DST+1
|
|
ESP EQU DST+2
|
|
JMPTMP: JMP (TMP)
|
|
END
|
|
;
|
|
; CALL 6502 ROUTINE
|
|
; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
|
|
;
|
|
ASM ROMCALL
|
|
PHP
|
|
LDA ESTKL,X
|
|
STA TMPL
|
|
LDA ESTKH,X
|
|
STA TMPH
|
|
INX
|
|
LDA ESTKL,X
|
|
PHA
|
|
INX
|
|
LDA ESTKL,X
|
|
TAY
|
|
INX
|
|
LDA ESTKL+1,X
|
|
PHA
|
|
LDA ESTKL,X
|
|
INX
|
|
STX ESP
|
|
TAX
|
|
PLA
|
|
BIT ROMIN
|
|
PLP
|
|
JSR JMPTMP
|
|
PHP
|
|
BIT LCBNK2
|
|
STA REGVALS+0
|
|
STX REGVALS+1
|
|
STY REGVALS+2
|
|
PLA
|
|
STA REGVALS+3
|
|
LDX ESP
|
|
LDA #<REGVALS
|
|
LDY #>REGVALS
|
|
STA ESTKL,X
|
|
STY ESTKH,X
|
|
PLP
|
|
RTS
|
|
REGVALS: DS 4
|
|
END
|
|
;
|
|
; CALL PRODOS
|
|
; SYSCALL(CMD, PARAMS)
|
|
;
|
|
ASM SYSCALL
|
|
LDA ESTKL,X
|
|
LDY ESTKH,X
|
|
STA PARAMS
|
|
STY PARAMS+1
|
|
INX
|
|
LDA ESTKL,X
|
|
STA CMD
|
|
STX ESP
|
|
BIT ROMIN
|
|
JSR $BF00
|
|
CMD: DB 00
|
|
PARAMS: DW 0000
|
|
BIT LCBNK2
|
|
LDX ESP
|
|
STA ESTKL,X
|
|
LDY #$00
|
|
STY ESTKH,X
|
|
END
|
|
;
|
|
; SET MEMORY TO VALUE
|
|
; MEMSET(VALUE, ADDR, SIZE)
|
|
;
|
|
ASM MEMSET
|
|
LDY #$00
|
|
LDA ESTKL+1,X
|
|
STA DSTL
|
|
LDA ESTKH+1,X
|
|
STA DSTH
|
|
INC ESTKL,X
|
|
INC ESTKH,X
|
|
SETMEM: DEC ESTKL,X
|
|
BNE :+
|
|
DEC ESTKH,X
|
|
BEQ MEMEXIT
|
|
: LDA ESTKL+2,X
|
|
STA (DST),Y
|
|
INY
|
|
BNE :+
|
|
INC DSTH
|
|
: DEC ESTKL,X
|
|
BNE :+
|
|
DEC ESTKH,X
|
|
BEQ MEMEXIT
|
|
: LDA ESTKH+2,X
|
|
STA (DST),Y
|
|
INY
|
|
BNE SETMEM
|
|
INC DSTH
|
|
BNE SETMEM
|
|
MEMEXIT: INX
|
|
INX
|
|
INX
|
|
END
|
|
;
|
|
; COPY MEMORY
|
|
; MEMCPY(SRCADDR, DSTADDR, SIZE)
|
|
;
|
|
ASM MEMCPY
|
|
LDY #$00
|
|
LDA ESTKL,X
|
|
BNE :+
|
|
LDA ESTKH,X
|
|
BEQ MEMEXIT
|
|
: LDA ESTKL+1,X
|
|
STA DSTL
|
|
LDA ESTKH+1,X
|
|
STA DSTH
|
|
LDA ESTKL+2,X
|
|
STA SRCL
|
|
LDA ESTKH+2,X
|
|
STA SRCH
|
|
CMP DSTH
|
|
BCC REVCPY
|
|
BNE FORCPY
|
|
LDA SRCL
|
|
CMP DSTL
|
|
BCS FORCPY
|
|
REVCPY: ; REVERSE DIRECTION COPY
|
|
; CLC
|
|
LDA ESTKL,X
|
|
ADC DSTL
|
|
STA DSTL
|
|
LDA ESTKH,X
|
|
ADC DSTH
|
|
STA DSTH
|
|
CLC
|
|
LDA ESTKL,X
|
|
ADC SRCL
|
|
STA SRCL
|
|
LDA ESTKH,X
|
|
ADC SRCH
|
|
STA SRCH
|
|
INC ESTKH,X
|
|
REVCPYLP:
|
|
LDA DSTL
|
|
BNE :+
|
|
DEC DSTH
|
|
: DEC DSTL
|
|
LDA SRCL
|
|
BNE :+
|
|
DEC SRCH
|
|
: DEC SRCL
|
|
LDA (SRC),Y
|
|
STA (DST),Y
|
|
DEC ESTKL,X
|
|
BNE REVCPYLP
|
|
DEC ESTKH,X
|
|
BNE REVCPYLP
|
|
BEQ MEMEXIT
|
|
FORCPY: INC ESTKH,X
|
|
FORCPYLP:
|
|
LDA (SRC),Y
|
|
STA (DST),Y
|
|
INC DSTL
|
|
BNE :+
|
|
INC DSTH
|
|
: INC SRCL
|
|
BNE :+
|
|
INC SRCH
|
|
: DEC ESTKL,X
|
|
BNE FORCPYLP
|
|
DEC ESTKH,X
|
|
BNE FORCPYLP
|
|
BEQ MEMEXIT
|
|
END
|
|
;
|
|
; CHAR OUT
|
|
; COUT(CHAR)
|
|
;
|
|
ASM COUT
|
|
LDA ESTKL,X
|
|
INX
|
|
ORA #$80
|
|
BIT ROMIN
|
|
JSR $FDED
|
|
BIT LCBNK2
|
|
END
|
|
;
|
|
; CHAR IN
|
|
; RDKEY()
|
|
;
|
|
ASM CIN
|
|
BIT ROMIN
|
|
STX ESP
|
|
JSR $FD0C
|
|
LDX ESP
|
|
BIT LCBNK2
|
|
DEX
|
|
AND #$7F
|
|
STA ESTKL,X
|
|
LDY #$00
|
|
STY ESTKH,X
|
|
END
|
|
;
|
|
; PRINT STRING
|
|
; PRSTR(STR)
|
|
;
|
|
ASM PRSTR
|
|
LDY #$00
|
|
LDA ESTKL,X
|
|
STA SRCL
|
|
LDA ESTKH,X
|
|
STA SRCH
|
|
BIT ROMIN
|
|
LDA (SRC),Y
|
|
STA ESTKL,X
|
|
BEQ :+
|
|
_PRS1: INY
|
|
LDA (SRC),Y
|
|
ORA #$80
|
|
JSR $FDED
|
|
TYA
|
|
CMP ESTKL,X
|
|
BNE _PRS1
|
|
: INX
|
|
BIT LCBNK2
|
|
END
|
|
;
|
|
; READ STRING
|
|
; STR = RDSTR(PROMPTCHAR)
|
|
;
|
|
ASM RDSTR
|
|
LDA ESTKL,X
|
|
STA $33
|
|
STX ESP
|
|
BIT ROMIN
|
|
JSR $FD6A
|
|
BIT LCBNK2
|
|
STX $01FF
|
|
: LDA $01FF,X
|
|
AND #$7F
|
|
STA $01FF,X
|
|
DEX
|
|
BPL :-
|
|
LDX ESP
|
|
LDA #$FF
|
|
STA ESTKL,X
|
|
LDA #$01
|
|
STA ESTKH,X
|
|
END
|
|
;
|
|
; CONVERT CHARACTER TO UPPER CASE (AND STRIP MSB)
|
|
; CH = TOUPPER(CH)
|
|
;
|
|
ASM TOUPPER
|
|
LDA ESTKL,X
|
|
AND #$7F
|
|
CMP #'a'
|
|
BCC :+
|
|
CMP #'z'+1
|
|
BCS :+
|
|
; SEC
|
|
SBC #$1F ; SBC #$20
|
|
: STA ESTKL,X
|
|
END
|
|
DEF CROUT
|
|
COUT($0D)
|
|
END
|
|
DEF BADMOD
|
|
PRSTR(@BADMODSTR)
|
|
CROUT()
|
|
END
|
|
DEF PRBYTE(VAL)
|
|
DROP ROMCALL(VAL, 0, 0, 0, $FDDA)
|
|
END
|
|
DEF PRWORD(VAL)
|
|
DROP ROMCALL(VAL >> 8, VAL, 0, 0, $F941)
|
|
END
|
|
;
|
|
; BASIC FILE I/O
|
|
;
|
|
DEF GETFILEINFO(PATH, INFOPTR)
|
|
BYTE PARAMS[18]
|
|
|
|
PARAMS.0 = 10
|
|
PARAMS:1 = PATH
|
|
PERR = SYSCALL($C4, @PARAMS)
|
|
IF NOT PERR
|
|
MEMCPY(@PARAMS.3, INFOPTR, 15)
|
|
FIN
|
|
RETURN PERR
|
|
END
|
|
DEF DESTROY(PATH)
|
|
BYTE PARAMS[3]
|
|
|
|
PARAMS.0 = 1
|
|
PARAMS:1 = PATH
|
|
PERR = SYSCALL($C1, @PARAMS)
|
|
RETURN PERR
|
|
END
|
|
DEF CREATE(PATH, ACCESS, TYPE, AUX)
|
|
BYTE PARAMS[12]
|
|
|
|
PARAMS.0 = 7
|
|
PARAMS:1 = PATH
|
|
PARAMS.3 = ACCESS
|
|
PARAMS.4 = TYPE
|
|
PARAMS:5 = AUX
|
|
PARAMS.7 = $1
|
|
PARAMS:8 = 0
|
|
PARAMS:10 = 0
|
|
PERR = SYSCALL($C0, @PARAMS)
|
|
RETURN PERR
|
|
END
|
|
DEF OPEN(PATH, BUFF)
|
|
BYTE PARAMS[6]
|
|
|
|
PARAMS.0 = 3
|
|
PARAMS:1 = PATH
|
|
PARAMS:3 = BUFF
|
|
PARAMS.5 = 0
|
|
PERR = SYSCALL($C8, @PARAMS)
|
|
RETURN PARAMS.5
|
|
END
|
|
DEF CLOSE(REFNUM)
|
|
BYTE PARAMS[2]
|
|
|
|
PARAMS.0 = 1
|
|
PARAMS.1 = REFNUM
|
|
PERR = SYSCALL($CC, @PARAMS)
|
|
RETURN PERR
|
|
END
|
|
DEF READ(REFNUM, BUFF, LEN)
|
|
BYTE PARAMS[8]
|
|
|
|
PARAMS.0 = 4
|
|
PARAMS.1 = REFNUM
|
|
PARAMS:2 = BUFF
|
|
PARAMS:4 = LEN
|
|
PARAMS:6 = 0
|
|
PERR = SYSCALL($CA, @PARAMS)
|
|
RETURN PARAMS:6
|
|
END
|
|
DEF WRITE(REFNUM, BUFF, LEN)
|
|
BYTE PARAMS[8]
|
|
PARAMS.0 = 4
|
|
PARAMS.1 = REFNUM
|
|
PARAMS:2 = BUFF
|
|
PARAMS:4 = LEN
|
|
PARAMS:6 = 0
|
|
PERR = SYSCALL($CB, @PARAMS)
|
|
RETURN PARAMS:6
|
|
END
|
|
;
|
|
; REL MODULE FIXUPS
|
|
;
|
|
;DEF DUMPRLD(RLD)
|
|
; COUT('$')
|
|
; PRBYTE(^RLD)
|
|
; COUT(':')
|
|
; COUT(' ')
|
|
; COUT('$')
|
|
; PRWORD(*(RLD + 1))
|
|
; COUT(' ')
|
|
; COUT('$')
|
|
; PRBYTE(^(RLD + 3))
|
|
; CROUT
|
|
; RETURN RLD + 4
|
|
;END
|
|
;DEF DUMPESD(ESD)
|
|
; WHILE ^ESD & $80
|
|
; COUT(^ESD)
|
|
; ESD = ESD + 1
|
|
; LOOP
|
|
; COUT(^ESD)
|
|
; COUT(':')
|
|
; COUT(' ')
|
|
; COUT('$')
|
|
; PRBYTE(^(ESD + 1))
|
|
; COUT(' ')
|
|
; COUT('$')
|
|
; PRWORD(^(ESD + 2))
|
|
; CROUT
|
|
; RETURN ESD + 4
|
|
;END
|
|
DEF MATCHSTR(STR1, STR2)
|
|
BYTE I
|
|
IF ^STR1 == ^STR2
|
|
FOR I = ^STR1 DOWNTO 1
|
|
IF (STR1).[I] <> (STR2).[I]
|
|
RETURN FALSE
|
|
FIN
|
|
NEXT
|
|
RETURN TRUE
|
|
FIN
|
|
RETURN FALSE
|
|
END
|
|
;
|
|
; THE GLOBAL SYMBOL DICTIONARY HAS THE FORMAT OF:
|
|
; STRING: NAME (VARIABLE LENGTH)
|
|
; WORD: ADDRESS
|
|
;
|
|
DEF DUMPDICT
|
|
WORD DICTPTR
|
|
|
|
DICTPTR = SYMTABLE
|
|
CROUT()
|
|
WHILE ^DICTPTR
|
|
PRSTR(DICTPTR)
|
|
COUT(':')
|
|
COUT(' ')
|
|
COUT('$')
|
|
PRWORD(*(DICTPTR + ^DICTPTR + 1))
|
|
CROUT()
|
|
DICTPTR = DICTPTR + ^DICTPTR + 3 ; NEXT ENTRY
|
|
LOOP
|
|
END
|
|
DEF SEARCHDICT(SYMSTR)
|
|
WORD DICTPTR
|
|
|
|
DICTPTR = SYMTABLE
|
|
;
|
|
; SEARCH GLOBAL DICTIONARY LOOKING FOR MATCH
|
|
;
|
|
WHILE ^DICTPTR
|
|
IF MATCHSTR(DICTPTR, SYMSTR)
|
|
RETURN DICTPTR + ^DICTPTR + 1
|
|
FIN
|
|
DICTPTR = DICTPTR + ^DICTPTR + 3 ; NEXT ENTRY
|
|
LOOP
|
|
RETURN 0
|
|
END
|
|
DEF ADDSYM(SYMSTR, ADDR)
|
|
IF SEARCHDICT(SYMSTR)
|
|
PRSTR(@DUPSYMERR)
|
|
PRSTR(SYMSTR)
|
|
CROUT()
|
|
RETURN ERROR
|
|
FIN
|
|
MEMCPY(SYMSTR, NEXTENTRY, ^SYMSTR + 1)
|
|
NEXTENTRY = NEXTENTRY + ^NEXTENTRY
|
|
(NEXTENTRY):1 = ADDR
|
|
NEXTENTRY = NEXTENTRY + 3
|
|
RETURN OK
|
|
END
|
|
DEF MATCHEXTRN(INDEX, ESD)
|
|
BYTE SYMSTR[$81], I
|
|
WORD SYMPTR
|
|
|
|
;
|
|
; FIND MATCHING ESD INDEX
|
|
;
|
|
WHILE ^ESD
|
|
SYMPTR = ESD
|
|
I = 1
|
|
WHILE ^ESD & $80
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
I = I + 1
|
|
ESD = ESD + 1
|
|
LOOP
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
SYMSTR = I
|
|
IF ^(ESD + 1) & $10
|
|
IF ^(ESD + 2) == INDEX
|
|
RETURN SEARCHDICT(@SYMSTR)
|
|
FIN
|
|
FIN
|
|
ESD = ESD + 4
|
|
LOOP
|
|
RETURN 0
|
|
END
|
|
DEF PREXTRN(INDEX, ESD)
|
|
BYTE SYMSTR[$81], I
|
|
WORD SYMPTR
|
|
|
|
;
|
|
; FIND MATCHING ESD INDEX
|
|
;
|
|
WHILE ^ESD
|
|
SYMPTR = ESD
|
|
I = 1
|
|
WHILE ^ESD & $80
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
I = I + 1
|
|
ESD = ESD + 1
|
|
LOOP
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
SYMSTR = I
|
|
IF ^(ESD + 1) & $10
|
|
IF ^(ESD + 2) == INDEX
|
|
PRSTR(@SYMSTR)
|
|
FIN
|
|
FIN
|
|
ESD = ESD + 4
|
|
LOOP
|
|
END
|
|
;
|
|
; THE EXTENDED MODULE FORMAT CONTAINS:
|
|
; DATA_SIZE (WORD)
|
|
; IF DATA_SIZE <> 0
|
|
; DATA_SEGMENT (0..DATA_SIZE)
|
|
; ELSE
|
|
; DATA_SIZE (WORD)
|
|
; BYTECODE_SIZE (WORD)
|
|
; BYTECODE_FUNCTION_COUNT (BYTE)
|
|
; DATA_SEGMENT (1..DATA_SIZE)
|
|
; BYTECODE_SEGMENT (1..BYTECODE_SIZE)
|
|
; BYTECODE_FUNCTION_DICTIONARY (0..BYTECODE_FUNCTION_COUNT * 6)
|
|
; BYTE: FLAGS
|
|
; BIT 7: ENTRY DEF
|
|
; BIT 0..1: OPTIMIZATION LEVEL (0, 1, 2, 3)
|
|
; WORD: FUNC SIZE
|
|
; WORD: FUNC OFFSET
|
|
; BYTE: ESD INDEX IF ENTRY
|
|
; FIN
|
|
; RELOCATEABLE_DICTIONARY
|
|
; BYTE: FLAGS
|
|
; BIT 7: SIZE OF RELOC FIELD - 1 = WORD, 0 = BYTE
|
|
; BIT 6: MSB/LSB OF WORD - 1 = MSB, 0 = LSB
|
|
; BIT 5: ENDIANNESS OF WORD - 1 = BIG, 0 = LITTLE
|
|
; BIT 4: EXTRN REF - 1 = EXTRN, 0 = NOT EXTERN
|
|
; BIT 3: BYTCODE FUNC - 1 = FUNC, 0 NOT FUNC
|
|
; BIT 2: SEGMENT FIXUP - 1 = BYTECODE, 0 = DATA
|
|
; BIT 0: NOT END OF RLD - 1 = NOT END, 0 = END
|
|
; WORD: FIXUP_OFFSET
|
|
; BYTE: 8 BIT VALUE/ESD INDEX IF EXTERN/FUNC INDEX IF BYTECODE FUNC
|
|
; END_OF_RLD = $00 (BYTE)
|
|
; EXTERNAL_SYMBOL_DICTIONARY
|
|
; STRING: NAME
|
|
; BYTE: FLAGS
|
|
; BIT 4: EXTRN REF
|
|
; BIT 3: EXPORT DEF
|
|
; BIT 2: MODULE DEP (UNUSED MACRO-BIT)
|
|
; BIT 1: BYTECODE ENTRY
|
|
; BYTE: EXTRN SYMBOL INDEX/BYTECODE ENTRY INDEX/LSB OF EXPORT OFFSET
|
|
; BYTE: EXTERN SYMBOL MODULE INDEX/MSB OF EXPORT OFFSET
|
|
; END_OF_ESD = $00 (BYTE)
|
|
;
|
|
DEF FIXUP(DATASEGPTR, CODESEGPTR, BFD, RLD, OFST, ESD, PASS)
|
|
WORD FIXVAL, FIXADDR, EXTRNVAL
|
|
|
|
WHILE ^RLD
|
|
IF ^RLD & $04
|
|
FIXADDR = CODESEGPTR + *(RLD + 1)
|
|
ELSE
|
|
FIXADDR = DATASEGPTR + *(RLD + 1)
|
|
FIN
|
|
IF ^RLD & $08
|
|
;
|
|
; BYTCODE FUNC INDEX ADDRESS
|
|
;
|
|
FIXVAL = BFD + (^(RLD + 3) * 6)
|
|
ELSIF ^RLD & $10
|
|
;
|
|
; EXTERNAL SYMBOL
|
|
;
|
|
EXTRNVAL = MATCHEXTRN(^(RLD + 3), ESD)
|
|
IF EXTRNVAL
|
|
FIXVAL = *EXTRNVAL
|
|
ELSIF PASS == 2
|
|
PRSTR(@BADEXT)
|
|
PREXTRN(^(RLD + 3), ESD)
|
|
CROUT()
|
|
RETURN ERROR
|
|
FIN
|
|
ELSE
|
|
;
|
|
; DATA ADDRESS
|
|
;
|
|
IF ^RLD & $80
|
|
;
|
|
; 16 BIT OFFSET
|
|
;
|
|
FIXVAL = OFST
|
|
ELSE
|
|
;
|
|
; 8 BIT VALUE FROM RLD TABLE
|
|
;
|
|
FIXVAL = ^(RLD + 3) + OFST
|
|
FIN
|
|
FIN
|
|
IF ^RLD & $80
|
|
;
|
|
; 16 BIT FIXUP
|
|
;
|
|
IF ^RLD & $20 ; REVERSE HI AND LO BYTES
|
|
FIXVAL = FIXVAL + ((FIXADDR).1 ? ((FIXADDR).0 << 8))
|
|
*FIXADDR = ((FIXVAL >> 8) & $FF) ? (FIXVAL << 8)
|
|
ELSE
|
|
*FIXADDR = FIXVAL + *FIXADDR
|
|
FIN
|
|
ELSE
|
|
;
|
|
; 8 BIT FIXUP
|
|
;
|
|
IF ^RLD & $40
|
|
^FIXADDR = (FIXVAL >> 8) + ^FIXADDR
|
|
ELSE
|
|
^FIXADDR = FIXVAL + ^FIXADDR
|
|
FIN
|
|
FIN
|
|
RLD = RLD + 4
|
|
LOOP
|
|
RETURN OK
|
|
END
|
|
DEF LOADMOD(MODSTR, PASS)
|
|
BYTE REFNUM, I, INFO[15], SYMSTR[81]
|
|
WORD RELOFST, MODPTR, MODSYMTBL, MODSYMSZ, LEN
|
|
WORD DATASEG, CODESEG, DATALEN, CODELEN, NUMDEFS, BFD, RLD, ESD
|
|
WORD CODEOFST, BFDOFST
|
|
|
|
DROP GETFILEINFO(MODSTR, @INFO)
|
|
IF PERR OR INFO.1 <> $FE ; REL FILE TYPE
|
|
RETURN 0, 0
|
|
FIN
|
|
IF MODADDR
|
|
RELOFST = MODADDR - INFO:2
|
|
ELSE
|
|
MODADDR = INFO:2
|
|
LINKADDR = MODADDR
|
|
RELOFST = 0
|
|
FIN
|
|
MODADDR = MODADDR + DATALEN
|
|
;
|
|
; READ REL FILE
|
|
;
|
|
REFNUM = OPEN(MODSTR, INBUFF)
|
|
LEN = READ(REFNUM, DATABUFF, 16384)
|
|
DROP CLOSE(REFNUM)
|
|
;
|
|
; GET POINTERS TO IMPORTANT SECTIONS
|
|
;
|
|
DATALEN = *DATABUFF
|
|
IF DATALEN == 0
|
|
;
|
|
; EXTENDED FORMAT REL
|
|
;
|
|
MODPTR = DATABUFF + 2
|
|
DATALEN = (MODPTR):0
|
|
CODELEN = (MODPTR):2
|
|
NUMDEFS = (MODPTR).4
|
|
DATASEG = MODPTR + 5
|
|
CODESEG = DATASEG + DATALEN
|
|
CODEOFST = RELOFST + DATALEN
|
|
BFD = CODESEG + CODELEN
|
|
BFDOFST = CODEOFST + CODELEN
|
|
MODPTR = BFD
|
|
FOR I = 0 TO NUMDEFS
|
|
;
|
|
; REFORMAT BFD
|
|
;
|
|
(MODPTR).0 = $20 ; JSR
|
|
(MODPTR):1 = $03D6 ; INTERPX
|
|
(MODPTR):3 = (MODPTR):3 + CODEOFST ; FIXUP
|
|
(MODPTR).5 = $00 ; EXTERNAL BANK # (0 = MAIN MEM)
|
|
MODPTR = MODPTR + 6
|
|
NEXT
|
|
ELSE
|
|
;
|
|
; NORMAL FORMAT REL
|
|
;
|
|
CODELEN = 0
|
|
DATASEG = DATABUFF + 2
|
|
CODESEG = 0
|
|
BFD = 0
|
|
NUMDEFS = 0
|
|
MODPTR = DATASEG + DATALEN
|
|
FIN
|
|
RLD = MODPTR
|
|
ESD = RLD
|
|
WHILE ^ESD ; SKIP OVER RLD
|
|
ESD = ESD + 4
|
|
LOOP
|
|
ESD = ESD + 1
|
|
;
|
|
; RUN THROUGH DATA FIXUP TABLE
|
|
;
|
|
IF FIXUP(DATASEG, CODESEG, BFD, RLD, RELOFST, ESD, PASS)
|
|
RETURN 0, 0
|
|
FIN
|
|
;
|
|
; CHECK SYMBOL TABLE FOR EXPORTS/IMPORTS/MODULE DEPENDENCIES
|
|
;
|
|
IF PASS == 1
|
|
WHILE ^ESD
|
|
I = 1
|
|
WHILE ^ESD & $80
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
I = I + 1
|
|
ESD = ESD + 1
|
|
LOOP
|
|
SYMSTR[I] = TOUPPER(^ESD)
|
|
SYMSTR = I
|
|
IF ^(ESD + 1) & $08 ; EXPORT SYMBOL
|
|
;
|
|
; ADD TO GLOBAL SYMBOL TABLE
|
|
;
|
|
IF ADDSYM(@SYMSTR, *(ESD + 2) + RELOFST)
|
|
RETURN 0, 0
|
|
FIN
|
|
ELSIF ^(ESD + 1) & $02 ; BYTECODE ENTRY SYMBOL
|
|
;
|
|
; ADD TO GLOBAL SYMBOL TABLE
|
|
;
|
|
IF ADDSYM(@SYMSTR, ^(ESD + 2) * 6 + BFDOFST)
|
|
RETURN 0, 0
|
|
FIN
|
|
ELSIF ^(ESD + 1) & $04 ; MODULE DEPENDENCY
|
|
;
|
|
; ADD MODULE DEPENDENCY TO MODFILE LIST
|
|
;
|
|
MEMCPY(@SYMSTR, MODFILE, I + 1)
|
|
MODFILE = MODFILE + I + 1
|
|
MODCOUNT = MODCOUNT + 1
|
|
FIN
|
|
ESD = ESD + 4
|
|
LOOP
|
|
FIN
|
|
RETURN DATASEG, DATALEN + CODELEN + NUMDEFS * 6
|
|
END
|
|
|
|
CROUT()
|
|
PRSTR(@PLASMASTR)
|
|
CROUT()
|
|
MEMSET(0, SYMTABLE, SYMSIZE)
|
|
MODCOUNT = 0
|
|
MODFILE = MODFILES
|
|
MODADDR = 0
|
|
PRSTR(@INPUTFILESTR)
|
|
WHILE ^(RDSTR($BA))
|
|
MEMCPY(INPUTSTR, MODFILE, ^INPUTSTR + 1)
|
|
MODFILE = MODFILE + ^MODFILE + 1
|
|
MODCOUNT = MODCOUNT + 1
|
|
LOOP
|
|
IF MODCOUNT
|
|
MODFILE = MODFILES
|
|
FOR MODI = 0 TO MODCOUNT - 1
|
|
IF NOT LOADMOD(MODFILE, 1)
|
|
PRSTR(MODFILE)
|
|
COUT('?')
|
|
COUT(7)
|
|
CROUT()
|
|
FIN
|
|
DROP
|
|
MODFILE = MODFILE + ^MODFILE + 1
|
|
NEXT
|
|
MODADDR = 0
|
|
MODFILE = MODFILES
|
|
IF LINKADDR == $2000
|
|
BINTYPE = $FF
|
|
ELSE
|
|
BINTYPE = $06
|
|
FIN
|
|
PRSTR(@OUTPUTFILESTR)
|
|
RDSTR($BA)
|
|
MEMCPY(INPUTSTR, BINFILESTR, ^INPUTSTR + 1)
|
|
DROP DESTROY(BINFILESTR)
|
|
DROP CREATE(BINFILESTR, $C3, BINTYPE, LINKADDR)
|
|
BINREF = OPEN(BINFILESTR, OUTBUFF)
|
|
IF BINREF == 0
|
|
PRSTR(@ERROUTSTR)
|
|
PRSTR(INPUTSTR)
|
|
ELSE
|
|
FOR MODI = 0 TO MODCOUNT - 1
|
|
MODBUFF =, MODLEN = LOADMOD(MODFILE, 2)
|
|
DROP WRITE(BINREF, MODBUFF, MODLEN)
|
|
PRSTR(MODFILE)
|
|
COUT('@')
|
|
COUT('$')
|
|
PRWORD(MODADDR - MODLEN)
|
|
CROUT()
|
|
MODFILE = MODFILE + ^MODFILE + 1
|
|
NEXT
|
|
DROP CLOSE(BINREF)
|
|
DUMPDICT()
|
|
FIN
|
|
CROUT()
|
|
PRSTR(@PRESSANYKEY)
|
|
WHILE ^$C000 < 128
|
|
LOOP
|
|
DROP ^$C010
|
|
FIN
|
|
DONE
|