Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
;era *.lst
;era *.lin
;era *.sym
;era *.bak
;pip a:=$1.plm[g2]
;seteof $1.plm
;isx
;plm80 $1.plm debug
;cpm
;vax $1.lst $$stan
;era $1.lst
isx
link $1.obj,x0100,plm80.lib to x$1.mod
locate x$1.mod code(0100H) stacksize(48)
era x$1.mod
cpm
objcpm x$1
era x$1
vax x$1.sym $$stan
vax x$1.lin $$stan


View File

@@ -0,0 +1,388 @@
TITLE 'GENERATE HEX FILE FROM COM FILE 9/81'
; HEX DUMP PROGRAM, READS AN INPUT FILE AND PRODUCES A HEX FILE
;
; COPYRIGHT (C), DIGITAL RESEARCH, 1976, 1977, 1978, 1979, 1980, 1981
; BOX 579 PACIFIC GROVE, CALIFORNIA
;
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;
ORG 100H
LXI SP,STKTOP
JMP MAIN
DB ' COPYRIGHT (C) DIGITAL RESEARCH '
BOOT EQU 0000H ;REBOOT POINT
BDOS EQU 0005H ;DOS ENTRY POINT
CONS EQU 1 ;READ CONSOLE
TYPEF EQU 2 ;TYPE FUNCTION
PRNTF EQU 9 ;PRINT BUFFER
OPENF EQU 15 ;FILE OPEN
CLOSF EQU 16 ;FILE CLOSE
DELF EQU 19 ;FILE DELETE
READF EQU 20 ;READ FUNCTION
WRITF EQU 21 ;WRITE RECORD
MAKEF EQU 22 ;MAKE FILE
DMAF EQU 26 ;SET DMA ADDRESS
;
FCB EQU 5CH ;FILE CONTROL BLOCK ADDRESS
BUFF EQU 80H ;INPUT DISK BUFFER ADDRESS
CR EQU 0DH
LF EQU 0AH
EOF EQU 1AH ;END OF FILE (CTL-Z)
;
; SET UP STACK
; STACK AREA
STACK: DS 64
STKTOP EQU $
;
; SUBROUTINES
;
;
GETBASE:
; READ THE OFFSET FROM THE SECOND PARAMETER
LXI H,FCB+17
LXI D,0
MVI B,8 ;MAX 8 DIGITS
GET0: MOV A,M
CPI ' '
JZ ENDGET
SUI '0'
CPI 10
JC GET1
; MUST BE HEX A-F
ADI ('0'-'A'+10) AND 0FFH
CPI 16
JNC BADGET
GET1: ;NEXT DIGIT IS IN A
XCHG
DAD H ;*2
DAD H ;*4
DAD H ;*8
DAD H ;*16
ADD L
MOV L,A
XCHG
INX H ;TO NEXT POSITION
DCR B
JNZ GET0
;
ENDGET:
XCHG
SHLD OFFSET
RET
;
BADGET:
LXI D,GETMSG
CALL PRINT
JMP BOOT
;
GETMSG:
DB CR,LF,'BAD HEX DIGIT IN BASE$'
;
PRINT: ;PRINT A BUFFER
MVI C,PRNTF
CALL BDOS
RET
;
PCHAR: ;SEND CHAR TO OUTPUT FILE
PUSH H
PUSH D
LXI H,OBP ;BUFFER POINTER
PUSH H ;SAVE FOR LATER
MOV E,M ;LO BYTE
MVI D,0
LXI H,BUFF
DAD D ;BUFF(OBP) IN H,L
MOV M,A ;STORE CHARACTER TO BUFFER
POP H ;RECALL OBP ADDRESS
INR M ;OBP=OBP+1
MOV A,M ;PAST END OF BUFFER?
CPI 128
JC EPCHAR
; WRITE THE BUFFER TO THE DISK FILE
MVI M,0 ;CLEARS OBP
PUSH B ;SAVE ENVIRONMENT
MVI C,WRITF
LXI D,FCB
CALL BDOS
ORA A ;ERROR?
JNZ BADPR
; NO ERROR, RETURN TO CALLER
POP B
EPCHAR: POP D
POP H
RET
;
BADPR: ;BAD WRITE
MVI C,CLOSF
LXI D,FCB
CALL BDOS ;TRY TO CLOSE THE FILE
LXI D,PRMSG
CALL PRINT
JMP BOOT
PRMSG: DB CR,LF,'DISK IS FULL$'
;
CRLF:
MVI A,CR
CALL PCHAR
MVI A,LF
CALL PCHAR
RET
;
;
PNIB: ;PRINT NIBBLE IN REG A
ANI 0FH ;LOW 4 BITS
CPI 10
JNC P10
; LESS THAN OR EQUAL TO 9
ADI '0'
JMP PRN
;
; GREATER OR EQUAL TO 10
P10: ADI 'A' - 10
PRN: CALL PCHAR
RET
;
MAIN: ; READ AND PROCESS SUCCESSIVE BUFFERS
CALL GETBASE ;GET BASE ADDRESS FOR DUMP
CALL SETUP ;SET UP INPUT FILE
; LOAD COM FILE TO MEMORY
LXI D,IBUFF
LOAD: ;READ DISK RECORD TO MEMORY
PUSH D ;SAVE DMA ADDRESS
MVI C,DMAF
CALL BDOS ;DMA SET
LXI D,FCB
MVI C,READF
CALL BDOS
POP D
ORA A
JNZ FINIS
LXI H,128
DAD D
XCHG
JMP LOAD ;FOR ANOTHER RECORD
;
FINIS:
DCR A ;EOF=1
JZ BUILDHEX
LXI D,RERR
CALL PRINT ;BAD DISK READ
JMP BOOT
;
BUILDHEX:
;BUILD HEX FILE FROM IBUFF THROUGH EBUFF
PUSH D
CALL SETHEX ;SET UP HEX FILE
POP D
DCX D ;LAST ADDRESS
LXI H,IBUFF ;D,E HOLDS HIGH ADDRESS, H,L HOLDS LOW ADDRESS
W0: MOV A,L ;GET LOW/NEXT ADDRESS
ADI 16 ;COMPUTE NEXT ADDRESS
MOV C,A ;SAVE TEMP IN B,C
MOV A,H
ACI 0
MOV B,A ;LOW ADDRESS+16 IN B,C
MOV A,E ;COMPARE HIGH ADDRESS
SUB C
MOV C,A ;SAVE DIFFERENCE
MOV A,D
SBB B
JC W1 ;'CAUSE LESS THAN 16
; OTHERWISE 16 BYTE RECORD
MVI A,16
JMP W2
;
W1: ;SHORT RECORD
MOV A,C ;-DIFF
ADI 17 ;MAKE IT POSITIVE
W2: ;CHECK FOR LAST RECORD
ORA A
JZ HDONE ;IF LAST
; OTHERWISE WRITE RECORD
PUSH D ;SAVE HIGH ADDRESS
MOV E,A ;SAVE LENGTH
MVI D,0 ;CLEAR CS
CALL CRLF ;WRITE CRLF
MVI A,':'
CALL PCHAR
MOV A,E ;LENGTH
CALL WRC ;WRITE CHARACTER
; APPLY OFFSET TO BASE ADDRESS
PUSH H
PUSH D
XCHG ;ABSOLUTE ADDRESS TO D,E
LXI H,-IBUFF
DAD D ;ABSOLUTE-IBUFF TO H,L
XCHG
LHLD OFFSET
DAD D ;ABSOLUTE-IBUFF+OFFSET
POP D
MOV A,H ;HO ADDRESS
CALL WRC
MOV A,L ;LO ADDRESS
CALL WRC
POP H ;ABSOLUTE ADDRESS
XRA A
CALL WRC ;RECORD TYPE
;
; WRITE RECORD
W3: MOV A,M
INX H
CALL WRC
DCR E
JNZ W3 ;FOR MORE
;
XRA A ;COMPUTE CHECKSUM
SUB D
CALL WRC
POP D ;RESTORE HIGH ADDR
JMP W0
;
WRC: ;WRITE CHAR WITH CHECK SUM IN D
PUSH PSW
RRC
RRC
RRC
RRC
ANI 0FH
CALL PNIB
POP PSW
PUSH PSW
ANI 0FH
CALL PNIB
POP PSW
ADD D
MOV D,A
RET
;
HDONE:
; FINISH BUFFER OUTPUT
CALL CRLF
MVI A,':'
CALL PCHAR
MVI B,8
ZLOOP: ;SEND 8 ZEROES TO OUTPUT
XRA A
CALL WRC
DCR B
JNZ ZLOOP
;
CALL CRLF
;
; FILL OUTPUT WITH END OF FILE CHARACTERS
FILLE: LDA OBP
ORA A
JZ EFILL ;WRITE 'TIL ZERO POINTER
MVI A,EOF
CALL PCHAR
JMP FILLE
; CLEARED, NOW CLOSE THE FILE
EFILL: MVI C,CLOSF
LXI D,FCB
CALL BDOS
CPI 255
JZ BADCLOSE
LXI D,ENDMSG
CALL PRINT
JMP BOOT
ENDMSG: DB CR,LF,'HEX FILE WRITTEN$'
;
BADCLOSE:
; CANNOT CLOSE THE FILE
LXI D,CLMSG
CALL PRINT
JMP BOOT
CLMSG: DB CR,LF,'CANNOT CLOSE FILE, CHECK WRITE PROTECT$'
;
; FILE CONTROL BLOCK DEFINITIONS
FCBDN EQU FCB+0 ;DISK NAME
FCBFN EQU FCB+1 ;FILE NAME
FCBFT EQU FCB+9 ;DISK FILE TYPE (3 CHARACTERS)
FCBRL EQU FCB+12 ;FILE'S CURRENT REEL NUMBER
FCBRC EQU FCB+15 ;FILE'S RECORD COUNT (0 TO 128)
FCBCR EQU FCB+32 ;CURRENT (NEXT) RECORD NUMBER (0 TO 127)
FCBLN EQU FCB+33 ;FCB LENGTH
;
;
FILLTYPE:
; SET THE TYPE FIELD FOR THE CURRENT FCB TO VALUE AT D,E
LXI H,FCBFT
MVI B,3
FILL0: LDAX D
INX D
MOV M,A
INX H
DCR B
JNZ FILL0
; mvi m,0 ;*** Bug fix: zeroes the extent
RET
;
SETUP: ;SET UP FILE
LXI D,COMTYPE
CALL FILLTYPE
; OPEN THE FILE FOR INPUT
LXI D,FCB
MVI C,OPENF
CALL BDOS
; CHECK FOR ERRORS
CPI 255
JNZ OPNOK
LXI D,OPERR
CALL PRINT
JMP BOOT
OPERR: DB CR,LF,'NO INPUT FILE PRESENT$'
COMTYPE:
DB 'COM'
;
SETHEX:
; SET UP HEX FILE
XRA A
STA OBP ;OUTPUT POINTER SET TO BEGINNING
LXI D,BUFF
MVI C,DMAF ;RESET DMA ADDRESS
CALL BDOS
;
LXI D,HEXTYPE
; CALL FILLTYPE ;SET TO .HEX
call patch ;*** bug fix ***
LXI D,FCB
PUSH D
MVI C,DELF ;DELETE OLD COPIES
CALL BDOS
POP D
MVI C,MAKEF ;MAKE A NEW ONE
CALL BDOS
CPI 255
JNZ OPNOK
;
; CANNOT CREATE THE FILE
LXI D,NOSPACE
CALL PRINT
JMP BOOT
NOSPACE:
DB CR,LF,'NO DIRECTORY SPACE$'
HEXTYPE:
DB 'HEX'
;
OPNOK: ;OPEN IS OK.
XRA A
STA FCBCR
RET
;
RERR: DB CR,LF,'DISK READ ERROR$'
;
OBP DS 1 ;OUTPUT BUFFER POINTER
OFFSET DS 2 ;DISPLACEMENT TO ADD IN HEX TAPE
ds 3
patch:
call filltype
mvi a,0
sta fcb+0ch
ret
IBUFF EQU ($ AND 0FF00H)+100H
END


View File

@@ -0,0 +1,14 @@
era genhex.asm
era xgenhex.asm
pip a:xgenhex.asm=e:genhex.asm
mac xgenhex
xref xgenhex
ren genhex.xrf=xgengex.xrf
vax genhex.xrf $$stan
load xgenhex
pip e:genhex.com=a:xgenhex.com
pip b:genhex.com=a:xgenhex.com
era xgenhex.*
era *.xrf
;end genhex submit


View File

@@ -0,0 +1,674 @@
TITLE 'GENMOD - MP/M RELOCATABLE MODULE GENERATOR 9/81'
; RELOCATING LOADER PROGRAM WITH MODULE GENERATION
;
; COPYRIGHT (C) 1979, 1980, 1981
; DIGITAL RESEARCH
; BOX 579, PACIFIC GROVE
; CALIFORNIA, 93950
;
;
; Revised:
; 14 Sept 81 by Thomas Rolander
ORG 000H ;BASE OF RELOCATABLE SEGMENT
BASE EQU $
ORG 100H ;BASE OF MP/M PROGRAM AREA
JMP START
DB ' COPYRIGHT (C) 1980, DIGITAL RESEARCH '
;
STKSIZ EQU 64 ;32 LEVEL WORKING STACK
;
; MISCELLANEOUS ADDRESS CONSTANTS
BOOT EQU BASE+0 ;SYSTEM REBOOT
BDOS EQU BASE+5 ;DOS ENTRY POINT
TOP EQU BASE+6 ;CONTAINS TOP OF MEMORY
DFCB EQU BASE+5CH ;DEFAULT FILE CONTROL BLOCK
DBF EQU BASE+80H ;DEFAULT BUFFER
RWORK EQU BASE+700H ;BASE OF RELOCATION WORK AREA
RMOD EQU BASE+600H ;MODULE RELOCATOR BASE
RSIZE EQU RMOD+1 ;MODULE SIZE FIELD
DSIZE EQU RMOD+4 ;DATA SIZE FIELD
;
; BDOS ENTRY FUNCTIONS
CONOF EQU 2 ;CONSOLE OUTPUT
OPF EQU 15 ;FILE OPEN FUNCTION
CLF EQU 16 ;FILE CLOSE FUNCTION
DLF EQU 19 ;FILE DELETE FUNCTION
RDF EQU 20 ;READ DISK
WRF EQU 21 ;WRITE DISK
MKF EQU 22 ;MAKE FILE
PRF EQU 9 ;PRINT BUFFER
DMF EQU 26 ;SET DMA ADDRESS
;
; NON GRAPHIC CHARACTERS
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
DEOF EQU 1AH ;END OF FILE
;
START:
LXI SP,STACK
;
CALL SETUP ;SET UP FILES
XRA A ;ZERO IN ACCUM
STA PASS ;PASS = 0
LXI H,0
SHLD HLOC ;HLOC = 0
CALL HREAD
LHLD HLOC ;HIGH ADDRESS TO H,L
INX H ;+1
PUSH H
; CLEAR THE RELOCATION BIT MAP
CALL FINDBYTE ;HLOC+1 IS TRANSLATED TO AN ABS ADDR
; MOVE H,L TO NEXT PARAGRAPH BOUNDARY
ADJ0: MOV A,L
ANI 7FH
JZ ADJ1
INX H ;TO NEXT ADDRESS
JMP ADJ0
ADJ1: DCX H
SHLD LBYTE ;LAST BYTE TO WRITE
XCHG ;LAST BYTE TO ZERO IS IN D,E
POP H ;RECALL HLOC+1
; CLEAR ALL BYTES FROM H,L THROUGH D,E
CLER0: MOV A,E
SUB L
MOV A,D
SBB H
JC CLER1
MVI M,0 ;CLEAR ANOTHER BYTE
INX H
JMP CLER0
CLER1: ;BIT VECTOR CLEARED
; THE RELOCATION BIT VECTOR IS BUILT DURING THE SECOND PASS
LXI H,PASS
INR M ;PASS = 1
CALL HREAD
; BIT VECTOR BUILT, WRITE THE MODULE
CALL TERMINATE
LXI D,OKMSG ;OPERATION COMPLETE
CALL PRINT
JMP FINIS
OKMSG: DB CR,LF,'MODULE CONSTRUCTED$'
;
; UTILITY SUBROUTINES
;
HREAD: ;HEX FORMAT READ SUBROUTINE
; INPUT RECORDS TAKE THE FORM:
; :NNLLLLTTD1D2D3...DNCC
; WHERE -
; NN IS THE RECORD LENGTH (00-FF)
; LLLL IS THE LOAD ADDRESS (0000-FFFF)
; TT IS THE RECORD TYPE (ALWAYS 00)
; D1-DN ARE THE DATA BYTES
; CC IS THE CHECKSUM
; THE LAST RECORD HAS A LENGTH OF ZERO, AND LLLL IS THE
; STARTING ADDRESS FOR THE MODULE (IGNORED HERE)
;
CALL DISKR ;NEXT INPUT CHARACTER TO ACCUM
CPI DEOF ;PAST END OF TAPE?
JZ CERROR
SBI ':'
JNZ HREAD ;LOOKING FOR START OF RECORD
;
; START FOUND, CLEAR CHECKSUM
MOV D,A
CALL RBYTE
MOV E,A ;SAVE LENGTH
CALL RBYTE ;HIGH ORDER ADDR
PUSH PSW
CALL RBYTE ;LOW ORDER ADDR
POP B ;HIGH ORDER ADDRESS TO B
MOV C,A ;LOW ORDER ADDRESS TO C
LDA BBOOL
ORA A
JNZ HVBIAS
MVI A,0FFH
STA BBOOL
MVI A,LOW(RWORK)
SUB C
MOV L,A
MVI A,HIGH(RWORK)
SBB B
MOV H,A
SHLD BRWRK ;BRWRK = RWORK-BIAS
MOV A,C
SUI LOW(RWORK)
MOV L,A
MOV A,B
SBI HIGH(RWORK)
MOV H,A
SHLD NBRWRK ;NBRWRK = BIAS-RWORK
HVBIAS:
LHLD BRWRK ;ADDRESS INTO WORK AREA (BIASED)
DAD B ;BIAS ADDRESS IN H,L
;
; IF ON SECOND PASS, THEN ADDRESSES ARE OFF BY ONE PAGE
LDA PASS
ORA A
JZ CHKLEN
; SECOND PASS, DECREMENT ADDRESS TO PREVIOUS PAGE
DCR H
CHKLEN:
; CHECK THE LENGTH FIELD FOR END OF HEX FILE
MOV A,E ;CHECK FOR LAST RECORD
ORA A
JNZ RDTYPE
; END OF HEX INPUT
RET
;
RDTYPE:
CALL RBYTE ;RECORD TYPE = 0
;
; LOAD THE RECORD ON PASS 0, SET REL BITS ON PASS 1
RED1: CALL RBYTE
MOV B,A ;SAVE DATA BYTE FOR COMPARE
LDA PASS
ORA A
JNZ COMP ;COMPARE ON PASS 1
;
; PASS 0, STORE DATA BYTE TO MEMORY
XCHG ;COMPARE WITH MEMORY TOP ADDRESS
PUSH H
LHLD TOP
MOV A,D
SUB H
JC SIZEOK
JNZ SZERR
MOV A,E
SUB L
JNC SZERR
SIZEOK:
POP H
XCHG
MOV M,B
; COMPUTE HIGH ADDRESS
PUSH H
PUSH D
XCHG ;CURRENT ADDRESS TO H,L
LHLD HLOC ;CURRENT HIGH LOCATION
MOV A,L
SUB E
MOV A,H
SBB D
POP D
POP H
JNC RED2 ;NO CARRY IF HLOC HIGH
SHLD HLOC ;NEW HLOC OTHERWISE
JMP RED2
;
COMP: ;PASS 1, COMPUTE RELOCATION BITS
MOV C,M ;GET DATA FROM MEMORY
MOV A,B
ora a
jnz comp1 ; jump if non-zero byte
lda igz
ora a
jnz red2 ; jump if ignoring zeroes on pass 1
mov a,b
comp1:
SUB C ;DIFFERENT?
JZ RED2 ;SKIP IF SAME DATA
PUSH D
PUSH H
; DIFFERENT, MUST BE BY 1
CPI 1
JZ RELOK ;OK TO RELOCATE
CPI -1 ; OR BY -1
JZ RELOK ;ALSO OK TO RELOCATE
; PRINT ERROR IN FORM -
; REL ERROR AT XXXX IMAGE X
LXI D,RELMSG
CALL PRINT
POP D ;ADDRESS
PUSH D
LHLD NBRWRK ;BIASED ADDRESS
DAD D ;REAL ADDRESS TO HL
CALL PADDR ;ADDRESS PRINTED
POP H
PUSH H ;HL READY FOR SETBIT
JMP RELOK
;
; INLINE RELOCATION ERROR MESSAGE
RELMSG: DB CR,LF,'RELOC ERROR AT $'
;
RELOK: CALL SETBIT ;RELOCATION BIT SET/RESET
POP H
POP D
RED2: INX H
DCR E
JNZ RED1 ;FOR ANOTHER BYTE
; OTHERWISE AT END OF RECORD - CHECKSUM
CALL RBYTE
JNZ CERROR
JMP HREAD ;FOR ANOTHER RECORD
;
RBYTE: ;READ ONE BYTE FROM BUFF AT WBP TO REG-A
; COMPUTE CHECKSUM IN REG-D
PUSH B
PUSH H
PUSH D
;
CALL DISKR ;GET ONE MORE CHARACTER
CALL HEXCON ;CONVERT TO HEX (OR ERROR)
;
; SHIFT LEFT AND MASK
RLC
RLC
RLC
RLC
ANI 0F0H
PUSH PSW ;SAVE FOR A FEW STEPS
CALL DISKR
CALL HEXCON
;
; OTHERWISE SECOND NIBBLE OK, SO MERGE
POP B ;PREVIOUS NIBBLE TO REG-B
ORA B
MOV B,A ;VALUE IS NOW IN B TEMPORARILY
POP D ;CHECKSUM
ADD D ;ACCUMULATING
MOV D,A ;BACK TO CS
; ZERO FLAG REMAINS SET
MOV A,B ;BRING BYTE BACK TO ACCUMULATOR
POP H
POP B ;BACK TO INITIAL STATE WITH ACCUM SET
RET
REND:
;NORMAL END OF LOAD
RET
;
;
DISKR: ;DISK READ
PUSH H
PUSH D
PUSH B
;
RDI: ;READ DISK INPUT
LDA DBP
ANI 7FH
JZ NDI ;GET NEXT DISK INPUT RECORD
;
; READ CHARACTER
RDC:
MVI D,0
MOV E,A
LXI H,DBF
DAD D
MOV A,M
CPI DEOF
JZ RRET ;END OF FILE
LXI H,DBP
INR M
JMP RRET
;
NDI: ;NEXT BUFFER IN
MVI C,RDF
LXI D,DFCB
CALL BDOS
ORA A
JNZ DEF
;
; BUFFER READ OK
STA DBP ;STORE 00H
JMP RDC
;
DEF: ;DISK END OF FILE
MVI A,DEOF
RRET:
POP B
POP D
POP H
; TRANSLATE TO UPPER CASE
TRAN:
CPI 7FH ;RUBOUT?
RZ
CPI ('A' OR 010$0000B) ;UPPER CASE A
RC
ANI 101$1111B ;CLEAR UPPER CASE BIT
RET
;
SETBIT:
;SET THE BIT POSITION GIVEN BY H,L TO 1
CALL FINDBYTE
; ROTATE A 1 BIT BY THE AMOUNT GIVEN BY B - 1
MVI A,1
SET0: DCR B
JZ SET1
ORA A ;CLEAR CY
RAL
JMP SET0
;
; BIT IS IN POSITION
SET1: ORA M ;OR'ED TO BIT PATTERN IN MEMORY
MOV M,A ;BACK TO BIT VECTOR
RET
;
FINDBYTE:
; H,L ADDRESSES A BYTE POSITION, CHANGE H,L TO BIT VECTOR
; POSITION, SET B TO NUMBER OF SHIFTS REQUIRED TO SELECT
; PROPER BIT AT RESULTING H,L POSITION
LXI D,-RWORK
DAD D
XCHG ;BIT ADDRESS IN D,E
MOV A,E
ANI 111B ;VALUE X = 0,1,...,7
; CHANGE TO 8-X (8,7,...,1) TO SIMPLIFY BIT SHIFTING LATER
CMA ;VALUE X = -1,-2,...,-8
ADI 9 ;VALUE X = 8,7, ...,1
MOV B,A
MVI C,3 ;SHIFT COUNT IS 3
SHRL: ;SHIFT RIGHT LOOP
XRA A ;CLEAR FLAGS
MOV A,D
RAR
MOV D,A
MOV A,E
RAR
MOV E,A
DCR C
JNZ SHRL
;
; END OF SHIFT, H,L ADDRESS RELATIVE BYTE POSITION
LHLD HLOC ;LAST MEMORY ADDRESS FOR CODE
INX H
DAD D ;ABSOLUTE ADDRESS IS IN H,L
RET
;
PCHAR: ;PRINT CHARACTER IN A
PUSH H
PUSH D
PUSH B
MOV E,A
MVI C,CONOF
CALL BDOS
POP B
POP D
POP H
RET
;
PNIB: ;PRINT NIBBLE IN REG A
ANI 0FH
CPI 10
JNC P10
; <= 9
ADI '0'
JMP PRN
P10: ADI 'A' - 10
PRN: CALL PCHAR
RET
;
PHEX: ;PRINT HEX CHAR IN REG-A
PUSH PSW
RRC
RRC
RRC
RRC
CALL PNIB
POP PSW
CALL PNIB
RET
;
PADDR: ;PRINT ADDRESS IN H,L
MOV A,H
CALL PHEX
MOV A,L
CALL PHEX
RET
;
CRLF: ;CARRIAGE RETURN - LINE FEED
MVI A,CR
CALL PCHAR
MVI A,LF
CALL PCHAR
RET
;
TERMINATE:
;WRITE MODULE TO DISK
LXI D,-(RWORK-1)
LHLD HLOC ;HIGH MODULE ADDRESS
DAD D ;MODULE RELATIVE END IN H,L
SHLD RSIZE ;STORE MODULE SIZE IN RELOCATOR
PUSH H
LXI D,RELEMSG ;REL MOD END
CALL PRINT
POP H
CALL PADDR ;REL MOD END XXXX
LHLD LBYTE ;LAST POSITION TO WRITE
PUSH H
LXI D,-RWORK
DAD D
PUSH H
LXI D,RELSMSG
CALL PRINT
POP H
CALL PADDR ;REL MOD SIZE XXXX
LXI D,RELDMSG
CALL PRINT
LHLD DSIZE
CALL PADDR ;REL DAT SIZE XXXX
POP H
LXI D,RMOD ;D,E ADDRESS FIRST POSITION TO WRITE
WLOOP: MOV A,L
SUB E
MOV A,H
SBB D ;CARRY GENERATED IF D,E > H,L
JC CLOS
; WRITE ANOTHER RECORD
PUSH H
PUSH D ;FIRST AND LAST SAVED
MVI C,DMF ;SET DMA ADDRESS
CALL BDOS
MVI C,WRF ;WRITE TO FILE
LXI D,OFCB
CALL BDOS ;WRITTEN
ORA A
JNZ OFERR
; WRITE OK, INCREMENT DMA ADDRESS
LXI H,128
POP D
DAD D
XCHG
POP H ;STATE RESTORED FOR ANOTHER WRITE
JMP WLOOP
CLOS: ;CLOSE OUTPUT FILE
; MOVE DMA ADDRESS BACK TO 80H SO DATA IS NOT DESTROYED
; (THERE MAY BE A SUBSEQUENT SAVE OF THE ENTIRE MEM IMAGE)
MVI C,DMF
LXI D,DBF
CALL BDOS
MVI C,CLF
LXI D,OFCB
CALL BDOS
CPI 255
JZ OFERR
RET
;
RELEMSG:
DB CR,LF,'REL MOD END $'
RELSMSG:
DB CR,LF,'REL MOD SIZE $'
RELDMSG:
DB CR,LF,'REL DAT SIZE $'
;
HEXCON:
;CONVERT ACCUMULATOR TO PURE BINARY FROM EXTERNAL ASCII
SUI '0'
CPI 10
RC ;MUST BE 0-9
ADI ('0'-'A'+10) AND 0FFH
CPI 16
RC ;MUST BE A-F
LXI D,HEXMSG
CALL PRINT
JMP FINIS
HEXMSG: DB CR,LF,'BAD HEX DIGIT'
INHEX: DB ' '
DB 'IN DATA SIZE SPECIFICATION$'
;
SETUP:
;SETUP FILES FOR PROCESSING
; SCAN FOR DATA SIZE SPECIFICATION
LXI D,DBF
SCNDLR:
LDAX D
INX D
ORA A
JZ NODTSZ
CPI '$'
JNZ SCNDLR
LXI H,0
MVI B,0
ldax d
call tran
cpi 'Z'
jnz scnend
mvi a,0ffh
sta igz
inx d
SCNEND:
LDAX D
INX D
ORA A
JZ ENDTSZ
CALL TRAN ;CONVERT TO UPPER CASE
CALL HEXCON
JNC ENDTSZ
OKDIGIT:
MOV C,A
DAD H
DAD H
DAD H
DAD H
DAD B
JMP SCNEND
NODTSZ:
LXI H,0
ENDTSZ:
LXI D,RMOD
MVI B,0
XRA A
ZEROBP:
STAX D
INX D
DCR B
JNZ ZEROBP
SHLD DSIZE
MVI A,'$'
STA INHEX
; SET DMA ADDRESS TO DBF
LXI D,DBF
MVI C,DMF
CALL BDOS
; LOOK FOR VALID FILE NAMES
LDA DFCB+1
CPI ' '
JZ FNERR
LDA DFCB+17
CPI ' '
JZ FNERR
; NAMES ARE PRESENT, COPY SECOND NAME TO OFCB
LXI H,OFCB
LXI D,DFCB+16
MVI B,16
FLOOP: LDAX D ;GET CHARACTER
MOV M,A
INX H
INX D
DCR B
JNZ FLOOP
;
; NAME COPIED, DELETE CURRENT VERSIONS, MAKE NEW FILE
LXI D,OFCB
PUSH D
MVI C,DLF
CALL BDOS
POP D
MVI C,MKF
CALL BDOS
CPI 255
JZ OFERR
XRA A
STA OFR ;CLEAR RECORD NUMBER
;
; NEW FILE HAS BEEN CREATED, NOW OPEN INPUT FILE
MVI C,OPF ;FILE OPEN FUNCTION
LXI D,DFCB ;FILE CONTROL BLOCK ADDRESS
CALL BDOS
CPI 255 ;ERROR IF NOT FOUND
JZ OPERR ;ERROR MESSAGE AND ABORT IF NOT FOUND
LXI H,DBP ;DATA BUFFER POINTER
MVI M,0 ;CAUSES IMMEDIATE DATA READ
RET
;
OPERR: ;OPEN ERROR
LXI D,OPMSG
CALL PRINT
JMP FINIS
;
OPMSG: DB CR,LF,'INPUT FILE NOT PRESENT$'
;
BERROR:
LXI D,BASMSG
CALL PRINT
JMP FINIS
BASMSG: DB CR,LF,'INVALID RELOCATION BASE$'
;
;
CERROR:
;ERROR IN INPUT, ABORT THE LOAD
LXI D,ERMSG
CALL PRINT
JMP FINIS
ERMSG: DB CR,LF,'BAD INPUT RECORD$'
;
FNERR:
LXI D,FNMSG
CALL PRINT
JMP FINIS
FNMSG: DB 'MISSING FILE NAME$'
;
OFERR:
LXI D,OFMSG
CALL PRINT
JMP FINIS
OFMSG: DB 'CANNOT CREATE OUTPUT FILE$'
;
SZERR:
LXI D,SZMSG
CALL PRINT
JMP FINIS
SZMSG: DB 'HEX FILE SIZE TOO LARGE$'
;
PRINT: ;PRINT MESSAGE ADDRESSED BY D,E
MVI C,PRF
CALL BDOS
RET
;
FINIS: ;END OF PROCESSING
JMP BOOT
;
DBP: DS 1 ;DISK BUFFER POINTER
RBASE: DS 1 ;RELOCATION BASE
PASS: DS 1 ;PASS 0,1
;
;
HLOC: DS 2 ;HIGH ADDRESS IN MODULE
LBYTE: DS 2 ;LAST BIT VECTOR BYTE POSITION
;
;
BRWRK: DS 2 ;BIASED RWORK
NBRWRK: DS 2 ;NEGATIVE BIASED RWORK
;
OFCB: DS 32 ;OUTPUT FILE CONTROL BLOCK
OFR: DS 1 ;OUTPUT FILE RECORD NUMBER
;
DS STKSIZ ;STACK SIZE
STACK:
;
igz: db 0 ;ignore zeroes on pass 1, boolean
BBOOL: DB 0 ;BIAS COMPUTED, BOOLEAN
; ;THIS DB GUARANTEES MODULE SIZE
END


View File

@@ -0,0 +1,14 @@
era genmod.asm
era xgenmod.asm
pip a:xgenmod.asm=e:genmod.asm
mac xgenmod
xref xgenmod
ren genmod.xrf=xgenmod.xrf
vax genmod.xrf $$stan
load xgenmod
pip e:genmod.com=a:xgenmod.com
pip b:genmod.com=a:xgenmod.com
era *.xrf
era xgenmod.*
;end genmod submit


View File

@@ -0,0 +1,28 @@
era *.lst
era *.lin
era *.sym
era *.bak
pip a:=e:load.plm
seteof load.plm
isx
plm80 load.plm debug
cpm
vax load.lst $$stan
isx
link load.obj,x0100,plm80.lib to xload.mod
locate xload.mod code(0100H) stacksize(48)
era xload.mod
cpm
objcpm xload
ren load.sym=xload.sym
ren load.lin=xload.lin
vax load.sym $$stan
vax load.lin $$stan
pip e:load.com=a:xload.com
pip b:load.com=a:xload.com
era load.lin
era load.sym
era load.lst
era xload.*
;end load submit


View File

@@ -0,0 +1,362 @@
LOAD:
DO;
/* C P / M C O M M A N D F I L E L O A D E R
COPYRIGHT (C) 1976, 1977, 1978, 1979, 1980, 1981
DIGITAL RESEARCH
BOX 579 PACIFIC GROVE
CALIFORNIA 93950
Revised:
14 Sept 81 by Thomas Rolander
*/
DECLARE
TPA LITERALLY '0100H', /* TRANSIENT PROGRAM AREA */
DFCBA LITERALLY '005CH', /* DEFAULT FILE CONTROL BLOCK */
DBUFF LITERALLY '0080H'; /* DEFAULT BUFFER ADDRESS */
/* JMP LOADCOM TO START LOAD */
DECLARE JUMP BYTE DATA(0C3H);
DECLARE JUMPA ADDRESS DATA(.LOADCOM);
DECLARE COPYRIGHT(*) BYTE DATA
(' COPYRIGHT (C) 1980, DIGITAL RESEARCH ');
MON1: PROCEDURE(F,A) EXTERNAL;
DECLARE F BYTE, A ADDRESS;
END MON1;
MON2: PROCEDURE(F,A) BYTE EXTERNAL;
DECLARE F BYTE, A ADDRESS;
END MON2;
DECLARE SP ADDRESS;
BOOT: PROCEDURE;
STACKPTR = SP;
RETURN;
END BOOT;
LOADCOM: PROCEDURE;
DECLARE FCB (33) BYTE AT (DFCBA),
FCBA LITERALLY 'DFCBA';
DECLARE BUFFER (128) BYTE AT (DBUFF),
BUFFA LITERALLY 'DBUFF';
DECLARE SFCB(33) BYTE, /* SOURCE FILE CONTROL BLOCK */
BSIZE LITERALLY '1024',
EOFILE LITERALLY '1AH',
SBUFF(BSIZE) BYTE, /* SOURCE FILE BUFFER */
RFLAG BYTE, /* READER FLAG */
SBP ADDRESS; /* SOURCE FILE BUFFER POINTER */
/* LOADCOM LOADS TRANSIENT COMMAND FILES TO THE DISK FROM THE
CURRENTLY DEFINED READER PERIPHERAL. THE LOADER PLACES THE MACHINE
CODE INTO A FILE WHICH APPEARS IN THE LOADCOM COMMAND */
DECLARE
TRUE LITERALLY '1',
FALSE LITERALLY '0',
FOREVER LITERALLY 'WHILE TRUE',
CR LITERALLY '13',
LF LITERALLY '10',
WHAT LITERALLY '63';
PRINTCHAR: PROCEDURE(CHAR);
DECLARE CHAR BYTE;
CALL MON1(2,CHAR);
END PRINTCHAR;
CRLF: PROCEDURE;
CALL PRINTCHAR(CR);
CALL PRINTCHAR(LF);
END CRLF;
PRINTNIB: PROCEDURE(N);
DECLARE N BYTE;
IF N > 9 THEN CALL PRINTCHAR(N+'A'-10); ELSE
CALL PRINTCHAR(N+'0');
END PRINTNIB;
PRINTHEX: PROCEDURE(B);
DECLARE B BYTE;
CALL PRINTNIB(SHR(B,4)); CALL PRINTNIB(B AND 0FH);
END PRINTHEX;
PRINTADDR: PROCEDURE(A);
DECLARE A ADDRESS;
CALL PRINTHEX(HIGH(A)); CALL PRINTHEX(LOW(A));
END PRINTADDR;
PRINTM: PROCEDURE(A);
DECLARE A ADDRESS;
CALL MON1(9,A);
END PRINTM;
PRINT: PROCEDURE(A);
DECLARE A ADDRESS;
/* PRINT THE STRING STARTING AT ADDRESS A UNTIL THE
NEXT DOLLAR SIGN IS ENCOUNTERED WITH PRECEDING CRLF */
CALL CRLF;
CALL PRINTM(A);
END PRINT;
DECLARE LA ADDRESS; /* CURRENT LOAD ADDRESS */
PERROR: PROCEDURE(A);
/* PRINT ERROR MESSAGE */
DECLARE A ADDRESS;
CALL PRINT(.('ERROR: $'));
CALL PRINTM(A);
CALL PRINTM(.(', LOAD ADDRESS $'));
CALL PRINTADDR(LA);
CALL BOOT;
END PERROR;
DECLARE DCNT BYTE;
OPEN: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
DCNT = MON2(15,FCB);
END OPEN;
CLOSE: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
DCNT = MON2(16,FCB);
END CLOSE;
SEARCH: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
DCNT = MON2(17,FCB);
END SEARCH;
SEARCHN: PROCEDURE;
DCNT = MON2(18,0);
END SEARCHN;
DELETE: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
CALL MON1(19,FCB);
END DELETE;
DISKREAD: PROCEDURE(FCB) BYTE;
DECLARE FCB ADDRESS;
RETURN MON2(20,FCB);
END DISKREAD;
DISKWRITE: PROCEDURE(FCB) BYTE;
DECLARE FCB ADDRESS;
RETURN MON2(21,FCB);
END DISKWRITE;
MAKE: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
DCNT = MON2(22,FCB);
END MAKE;
RENAME: PROCEDURE(FCB);
DECLARE FCB ADDRESS;
CALL MON1(23,FCB);
END RENAME;
MOVE: PROCEDURE(S,D,N);
DECLARE (S,D) ADDRESS, N BYTE,
A BASED S BYTE, B BASED D BYTE;
DO WHILE (N:=N-1) <> 255;
B = A; S=S+1; D=D+1;
END;
END MOVE;
GETCHAR: PROCEDURE BYTE;
/* GET NEXT CHARACTER */
DECLARE I BYTE;
IF (SBP := SBP+1) <= LAST(SBUFF) THEN
RETURN SBUFF(SBP);
/* OTHERWISE READ ANOTHER BUFFER FULL */
DO SBP = 0 TO LAST(SBUFF) BY 128;
IF (I:=DISKREAD(.SFCB)) = 0 THEN
CALL MOVE(80H,.SBUFF(SBP),80H); ELSE
DO;
IF I<>1 THEN CALL PERROR(.('DISK READ$'));
SBUFF(SBP) = EOFILE;
SBP = LAST(SBUFF);
END;
END;
SBP = 0; RETURN SBUFF(0);
END GETCHAR;
DECLARE
STACKPOINTER LITERALLY 'STACKPTR';
/* INTEL HEX FORMAT LOADER */
RELOC: PROCEDURE;
DECLARE (RL, CS, RT) BYTE;
DECLARE
TA ADDRESS, /* TEMP ADDRESS */
SA ADDRESS, /* START ADDRESS */
FA ADDRESS, /* FINAL ADDRESS */
NB ADDRESS, /* NUMBER OF BYTES LOADED */
MBUFF(256) BYTE,
P BYTE,
L ADDRESS;
SETMEM: PROCEDURE(B);
/* SET MBUFF TO B AT LOCATION LA MOD LENGTH(MBUFF) */
DECLARE (B,I) BYTE;
IF LA < L THEN
CALL PERROR(.('INVERTED LOAD ADDRESS$'));
DO WHILE LA > L + LAST(MBUFF); /* WRITE A PARAGRAPH */
DO I = 0 TO 127; /* COPY INTO BUFFER */
BUFFER(I) = MBUFF(LOW(L)); L = L + 1;
END;
/* WRITE BUFFER ONTO DISK */
P = P + 1;
IF DISKWRITE(FCBA) <> 0 THEN
DO; CALL PERROR(.('DISK WRITE$'));
END;
END;
MBUFF(LOW(LA)) = B;
END SETMEM;
DIAGNOSE: PROCEDURE;
DECLARE M BASED TA BYTE;
NEWLINE: PROCEDURE;
CALL CRLF; CALL PRINTADDR(TA); CALL PRINTCHAR(':');
CALL PRINTCHAR(' ');
END NEWLINE;
/* PRINT DIAGNOSTIC INFORMATION AT THE CONSOLE */
CALL PRINT(.('LOAD ADDRESS $')); CALL PRINTADDR(TA);
CALL PRINT(.('ERROR ADDRESS $')); CALL PRINTADDR(LA);
CALL PRINT(.('BYTES READ:$')); CALL NEWLINE;
DO WHILE TA < LA;
IF (LOW(TA) AND 0FH) = 0 THEN CALL NEWLINE;
CALL PRINTHEX(MBUFF(TA-L)); TA=TA+1;
CALL PRINTCHAR(' ');
END;
CALL CRLF;
CALL BOOT;
END DIAGNOSE;
READHEX: PROCEDURE BYTE;
/* READ ONE HEX CHARACTER FROM THE INPUT */
DECLARE H BYTE;
IF (H := GETCHAR) - '0' <= 9 THEN RETURN H - '0';
IF H - 'A' > 5 THEN
DO; CALL PRINT(.('INVALID HEX DIGIT$'));
CALL DIAGNOSE;
END;
RETURN H - 'A' + 10;
END READHEX;
READBYTE: PROCEDURE BYTE;
/* READ TWO HEX DIGITS */
RETURN SHL(READHEX,4) OR READHEX;
END READBYTE;
READCS: PROCEDURE BYTE;
/* READ BYTE WHILE COMPUTING CHECKSUM */
DECLARE B BYTE;
CS = CS + (B := READBYTE);
RETURN B;
END READCS;
MAKE$DOUBLE: PROCEDURE(H,L) ADDRESS;
/* CREATE A BOUBLE BYTE VALUE FROM TWO SINGLE BYTES */
DECLARE (H,L) BYTE;
RETURN SHL(DOUBLE(H),8) OR L;
END MAKE$DOUBLE;
/* INITIALIZE */
SA, FA, NB = 0;
P = 0; /* PARAGRAPH COUNT */
TA,L = TPA; /* BASE ADDRESS OF TRANSIENT ROUTINES */
SBUFF(0) = EOFILE;
/* READ RECORDS UNTIL :00XXXX IS ENCOUNTERED */
DO FOREVER;
/* SCAN THE : */
DO WHILE GETCHAR <> ':';
END;
/* SET CHECK SUM TO ZERO, AND SAVE THE RECORD LENGTH */
CS = 0;
/* MAY BE THE END OF TAPE */
IF (RL := READCS) = 0 THEN
GO TO FIN;
NB = NB + RL;
TA, LA = MAKE$DOUBLE(READCS,READCS);
IF SA = 0 THEN SA = LA;
/* READ THE RECORD TYPE (NOT CURRENTLY USED) */
RT = READCS;
/* PROCESS EACH BYTE */
DO WHILE (RL := RL - 1) <> 255;
CALL SETMEM(READCS); LA = LA+1;
END;
IF LA > FA THEN FA = LA - 1;
/* NOW READ CHECKSUM AND COMPARE */
IF CS + READBYTE <> 0 THEN
DO; CALL PRINT(.('CHECK SUM ERROR $'));
CALL DIAGNOSE;
END;
END;
FIN:
/* EMPTY THE BUFFERS */
TA = LA;
DO WHILE L < TA;
CALL SETMEM(0); LA = LA+1;
END;
/* PRINT FINAL STATISTICS */
CALL PRINT(.('FIRST ADDRESS $')); CALL PRINTADDR(SA);
CALL PRINT(.('LAST ADDRESS $')); CALL PRINTADDR(FA);
CALL PRINT(.('BYTES READ $')); CALL PRINTADDR(NB);
CALL PRINT(.('RECORDS WRITTEN $')); CALL PRINTHEX(P);
CALL CRLF;
END RELOC;
/* ARRIVE HERE FROM THE SYSTEM MONITOR, READY TO READ THE HEX TAPE */
/* SET UP STACKPOINTER IN THE LOCAL AREA */
DECLARE STACK(16) ADDRESS;
SP = STACKPOINTER; STACKPOINTER = .STACK(LENGTH(STACK));
LA = TPA;
SBP = LENGTH(SBUFF);
/* SET UP THE SOURCE FILE */
CALL MOVE(FCBA,.SFCB,33);
CALL MOVE(.('HEX',0),.SFCB(9),4);
CALL OPEN(.SFCB);
IF DCNT = 255 THEN CALL PERROR(.('CANNOT OPEN SOURCE$'));
CALL MOVE(.('COM'),FCBA+9,3);
/* REMOVE ANY EXISTING FILE BY THIS NAME */
CALL DELETE(FCBA);
/* THEN OPEN A NEW FILE */
CALL MAKE(FCBA); CALL OPEN(FCBA);
IF DCNT = 255 THEN CALL PERROR(.('NO MORE DIRECTORY SPACE$')); ELSE
DO; CALL RELOC;
CALL CLOSE(FCBA);
IF DCNT = 255 THEN CALL PERROR(.('CANNOT CLOSE FILE$'));
END;
CALL CRLF;
CALL BOOT;
END LOADCOM;
END;


View File

@@ -0,0 +1,28 @@
era *.lst
era *.lin
era *.sym
era *.bak
pip a:=e:load.plm
seteof load.plm
isx
plm80 load.plm pagewidth(80) debug
cpm
vax load.lst $$stan
isx
link load.obj,x0100,plm80.lib to xload.mod
locate xload.mod code(0100H) stacksize(48)
era xload.mod
cpm
objcpm xload
ren load.sym=xload.sym
ren load.lin=xload.lin
vax load.sym $$stan
vax load.lin $$stan
pip e:load.com=a:xload.com
pip b:load.com=a:xload.com
era load.lin
era load.sym
era load.lst
era xload.*
;end load submit