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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
rmac bnkbdos
xref bnkbdos
era bnkbdos.prn
vax bnkbdos.xrf $$STRAnp
era bnkbdos.xrf
link bnkbdos[os]
era bnkbdos.rel
era bnkbdos.sym
gensys $$a
pip d:[g0]=mpm.sys


View File

@@ -0,0 +1,96 @@
; MDS-800 Cold Start Loader for MP/M 2.0
;
; VERSION 2.0 09/1481
;
mpmldrb equ 0100h ;base of MP/M loader
;
org 3000h ;loaded here by hardware
;
ntrks equ 2 ;tracks to read
mpmldr0 equ 25 ;# on track 0
mpmldr1 equ 26 ;# on track 1
;
rmon80 equ 0ff0fh ;restart location for mon80
base equ 078h ;'base' used by controller
rtype equ base+1 ;result type
rbyte equ base+3 ;result byte
reset equ base+7 ;reset controller
;
dstat equ base ;disk status port
ilow equ base+1 ;low iopb address
ihigh equ base+2 ;high iopb address
bsw equ 0ffh ;boot switch
readf equ 4h ;disk read function
stack equ 100h ;use end of boot for stack
;
rstart:
lxi sp,stack;in case of call to mon80
; clear disk status
in rtype
in rbyte
; check if boot switch is off
coldstart:
in bsw
ani 02h ;switch on?
jnz coldstart
; clear the controller
out reset ;logic cleared
;
;
mvi b,ntrks ;number of tracks to read
lxi h,iopb0
;
start:
;
; read first/next track into cpmb
mov a,l
out ilow
mov a,h
out ihigh
wait0: in dstat
ani 4
jz wait0
;
; check disk status
in rtype
ani 11b
cpi 2
;
jnc rstart ;retry the load
;
in rbyte ;i/o complete, check status
; if not ready, then go to mon80
ral
cc rmon80 ;not ready bit set
rar ;restore
ani 11110b ;overrun/addr err/seek/crc/xxxx
;
jnz rstart ;retry the load
;
;
lxi d,iopbl ;length of iopb
dad d ;addressing next iopb
dcr b ;count down tracks
jnz start
;
;
; jmp to the MP/M loader
jmp mpmldrb
;
; parameter blocks
iopb0: db 80h ;iocw, no update
db readf ;read function
db mpmldr0 ;# sectors to read trk 0
db 0 ;track 0
db 2 ;start with sector 2, trk 0
dw mpmldrb ;start at base of bdos
iopbl equ $-iopb0
;
iopb1: db 80h
db readf
db mpmldr1 ;sectors to read on track 1
db 1 ;track 1
db 1 ;sector 1
dw mpmldrb+mpmldr0*128 ;base of second read
end


View File

@@ -0,0 +1,15 @@
; MACRO LIBRARY FOR PEDESTRIAN PUSHBUTTONS
;
CWINP EQU 00H ;INPUT PORT FOR CROSSWALK
;
PUSH? MACRO IFTRUE
;; "PUSH?" JUMPS TO LABEL "IFTRUE" WHEN ANY ONE
;; OF THE CROSSWALK SWITCHES IS DEPRESSED. THE
;; VALUE HAS BEEN LATCHED, AND READING THE PORT
;; CLEARS THE LATCHED VALUES
IN CWINP ;;READ THE CROSSWALK SWITCHES
ANI (1 SHL CWCNT) - 1 ;;BUILD MASK
JNZ IFTRUE ;;ANY SWITCHES SET?
;; CONTINUE ON FALSE CONDITION
ENDM


View File

@@ -0,0 +1,59 @@
; MACRO LIBRARY FOR 8-BIT COMPARISON OPERATION
;
TEST? MACRO X,Y
;; UTILTITY MACRO TO GENERATE CONDITION CODES
IF NOT NUL X ;;THEN LOAD X
LDA X ;;X ASSUMED TO BE IN MEMORY
ENDIF
IRPC ?Y,Y ;;Y MAY BE CONSTANT OPERAND
TDIG? SET '&?Y'-'0' ;;FIRST CHAR DIGIT?
EXITM ;;STOP IRPC AFTER FIRST CHAR
ENDM
IF TDIG? <= 9 ;;Y NUMERIC?
SUI Y ;;YES, SO SUB IMMEDIATE
ELSE
LXI H,Y ;;Y NOT NUMERIC
SUB M ;;SO SUB FROM MEMORY
ENDM
;
LSS MACRO X,Y,TL
;; X LSS THAN Y TEST,
;; TRANSFER TO TL (TRUE LABEL) IF TRUE,
;; CONTINUE IF TEST IS FALSE
TEST? X,Y ;;SET CONDITION CODES
JC TL
ENDM
;
LEQ MACRO X,Y,TL
;; X LESS THAN OR EQUAL TO Y TEST
LSS X,Y,TL
JZ TL
ENDM
;
EQL MACRO X,Y,TL
;; X EQUAL TO Y TEST
TEST? X,Y
JZ TL
ENDM
;
NEQ MACRO X,Y,TL
;; X NOT EQUAL TO Y TEST
TEST? X,Y
JNZ TL
ENDM
;
GEQ MACRO X,Y,TL
;; X GREATER THAN OR EQUAL TO Y TEST
TEST? X,Y
JNC TL
ENDM
;
GTR MACRO X,Y,TL
;; X GREATER THAN Y TEST
LOCAL FL ;;FALSE LABEL
TEST? X,Y
JC FL
DCR A
JNC TL
FL: ENDM


View File

@@ -0,0 +1,388 @@
;*********************************************************
;* *
;* Sector Deblocking Algorithms for MP/M II V2.0 *
;* *
;*********************************************************
;
; utility macro to compute sector mask
smask macro hblk
;; compute log2(hblk), return @x as result
;; (2 ** @x = hblk on return)
@y set hblk
@x set 0
;; count right shifts of @y until = 1
rept 8
if @y = 1
exitm
endif
;; @y is not 1, shift right one position
@y set @y shr 1
@x set @x + 1
endm
endm
;
;*****************************************************
;* *
;* MP/M to host disk constants *
;* *
;*****************************************************
blksiz equ 2048 ;MP/M allocation size
hstsiz equ 512 ;host disk sector size
hstspt equ 20 ;host disk sectors/trk
hstblk equ hstsiz/128 ;MP/M sects/host buff
cpmspt equ hstblk * hstspt ;MP/M sectors/track
secmsk equ hstblk-1 ;sector mask
smask hstblk ;compute sector mask
secshf equ @x ;log2(hstblk)
;
;*****************************************************
;* *
;* BDOS constants on entry to write *
;* *
;*****************************************************
wrall equ 0 ;write to allocated
wrdir equ 1 ;write to directory
wrual equ 2 ;write to unallocated
;
;*****************************************************
;* *
;* The BDOS entry points given below show the *
;* code which is relevant to deblocking only. *
;* *
;*****************************************************
;
; DISKDEF macro, or hand coded tables go here
dpbase equ $ ;disk param block base
;
boot:
wboot:
;enter here on system boot to initialize
xra a ;0 to accumulator
sta hstact ;host buffer inactive
sta unacnt ;clear unalloc count
ret
;
home:
;home the selected disk
lda hstwrt ;check for pending write
ora a
jnz homed
sta hstact ;clear host active flag
homed:
ret
;
seldsk:
;select disk
mov a,c ;selected disk number
sta sekdsk ;seek disk number
mov l,a ;disk number to HL
mvi h,0
rept 4 ;multiply by 16
dad h
endm
lxi d,dpbase ;base of parm block
dad d ;hl=.dpb(curdsk)
ret
;
settrk:
;set track given by registers BC
mov h,b
mov l,c
shld sektrk ;track to seek
ret
;
setsec:
;set sector given by register c
mov a,c
sta seksec ;sector to seek
ret
;
setdma:
;set dma address given by BC
mov h,b
mov l,c
shld dmaadr
ret
;
sectran:
;translate sector number BC
mov h,b
mov l,c
ret
;
;*****************************************************
;* *
;* The READ entry point takes the place of *
;* the previous BIOS defintion for READ. *
;* *
;*****************************************************
read:
;read the selected MP/M sector
xra a
sta unacnt ;unacnt = 0
inr a
sta readop ;read operation
sta rsflag ;must read data
mvi a,wrual
sta wrtype ;treat as unalloc
jmp rwoper ;to perform the read
;
;*****************************************************
;* *
;* The WRITE entry point takes the place of *
;* the previous BIOS defintion for WRITE. *
;* *
;*****************************************************
write:
;write the selected MP/M sector
xra a ;0 to accumulator
sta readop ;not a read operation
mov a,c ;write type in c
sta wrtype
ani wrual ;write unallocated?
jz chkuna ;check for unalloc
;
; write to unallocated, set parameters
mvi a,blksiz/128 ;next unalloc recs
sta unacnt
lda sekdsk ;disk to seek
sta unadsk ;unadsk = sekdsk
lhld sektrk
shld unatrk ;unatrk = sectrk
lda seksec
sta unasec ;unasec = seksec
;
chkuna:
;check for write to unallocated sector
lda unacnt ;any unalloc remain?
ora a
jz alloc ;skip if not
;
; more unallocated records remain
dcr a ;unacnt = unacnt-1
sta unacnt
lda sekdsk ;same disk?
lxi h,unadsk
cmp m ;sekdsk = unadsk?
jnz alloc ;skip if not
;
; disks are the same
lxi h,unatrk
call sektrkcmp ;sektrk = unatrk?
jnz alloc ;skip if not
;
; tracks are the same
lda seksec ;same sector?
lxi h,unasec
cmp m ;seksec = unasec?
jnz alloc ;skip if not
;
; match, move to next sector for future ref
inr m ;unasec = unasec+1
mov a,m ;end of track?
cpi cpmspt ;count MP/M sectors
jc noovf ;skip if no overflow
;
; overflow to next track
mvi m,0 ;unasec = 0
lhld unatrk
inx h
shld unatrk ;unatrk = unatrk+1
;
noovf:
;match found, mark as unnecessary read
xra a ;0 to accumulator
sta rsflag ;rsflag = 0
jmp rwoper ;to perform the write
;
alloc:
;not an unallocated record, requires pre-read
xra a ;0 to accum
sta unacnt ;unacnt = 0
inr a ;1 to accum
sta rsflag ;rsflag = 1
;
;*****************************************************
;* *
;* Common code for READ and WRITE follows *
;* *
;*****************************************************
rwoper:
;enter here to perform the read/write
xra a ;zero to accum
sta erflag ;no errors (yet)
lda seksec ;compute host sector
rept secshf
ora a ;carry = 0
rar ;shift right
endm
sta sekhst ;host sector to seek
;
; active host sector?
lxi h,hstact ;host active flag
mov a,m
mvi m,1 ;always becomes 1
ora a ;was it already?
jz filhst ;fill host if not
;
; host buffer active, same as seek buffer?
lda sekdsk
lxi h,hstdsk ;same disk?
cmp m ;sekdsk = hstdsk?
jnz nomatch
;
; same disk, same track?
lxi h,hsttrk
call sektrkcmp ;sektrk = hsttrk?
jnz nomatch
;
; same disk, same track, same buffer?
lda sekhst
lxi h,hstsec ;sekhst = hstsec?
cmp m
jz match ;skip if match
;
nomatch:
;proper disk, but not correct sector
lda hstwrt ;host written?
ora a
cnz writehst ;clear host buff
;
filhst:
;may have to fill the host buffer
lda sekdsk
sta hstdsk
lhld sektrk
shld hsttrk
lda sekhst
sta hstsec
lda rsflag ;need to read?
ora a
cnz readhst ;yes, if 1
xra a ;0 to accum
sta hstwrt ;no pending write
;
match:
;copy data to or from buffer
lda seksec ;mask buffer number
ani secmsk ;least signif bits
mov l,a ;ready to shift
mvi h,0 ;double count
rept 7 ;shift left 7
dad h
endm
; hl has relative host buffer address
lxi d,hstbuf
dad d ;hl = host address
xchg ;now in DE
lhld dmaadr ;get/put MP/M data
mvi c,128 ;length of move
lda readop ;which way?
ora a
jnz rwmove ;skip if read
;
; write operation, mark and switch direction
mvi a,1
sta hstwrt ;hstwrt = 1
xchg ;source/dest swap
;
rwmove:
;C initially 128, DE is source, HL is dest
ldax d ;source character
inx d
mov m,a ;to dest
inx h
dcr c ;loop 128 times
jnz rwmove
;
; data has been moved to/from host buffer
lda wrtype ;write type
ani wrdir ;to directory?
lda erflag ;in case of errors
rz ;no further processing
;
; clear host buffer for directory write
ora a ;errors?
rnz ;skip if so
xra a ;0 to accum
sta hstwrt ;buffer written
call writehst
lda erflag
ret
;
;*****************************************************
;* *
;* Utility subroutine for 16-bit compare *
;* *
;*****************************************************
sektrkcmp:
;HL = .unatrk or .hsttrk, compare with sektrk
xchg
lxi h,sektrk
ldax d ;low byte compare
cmp m ;same?
rnz ;return if not
; low bytes equal, test high 1s
inx d
inx h
ldax d
cmp m ;sets flags
ret
;
;*****************************************************
;* *
;* WRITEHST performs the physical write to *
;* the host disk, READHST reads the physical *
;* disk. *
;* *
;*****************************************************
writehst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. write "hstsiz" bytes
;from hstbuf and return error flag in erflag.
;return erflag non-zero if error
ret
;
readhst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. read "hstsiz" bytes
;into hstbuf and return error flag in erflag.
ret
;
;*****************************************************
;* *
;* Unitialized RAM data areas *
;* *
;*****************************************************
;
sekdsk: ds 1 ;seek disk number
sektrk: ds 2 ;seek track number
seksec: ds 1 ;seek sector number
;
hstdsk: ds 1 ;host disk number
hsttrk: ds 2 ;host track number
hstsec: ds 1 ;host sector number
;
sekhst: ds 1 ;seek shr secshf
hstact: ds 1 ;host active flag
hstwrt: ds 1 ;host written flag
;
unacnt: ds 1 ;unalloc rec cnt
unadsk: ds 1 ;last unalloc disk
unatrk: ds 2 ;last unalloc track
unasec: ds 1 ;last unalloc sector
;
erflag: ds 1 ;error reporting
rsflag: ds 1 ;read sector flag
readop: ds 1 ;1 if read operation
wrtype: ds 1 ;write operation type
dmaadr: ds 2 ;last dma address
hstbuf: ds hstsiz ;host buffer
;
;*****************************************************
;* *
;* The ENDEF macro invocation goes here *
;* *
;*****************************************************
end


View File

@@ -0,0 +1,35 @@
File: Contents:
RMAC.COM "RMAC" Relocating Macro Assembler
LINK.COM Linkage Editor
LIB.COM Library Manager
XREF.COM Cross Reference Utility
I8085.LIB Simple macros for 8085 RIM/SIM instructions
Z80.LIB Macro lirary for Z80 operation codes
Z80.DOC Documentation for the Z80.LIB file
INTER.LIB Traffic light intersection library (see manual)
TREADLES.LIB Library for traffic treadles
BUTTONS.LIB Library for pedestrian pushbuttons
SIMPIO.LIB Simple BDOS I/O Library
SEQIO.LIB Sequential file I/O library
STACK.LIB Simple stack machine library
DSTACK.LIB Complete stack machine library
COMPARE.LIB Library for simple 8-bit comparison operations
NCOMPARE.LIB 8-bit comparisons with negation
WHEN.LIB Macros for the WHEN construct (see manual)
DOWHILE.LIB Macros for the DOWHILE contstruct
SELECT.LIB Macros for the SELECT construct
LDRBIOS.ASM Sample Loader BIOS for MP/M II MPMLDR
BOOT.ASM Sample Boot for MP/M II
DEBLOCK.ASM Sample Deblocking algorithm for MP/M II
TODCNV.ASM Sample Time & Date Conversion for MP/M II
RESXIOS.ASM Sample Resident XIOS for MP/M II
DUMP.ASM Sample PRL for MP/M II
EXTRN.ASM Sample External module for DUMP.ASM


View File

@@ -0,0 +1,257 @@
; MP/M II V2.0 disk re-definition library
;
; Copyright (c) 1979, 1980, 1981
; Digital Research
; Box 579
; Pacific Grove, CA
; 93950
;
; MP/M II logical disk drives are defined using the
; macros given below, where the sequence of calls
; is:
;
; disks n
; diskdef parameter-list-0
; diskdef parameter-list-1
; ...
; diskdef parameter-list-n
; endef
;
; where n is the number of logical disk drives attached
; to the MP/M II system, and parameter-list-i defines the
; characteristics of the ith drive (i=0,1,...,n-1)
;
; each parameter-list-i takes the form
; dn,fsc,lsc,[skf],bls,dks,dir,cks,ofs,[k16],[prm]
; where
; dn is the disk number 0,1,...,n-1
; fsc is the first sector number (usually 0 or 1)
; lsc is the last sector number on a track
; skf is optional "skew factor" for sector translate
; bls is the data block size (1024,2048,...,16384)
; dks is the disk size in bls increments (word)
; dir is the number of directory elements (word)
; cks is the number of dir elements to checksum
; ofs is the number of tracks to skip (word)
; k16 is an optional 0 which forces 16K/directory entry
; prm is an optional 0 which marks drive as permanent
;
; for convenience, the form
; dn,dm
; defines disk dn as having the same characteristics as
; a previously defined disk dm.
;
; a standard four drive MP/M II system is defined by
; disks 4
; diskdef 0,1,26,6,1024,243,64,64,2
; dsk set 0
; rept 3
; dsk set dsk+1
; diskdef %dsk,0
; endm
; endef
;
; the value of "begdat" at the end of assembly defines the
; beginning of the uninitialize ram area above the bios,
; while the value of "enddat" defines the next location
; following the end of the data area. the size of this
; area is given by the value of "datsiz" at the end of the
; assembly. note that the allocation vector will be quite
; large if a large disk size is defined with a small block
; size.
;
dskhdr macro dn
;; define a single disk header list
dpe&dn: dw xlt&dn,0000h ;translate table
dw 0000h,0000h ;scratch area
dw dirbuf,dpb&dn ;dir buff,parm block
dw csv&dn,alv&dn ;check, alloc vectors
endm
;
disks macro nd
;; define nd disks
ndisks set nd ;;for later reference
dpbase equ $ ;base of disk parameter blocks
;; generate the nd elements
dsknxt set 0
rept nd
dskhdr %dsknxt
dsknxt set dsknxt+1
endm
endm
;
dpbhdr macro dn
dpb&dn equ $ ;disk parm block
endm
;
ddb macro data,comment
;; define a db statement
db data comment
endm
;
ddw macro data,comment
;; define a dw statement
dw data comment
endm
;
gcd macro m,n
;; greatest common divisor of m,n
;; produces value gcdn as result
;; (used in sector translate table generation)
gcdm set m ;;variable for m
gcdn set n ;;variable for n
gcdr set 0 ;;variable for r
rept 65535
gcdx set gcdm/gcdn
gcdr set gcdm - gcdx*gcdn
if gcdr = 0
exitm
endif
gcdm set gcdn
gcdn set gcdr
endm
endm
;
diskdef macro dn,fsc,lsc,skf,bls,dks,dir,cks,ofs,k16,prm
;; generate the set statements for later tables
if nul lsc
;; current disk dn same as previous fsc
dpb&dn equ dpb&fsc ;equivalent parameters
als&dn equ als&fsc ;same allocation vector size
css&dn equ css&fsc ;same checksum vector size
xlt&dn equ xlt&fsc ;same translate table
else
cksz set (cks)/4
secmax set lsc-(fsc) ;;sectors 0...secmax
sectors set secmax+1;;number of sectors
als&dn set (dks)/8 ;;size of allocation vector
if ((dks) mod 8) ne 0
als&dn set als&dn+1
endif
css&dn set cksz ;;number of checksum elements
;; generate the block shift value
blkval set bls/128 ;;number of sectors/block
blkshf set 0 ;;counts right 0's in blkval
blkmsk set 0 ;;fills with 1's from right
rept 16 ;;once for each bit position
if blkval=1
exitm
endif
;; otherwise, high order 1 not found yet
blkshf set blkshf+1
blkmsk set (blkmsk shl 1) or 1
blkval set blkval/2
endm
;; generate the extent mask byte
blkval set bls/1024 ;;number of kilobytes/block
extmsk set 0 ;;fill from right with 1's
rept 16
if blkval=1
exitm
endif
;; otherwise more to shift
extmsk set (extmsk shl 1) or 1
blkval set blkval/2
endm
;; may be double byte allocation
if (dks) > 256
extmsk set (extmsk shr 1)
endif
;; may be optional [0] in last position
if not nul k16
extmsk set k16
endif
;; now generate directory reservation bit vector
dirrem set dir ;;# remaining to process
dirbks set bls/32 ;;number of entries per block
dirblk set 0 ;;fill with 1's on each loop
rept 16
if dirrem=0
exitm
endif
;; not complete, iterate once again
;; shift right and add 1 high order bit
dirblk set (dirblk shr 1) or 8000h
if dirrem > dirbks
dirrem set dirrem-dirbks
else
dirrem set 0
endif
endm
dpbhdr dn ;;generate equ $
ddw %sectors,<;sec per track>
ddb %blkshf,<;block shift>
ddb %blkmsk,<;block mask>
ddb %extmsk,<;extnt mask>
ddw %(dks)-1,<;disk size-1>
ddw %(dir)-1,<;directory max>
ddb %dirblk shr 8,<;alloc0>
ddb %dirblk and 0ffh,<;alloc1>
if nul prm
ddw %(cks)/4,<;check size>
else
ddw 8000h+cksz,<;permanent disk with check size>
endif
ddw %ofs,<;offset>
;; generate the translate table, if requested
if nul skf
xlt&dn equ 0 ;no xlate table
else
if skf = 0
xlt&dn equ 0 ;no xlate table
else
;; generate the translate table
nxtsec set 0 ;;next sector to fill
nxtbas set 0 ;;moves by one on overflow
gcd %sectors,skf
;; gcdn = gcd(sectors,skew)
neltst set sectors/gcdn
;; neltst is number of elements to generate
;; before we overlap previous elements
nelts set neltst ;;counter
xlt&dn equ $ ;translate table
rept sectors ;;once for each sector
if sectors < 256
ddb %nxtsec+(fsc)
else
ddw %nxtsec+(fsc)
endif
nxtsec set nxtsec+(skf)
if nxtsec >= sectors
nxtsec set nxtsec-sectors
endif
nelts set nelts-1
if nelts = 0
nxtbas set nxtbas+1
nxtsec set nxtbas
nelts set neltst
endif
endm
endif ;;end of nul fac test
endif ;;end of nul bls test
endm
;
defds macro lab,space
lab: ds space
endm
;
lds macro lb,dn,val
defds lb&dn,%val&dn
endm
;
endef macro
;; generate the necessary ram data areas
begdat equ $
dirbuf: ds 128 ;directory access buffer
dsknxt set 0
rept ndisks ;;once for each disk
lds alv,%dsknxt,als
lds csv,%dsknxt,css
dsknxt set dsknxt+1
endm
enddat equ $
datsiz equ $-begdat
force: db 0 ;force out last byte in hex file
endm
;


View File

@@ -0,0 +1,41 @@
; MACRO LIBRARY FOR "DOWHILE" CONSTRUCT
;
GENDTST MACRO TST,X,Y,NUM
;; GENERATE A "DOWHILE" TEST
TST X,Y,,ENDD&NUM
ENDM
;
GENDLAB MACRO LAB,NUM
;; PRODUCE THE LABEL LAB & NUM
;; FOR DOWHILE ENTRY OR EXIT
LAB&NUM:
ENDM
;
GENDJMP MACRO NUM
;; GENERATE JUMP TO DOWHILE TEST
JMP DTEST&NUM
ENDM
;
DOWHILE MACRO XV,REL,YV
;; INITIALIZE COUNTER
DOCNT SET 0 ;NUMBER OF DOWHILES
;;
DOWHILE MACRO X,R,Y
;; GENERATE THE DOWHILE ENTRY
GENDLAB DTEST,%DOCNT
;; GENERATE THE CONDITIONAL TEST
GENDTST R,X,Y,%DOCNT
DOLEV SET DOCNT ;;NEXT ENDD TO GENERATE
DOCNT SET DOCNT+1
ENDM
DOWHILE XV,REL,YV
ENDM
;
ENDDO MACRO
;; GENERATE THE JUMP TO THE TEST
GENDJMP %DOLEV
;; GENERATE THE END OF A DOWHILE
GENDLAB ENDD,%DOLEV
DOLEV SET DOLEV-1
ENDM


View File

@@ -0,0 +1,468 @@
; MACRO LIBRARY FOR A ZERO ADDRESS MACHINE
; *****************************************
; * BEGIN TRACE/DUMP UTILITIES *
; *****************************************
BDOS EQU 0005H ;SYSTEM ENTRY
RCHAR EQU 1 ;READ A CHARACTER
WCHAR EQU 2 ;WRITE CHARACTER
WBUFF EQU 9 ;WRITE BUFFER
TRAN EQU 100H ;TRANSIENT PROGRAM AREA
DATA EQU 1100H ;DATA AREA
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
DEBUGT SET 0 ;;TRACE DEBUG SET FALSE
DEBUGP SET 0 ;;PRINT DEBUG SET FALSE
;
PRN MACRO PR
;; PRINT MESSAGE 'PR' AT CONSOLE
IF DEBUGP ;;PRINT DEBUG ON?
LOCAL PMSG,MSG ;;LOCAL MESSAGE
JMP PMSG ;;AROUND MESSAGE
MSG: DB CR,LF ;;RETURN CARRIAGE
DB '&PR$' ;;LITERAL MESSAGE
PMSG: PUSH H ;;SAVE TOP ELEMENT OF STACK
LXI D,MSG ;;LOCAL MESSAGE ADDRESS
MVI C,WBUFF ;;WRITE BUFFER 'TIL $
CALL BDOS ;;PRINT IT
POP H ;;RESTORE TOP OF STACK
ENDIF ;;END TEST DEBUGP
ENDM
;
UGEN MACRO
;; GENERATE UTILITIES FOR TRACE OR DUMP
LOCAL PSUB
JMP PSUB ;;JUMP PAST SUBROUTINES
@CH: ;;WRITE CHARACTER IN REG-A
MOV E,A
MVI C,WCHAR
JMP BDOS ;;RETURN THRU BDOS
;;
@NB: ;;WRITE NIBBLE IN REG-A
ADI 90H
DAA
ACI 40H
DAA
JMP @CH ;;RETURN THRU @CH
;;
@HX: ;;WRITE HEX VALUE IN REG-A
PUSH PSW ;;SAVE LOW BYTE
RRC
RRC
RRC
RRC
ANI 0FH ;;MASK HIGH NIBBLE
CALL @NB ;;PRINT HIGH NIBBLE
POP PSW
ANI 0FH
JMP @NB ;;PRINT LOW NIBBLE
;;
@AD ;;WRITE ADDRESS VALUE IN HL
PUSH H ;;SAVE VALUE
MVI A,' ' ;;LEADING BLANK
CALL @CH ;;AHEAD OF ADDRESS
POP H ;;HIGH BYTE TO A
MOV A,H
PUSH H ;;COPY BACK TO STACK
CALL @HX ;;WRITE HIGH BYTE
POP H
MOV A,L ;;LOW BYTE
JMP @HX ;;WRITE LOW BYTE
;
@IN: ;;READ HEX VALUE TO HL FROM CONSOLE
MVI A,' ' ;;LEADING SPACE
CALL @CH ;;TO CONSOLE
LXI H,0 ;;STARTING VALUE
@IN0: PUSH H ;;SAVE IT FOR CHAR READ
MVI C,RCHAR ;;READ CHARACTER FUNCTION
CALL BDOS ;;READ TO ACCUMULATOR
POP H ;;VALUE BEING BUILT IN HL
SUI '0' ;;NORMALIZE TO BINARY
CPI 10 ;;DECIMAL?
JC @IN1 ;;CARRY IF 0,1,...,9
;; MAY BE HEXADECIMAL A,...,F
SUI 'A'-'0'-10
CPI 16 ;;A THROUGH F?
RNC ;;RETURN WITH ASSUMED CR
@IN1: ;;IN RANGE, MULTIPLY BY 4 AND ADD
REPT 4
DAD H ;;SHIFT 4
ENDM
ORA L ;;ADD DIGIT
MOV L,A ;;AND REPLACE VALUE
JMP @IN0 ;;FOR ANOTHER DIGIT
;;
PSUB:
UGEN MACRO
;; REDEF TO INCLUDE ONCE
ENDM
UGEN ;;GENERATE FIRST TIME
ENDM
; *****************************************
; * END OF TRACE/DUMP UTILITIES *
; * BEGIN TRACE(ONLY) UTILITIES *
; *****************************************
TRACE MACRO CODE,MNAME
;; TRACE MACRO GIVEN BY MNAME,
;; AT LOCATION GIVEN BY CODE
LOCAL PSUB
UGEN ;;GENERATE UTILITIES
JMP PSUB
@T1: DS 2 ;;TEMP FOR REG-1
@T2: DS 2 ;;TEMP FOR REG-2
;;
@TR: ;;TRACE MACRO CALL
;; BC=CODE ADDRESS, DE=MESSAGE
SHLD @T1 ;;STORE TOP REG
POP H ;;RETURN ADDRESS
XTHL ;;REG-2 TO TOP
SHLD @T2 ;;STORE TO TEMP
PUSH PSW ;;SAVE FLAGS
PUSH B ;;SAVE RET ADDRESS
MVI C,WBUFF ;;PRINT BUFFER FUNC
CALL BDOS ;;PRINT MACRO NAME
POP H ;;CODE ADDRESS
CALL @AD ;;PRINTED
LHLD @T1 ;;TOP OF STACK
CALL @AD ;;PRINTED
LHLD @T2 ;;TOP-1
CALL @AD ;;PRINTED
POP PSW ;;FLAGS RESTORED
POP D ;;RETURN ADDRESS
LHLD @T2 ;;TOP-1
PUSH H ;;RESTORED
PUSH D ;;RETURN ADDRESS
LHLD @T1 ;;TOP OF STACK
RET
;;
PSUB: ;;PAST SUBROUTINES
;;
TRACE MACRO C,M
;; REDEFINED TRACE, USES @TR
LOCAL PMSG,MSG
JMP PMSG
MSG: DB CR,LF ;;CR,LF
DB '&M$' ;;MAC NAME
PMSG:
LXI B,C ;;CODE ADDRESS
LXI D,MSG ;;MACRO NAME
CALL @TR ;;TO TRACE IT
ENDM
;; BACK TO ORIGINAL MACRO LEVEL
TRACE CODE,MNAME
ENDM
;
TRT MACRO F
;; TURN ON FLAG "F"
DEBUG&F SET 1 ;;PRINT/TRACE ON
ENDM
;
TRF MACRO F
;; TURN OFF FLAG "F"
DEBUG&F SET 0 ;;TRACE/PRINT OFF
ENDM
;
?TR MACRO M
;; CHECK DEBUGT TOGGLE BEFORE TRACE
IF DEBUGT
TRACE %$,M
ENDM
; *****************************************
; * END TRACE (ONLY) UTILITIES *
; * BEGIN DUMP(ONLY) UTILITIES *
; *****************************************
DMP MACRO VNAME,N
;; DUMP VARIABLE VNAME FOR
;; N ELEMENTS (DOUBLE BYTES)
LOCAL PSUB ;;PAST SUBROUTINES
UGEN ;;GEN INLINE ROUTINES
JMP PSUB ;;PAST LOCAL SUBROUTINES
@DM: ;;DUMP UTILITY PROGRAM
;; DE=MSG ADDRESS, C=ELEMENT COUNT
;; HL=BASE ADDRESS TO PRINT
PUSH H ;;BASE ADDRESS
PUSH B ;;ELEMENT COUNT
MVI C,WBUFF ;;WRITE BUFFER FUNC
CALL BDOS ;;MESSAGE WRITTEN
@DM0: POP B ;;RECALL COUNT
POP H ;;RECALL BASE ADDRESS
MOV A,C ;;END OF LIST?
ORA A
RZ ;;RETURN IF SO
DCR C ;;DECREMENT COUNT
MOV E,M ;;NEXT ITEM (LOW)
INX H
MOV D,M ;;NEXT ITEM (HIGH)
INX H ;;READY FOR NEXT ROUND
PUSH H ;;SAVE PRINT ADDRESS
PUSH B ;;SAVE COUNT
XCHG ;;DATA READY
CALL @AD ;;PRINT ITEM VALUE
JMP @DM0 ;;FOR ANOTHER VALUE
;;
@DT: ;;DUMP TOP OF STACK ONLY
PRN <(TOP)=> ;;"(TOP)="
PUSH H
CALL @AD ;;VALUE OF HL
POP H ;;TOP RESTORED
RET
;;
PSUB:
;;
DMP MACRO ?V,?N
;; REDEFINE DUMP TO USE @DM UTILITY
LOCAL PMSG,MSG
;; SPECIAL CASE IF NULL PARAMETERS
IF NUL VNAME
;; DUMP THE TOP OF THE STACK ONLY
CALL @DT
EXITM
ENDIF
;; OTHERWISE DUMP VARIABLE NAME
JMP PMSG
MSG: DB CR,LF ;;CRLF
DB '&?V=$' ;;MESSAGE
PMSG: ADR ?V ;;HL=ADDRESS
ACTIVE SET 0 ;;CLEAR ACTIVE FLAG
LXI D,MSG ;;MESSAGE TO PRINT
IF NUL ?N ;;USE LENGTH 1
MVI C,1
ELSE
MVI C,?N
ENDIF
CALL @DM ;;TO PERFORM THE DUMP
ENDM ;;END OF REDEFINITION
DMP VNAME,N
ENDM
;
; *****************************************
; * END DUMP (ONLY) UTILITIES, *
; * BEGIN STACK MACHINE OPCODES *
; *****************************************
ACTIVE SET 0 ;ACTIVE REGISTER FLAG
;
SIZ MACRO SIZE
ORG TRAN ;;SET TO TRANSIENT AREA
;; CREATE A STACK WHEN "XIT" ENCOUNTERED
@STK SET SIZE ;;SAVE FOR DATA AREA
LXI SP,STACK
ENDM
;
SAVE MACRO
;; CHECK TO ENSURE "ENTER" PROPERLY SET UP
IF STACK ;;IS IT PRESENT?
ENDIF
SAVE MACRO ;;REDEFINE AFTER INITIAL REFERENCE
IF ACTIVE ;;ELEMENT IN HL
PUSH H ;;SAVE IT
ENDIF
ACTIVE SET 1 ;;SET ACTIVE
ENDM
SAVE
ENDM
;
REST MACRO
;; RESTORE THE TOP ELEMENT
IF NOT ACTIVE
POP H ;;RECALL TO HL
ENDIF
ACTIVE SET 1 ;;MARK AS ACTIVE
ENDM
;
CLEAR MACRO
;; CLEAR THE TOP ACTIVE ELEMENT
REST ;;ENSURE ACTIVE
ACTIVE SET 0 ;;CLEARED
ENDM
;
DCL MACRO VNAME,SIZE
;; LABEL THE DECLARATION
VNAME:
IF NUL SIZE
DS 2 ;;ONE WORD REQ'D
ELSE
DS SIZE*2 ;;DOUBLE WORDS
ENDM
;
LIT MACRO VAL
;; LOAD LITERAL VALUE TO TOP OF STACK
SAVE ;;SAVE IF ACTIVE
LXI H,VAL ;;LOAD LITERAL
?TR LIT
ENDM
;
ADR MACRO BASE,INX,CON
;; LOAD ADDRESS OF BASE, INDEXED BY INX,
;; WITH CONSTANT OFFSET GIVEN BY CON
SAVE ;;PUSH IF ACTIVE
IF NUL INX&CON
LXI H,BASE ;;ADDRESS OF BASE
EXITM ;;SIMPLE ADDRESS
ENDIF
;; MUST BE INX AND/OR CON
IF NUL INX
LXI H,CON*2 ;;CONSTANT
ELSE
LHLD INX ;;INDEX TO HL
DAD H ;;DOUBLE PRECISION INX
IF NOT NUL CON
LXI D,CON*2 ;;DOUBLE CONST
DAD D ;;ADDED TO INX
ENDIF ;;NOT NUL CON
ENDIF ;;NUL INX
LXI D,BASE ;;READY TO ADD
DAD D ;;BASE+INX*2+CON*2
ENDM
;
VAL MACRO B,I,C
;; GET VALUE OF B+I+C TO HL
;; CHECK SIMPLE CASE OF B ONLY
IF NUL I&C
SAVE ;;PUSH IF ACTIVE
LHLD B ;;LOAD DIRECTLY
ELSE
;; "ADR" PUSHES ACTIVE REGISTERS
ADR B,I,C ;;ADDRESS IN HL
MOV E,M ;;LOW ORDER BYTE
INX H
MOV D,M ;;HIGH ORDER BYTE
XCHG ;;BACK TO HL
ENDIF
?TR VAL ;;TRACE SET?
ENDM
;
STO MACRO B,I,C
;; STORE THE VALUE OF THE TOP OF STACK
;; LEAVING THE TOP ELEMENT ACTIVE
IF NUL I&C
REST ;;ACTIVATE STACK
SHLD B ;;STORED DIRECTLY TO B
ELSE
ADR B,I,C
POP D ;;VALUE IS IN DE
MOV M,E ;;LOW BYTE
INX H
MOV M,D ;;HIGH BYTE
ENDIF
CLEAR ;;MARK EMPTY
?TR STO ;;TRACE?
ENDM
;
SUM MACRO
REST ;;RESTORE IF SAVED
;; ADD THE TOP TWO STACK ELEMENTS
POP D ;;TOP-1 TO DE
DAD D ;;BACK TO HL
?TR SUM
ENDM
;
DIF MACRO
;; COMPUTE DIFFERENCE BETWEEN TOP ELEMENTS
REST ;;RESTORE IF SAVED
POP D ;;TOP-1 TO DE
MOV A,E ;;TOP-1 LOW BYTE TO A
SUB L ;;LOW ORDER DIFFERENCE
MOV L,A ;;BACK TO L
MOV A,D ;;TOP-1 HIGH BYTE
SBB H ;;HIGH ORDER DIFFERENCE
MOV H,A ;;BACK TO H
;; CARRY FLAG MAY BE SET UPON RETURN
?TR DIF
ENDM
;
LSR MACRO LEN
;; LOGICAL SHIFT RIGHT BY LEN
REST ;;ACTIVATE STACK
REPT LEN ;;GENERATE INLINE
XRA A ;;CLEAR CARRY
MOV A,H
RAR ;;ROTATE WITH HIGH 0
MOV H,A
MOV A,L
RAR
MOV L,A ;;BACK WITH HIGH BIT
ENDM
ENDM
;
GEQ MACRO LAB
;; JUMP TO LAB IF (TOP-1) IS GREATER OR
;; EQUAL TO (TOP) ELEMENT.
DIF ;;COMPUTE DIFFERENCE
CLEAR ;;CLEAR ACTIVE
?TR GEQ
JNC LAB ;;NO CARRY IF GREATER
ORA H ;;BOTH BYTES ZERO?
JZ LAB ;;ZERO IF EQUAL
;; DROP THROUGH IF NEITHER
ENDM
;
DUP MACRO
;; DUPLICATE THE TOP ELEMENT IN THE STACK
REST ;;ENSURE ACTIVE
PUSH H
?TR DUP
ENDM
;
BRN MACRO ADDR
;; BRANCH TO ADDRESS
JMP ADDR
ENDM
;
XIT MACRO
?TR XIT ;;TRACE ON?
JMP 0 ;;RESTART AT 0000
ORG DATA ;;START DATA AREA
DS @STK*2 ;;OBTAINED FROM "SIZ"
STACK: ENDM
;
; *****************************************
; * MEMORY MAPPED I/O SECTION *
; *****************************************
; INPUT VALUES WHICH ARE READ AS IF IN MEMORY
ADC0 EQU 1080H ;A-D CONVERTER 0
ADC1 EQU 1082H ;A-D CONVERTER 1
ADC2 EQU 1084H ;A-D CONVERTER 2
ADC3 EQU 1086H ;A-D CONVERTER 3
;
DAC0 EQU 1090H ;D-A CONVERTER 0
DAC1 EQU 1092H ;D-A CONVERTER 1
DAC2 EQU 1094H ;D-A CONVERTER 2
DAC3 EQU 1096H ;D-A CONVERTER 3
;
RWTRACE MACRO MSG,ADR
;; READ OR WRITE TRACE WITH MESSAGE
;; GIVEN BY "MSG" TO/FROM "ADR"
PRN <MSG AT ADR>
ENDM
;
RDM MACRO ?C
;; READ A-D CONVERTER NUMBER "?C"
SAVE ;;CLEAR THE STACK
IF DEBUGP ;;STOP EXECUTION IN DDT
RWTRACE <A-D INPUT >,% ADC&?C
UGEN ;;ENSURE @IN IS PRESENT
CALL @IN ;;VALUE TO HL
SHLD ADC&?C ;;SIMULATE MEMORY INPUT
ELSE
;; READ FROM MEMORY MAPPED INPUT ADDRESS
LHLD ADC&?C
ENDIF
?TR RDM ;;TRACING?
ENDM
;
WRM MACRO ?C
;; WRITE D-A CONVERTER NUMBER "?C"
REST ;;RESTORE STACK
IF DEBUGP ;;TRACE THE OUTPUT
RWTRACE <D-A OUTPUT>,% DAC&?C
UGEN ;;INCLUDE SUBROUTINES
CALL @AD ;;WRITE THE VALUE
ENDIF
SHLD DAC&?C
?TR WRM ;;TRACING OUTPUT?
CLEAR ;;REMOVE THE VALUE
ENDM
; *****************************************
; * END OF MACRO LIBRARY *
; *****************************************


View File

@@ -0,0 +1,242 @@
; NOTE:
; In order to execute this sample DUMP utility you
; must assemble EXTRN.ASM and then link DUMP and EXTRN to
; create the DUMP.PRL file. This is shown below:
;
; 0A>RMAC dump
; 0A>RMAC extrn
; 0A>LINK dump,extrn[op]
;
title 'File Dump Program'
cseg
; File dump program, reads an input file and
; prints in hex
;
; Copyright (C) 1975, 1976, 1977, 1978, 1979, 1980, 1981
; Digital Research
; Box 579, Pacific Grove
; California, 93950
;
; Externals
extrn bdos
extrn fcb
extrn buff
;
cons equ 1 ;read console
typef equ 2 ;type function
printf equ 9 ;buffer print entry
brkf equ 11 ;break key function
openf equ 15 ;file open
readf equ 20 ;read function
;
; non graphic characters
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
;
; 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
;fcbln equ fcb+33 ;fcb length
;
dump:
; set up stack
lxi h,0
dad sp
; entry stack pointer in hl from the ccp
shld oldsp
; set sp to local stack area (restored at finis)
lxi sp,stktop
; print sign on message
lxi d,signon
call prntmsg
; read and print successive buffers
call setup ;set up input file
cpi 255 ;255 if file not present
jnz openok ;skip if open is ok
;
; file not there, give error message and return
lxi d,opnmsg
call prntmsg
jmp finis ;to return
;
openok: ;open operation ok, set buffer index to end
mvi a,80h
sta ibp ;set buffer pointer to 80h
; hl contains next address to print
lxi h,0 ;start with 0000
;
gloop:
push h ;save line position
call gnb
pop h ;recall line position
jc finis ;carry set by gnb if end file
mov b,a
; print hex values
; check for line fold
mov a,l
ani 0fh ;check low 4 bits
jnz nonum
; print line number
call crlf
;
; check for break key
call break
; accum lsb = 1 if character ready
rrc ;into carry
jc purge ;don't print any more
;
mov a,h
call phex
mov a,l
call phex
nonum:
inx h ;to next line number
mvi a,' '
call pchar
mov a,b
call phex
jmp gloop
;
purge:
mvi c,cons
call bdos
finis:
; end of dump, return to ccp
; (note that a jmp to 0000h reboots)
call crlf
lhld oldsp
sphl
; stack pointer contains ccp's stack location
ret ;to the ccp
;
;
; subroutines
;
break: ;check break key (actually any key will do)
push h! push d! push b; environment saved
mvi c,brkf
call bdos
pop b! pop d! pop h; environment restored
ret
;
pchar: ;print a character
push h! push d! push b; saved
mvi c,typef
mov e,a
call bdos
pop b! pop d! pop h; restored
ret
;
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
;
phex: ;print hex char in reg a
push psw
rrc
rrc
rrc
rrc
call pnib ;print nibble
pop psw
call pnib
ret
;
prntmsg: ;print message
; d,e addresses message ending with "$"
mvi c,printf ;print buffer function
jmp bdos
; ret
;
;
gnb: ;get next byte
lda ibp
cpi 80h
jnz g0
; read another buffer
;
;
call diskr
ora a ;zero value if read ok
jz g0 ;for another byte
; end of data, return with carry set for eof
stc
ret
;
g0: ;read the byte at buff+reg a
mov e,a ;ls byte of buffer index
mvi d,0 ;double precision index to de
inr a ;index=index+1
sta ibp ;back to memory
; pointer is incremented
; save the current file address
lxi h,buff
dad d
; absolute character address is in hl
mov a,m
; byte is in the accumulator
ora a ;reset carry bit
ret
;
setup: ;set up file
; open the file for input
xra a ;zero to accum
sta fcb+32 ;clear current record
;
; open the file in R/O mode
lxi h,fcb+6
mov a,m
ori 80h
mov m,a ;set f6' on
lxi d,fcb
mvi c,openf
call bdos
; 255 in accum if open error
ret
;
diskr: ;read disk file record
push h! push d! push b
lxi d,fcb
mvi c,readf
call bdos
pop b! pop d! pop h
ret
;
; fixed message area
signon:
db 'MP/M II V2.0 File Dump'
db cr,lf,'$'
opnmsg:
db cr,lf,'No input file present on disk$'
; variable area
ibp: ds 2 ;input buffer pointer
oldsp: ds 2 ;entry sp value from ccp
;
; stack area
ds 64 ;reserve 32 level stack
stktop:
;
end dump


View File

@@ -0,0 +1,14 @@
title 'External Reference Module'
bdos equ 0005h
fcb equ 005ch
tfcb equ 006ch
buff equ 0080h
public bdos
public fcb
public tfcb
public buff
end


View File

@@ -0,0 +1,17 @@
; INTEL 8085 MACRO LIBRARY
;
; THE SIM (SET INTERRUPT MASK),
; AND RIM (READ INTERRUPT MASK)
; ARE DEFINED BY THE FOLLOWING MACROS:
;
SIM MACRO
;; SET INTERRUPT MASK FROM REG-A VALUE
DB 30H ;;OPCODE FOR SIM
ENDM
;
RIM MACRO
;; READ INTERRUPT MASK TO REG-A
DB 20H ;;OPCODE FOR RIM
ENDM
;


View File

@@ -0,0 +1,80 @@
; MACRO LIBRARY FOR BASIC INTERSECTION
;
; GLOBAL DEFINITIONS FOR DEBUG PROCESSING
TRUE EQU 0FFFFH ;VALUE OF TRUE
FALSE EQU NOT TRUE;VALUE OF FALSE
DEBUG SET FALSE ;INITIALLY FALSE
BDOS EQU 5 ;ENTRY TO CP/M BDOS
RCHAR EQU 1 ;READ CHARACTER FUNCTION
WBUFF EQU 9 ;WRITE BUFFER FUNCTION
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
; INPUT/OUTPUT PORTS FOR LIGHT AND CLOCK
LIGHT EQU 00H ;TRAFFIC LIGHT CONTROL
CLOCK EQU 03H ;24 HOUR CLOCK (0,1,...,23)
;
; BIT POSITIONS FOR TRAFFIC LIGHT CONTROL
NSBITS EQU 4 ;NORTH SOUUTH BITS
EWBITS EQU 0 ;EAST WEST BITS
;
; CONSTANT VALUES FOR THE LIGHT CONTROL
OFF EQU 0 ;TURN LIGHT OFF
RED EQU 1 ;VALUE FOR RED LIGHT
YELLOW EQU 2 ;VALUE FOR YELLOW LIGHT
GREEN EQU 3 ;GREEN LIGHT
;
SETLITE MACRO DIR,COLOR
;; SET LIGHT GIVEN BY "DIR" TO COLOR GIVEN BY "COLOR"
IF DEBUG ;;PRINT INFO AT CONSOLE
LOCAL SETMSG,PASTMSG
MVI C,WBUFF ;;WRITE BUFFER FUNCTION
LXI D,SETMSG
CALL BDOS ;;WRITE THE TRACE INFO
JMP PASTMSG
SETMSG: DB CR,LF
DB '&DIR CHANGING TO &COLOR$'
PASTMSG:
EXITM
ENDIF
MVI A,COLOR SHL DIR&BITS ;;READIED
OUT LIGHT ;;SENT IN PROPER BIT POSITION
ENDM
;
TIMER MACRO SECONDS
;; CONSTRUCT INLINE TIME-OUT LOOP
LOCAL T1,T2,T3 ;;LOOP ENTRIES
MVI D,4*SECONDS ;;BASIC LOOP CONTROL
T1: MVI B,250 ;;250MSEC *4 = 1 SEC
T2: MVI C,182 ;;182*5.5USEC = 1MSEC
T3: DCR C ;;1 CY = .5 USEC
JNZ T3 ;;+10 CY = 5.5 USEC
DCR B ;;COUNT 250,249...
JNZ T2 ;;LOOP ON B REGISTER
DCR D ;;BASIC LOOP CONTROL
JNZ T1 ;;LOOP ON D REGISTER
;; ARRIVE HERE WITH APPROXIMATELY "SECONDS"
;; TIMEOUT, CONTINUE PROCESSING.
ENDM
;
CLOCK? MACRO LOW,HIGH,IFTRUE
;; CHECK FOR REAL-TIME CLOCK GREATER THAN OR
;; EQUAL TO "LOW." AND LESS THAN "HIGH."
;; CONTINUE AT "IFTRUE" WHEN BETWEEN THESE
;; TIMES.
LOCAL IFFALSE ;;ALTERNATE TO TRUE CASE
IN CLOCK ;;READ REAL-TIME CLOCK
IF NOT NUL HIGH ;;CHECK HIGH CLOCK
CPI HIGH ;;EQUAL OR GREATER?
JNC IFFALSE ;;SKIP TO END IF SO
ENDIF
CPI LOW ;;LESS THAN LOW VALUE?
JNC IFTRUE ;;SKIP TO LABEL IF NOT
IFFALSE:
ENDM
;
RETRY MACRO GOLABEL
;; CONTINUE EXECUTION AT "GOLABEL"
JMP GOLABEL
ENDM


View File

@@ -0,0 +1,417 @@
; MP/M 2.0 Loader BIOS
; (modified CP/M 2.2 BIOS)
; MDS I/O drivers for CP/M 2.2
; (single drive, single density)
; -or-
; (single drive, double density)
; Version 2.0 -- Sept 81
vers equ 20 ;version 2.0
; Copyright (C) 1980, 1981
; Digital Research
; Box 579, Pacific Grove
; California, 93950
false equ 0
true equ not false
asm equ true
mac equ not asm
sgl equ true
dbl equ not sgl
if mac
maclib diskdef
numdsks equ 1 ;number of drives available
endif
ram$top equ 1d00h ; top address+1
bios equ ram$top-0600h ; basic input/output system
bdos equ bios-0e00h ; base of the bdos
org bios
buff equ 0080h ;default buffer address
retry equ 10 ;max retries on disk i/o before error
; jump vector for indiviual routines
jmp boot
wboote: jmp wboot
jmp const
jmp conin
jmp conout
jmp list
jmp punch
jmp reader
jmp home
jmp seldsk
jmp settrk
jmp setsec
jmp setdma
jmp read
jmp write
jmp list$st ; list status poll
jmp sect$tran ; sector translation
; we also assume the MDS system has four disk drives
numdisks equ 1 ;number of drives available
revrt equ 0fdh ;interrupt revert port
intc equ 0fch ;interrupt mask port
icon equ 0f3h ;interrupt control port
inte equ 0111$1110b ;enable rst 0(warm boot), rst 7 (monitor)
; MDS monitor equates
rmon80 equ 0ff0fh ;restart mon80 (boot error)
; disk ports and commands
base equ 78h ;base of disk command io ports
dstat equ base ;disk status (input)
rtype equ base+1 ;result type (input)
rbyte equ base+3 ;result byte (input)
ilow equ base+1 ;iopb low address (output)
ihigh equ base+2 ;iopb high address (output)
readf equ 4h ;read function
writf equ 6h ;write function
recal equ 3h ;recalibrate drive
iordy equ 4h ;i/o finished mask
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
boot:
wboot:
gocpm:
ret
crtin: ; crt: input
in 0f7h ! ani 2 ! jz crtin
in 0f6h ! ani 7fh
ret
crtout: ; crt: output
in 0f7h ! ani 1 ! jz crtout
mov a,c ! out 0f6h
ret
crtst: ; crt: status
in 0f7h ! ani 2 ! rz
ori 0ffh
ret
ttyin: ; tty: input
in 0f5h ! ani 2 ! jz ttyin
in 0f4h ! ani 7fh
ret
ttyout: ; tty: output
in 0f5h ! ani 1 ! jz ttyout
mov a,c ! out 0f4h
ret
;ttyst:
; in 0f5h ! ani 2 ! rz
; ori -1
; ret
lptout: ; lpt: output
in 0fbh ! ani 1 ! jz lptout
mov a,c ! cma ! out 0fah
ret
lpt$st:
in 0fbh ! ani 1 ! rz
ori 0ffh
ret
conin equ crtin
const equ crtst
conout equ crtout
reader equ ttyin
punch equ ttyout
list equ lptout
listst equ lptst
seldsk: ;select disk given by register c
lxi h, 0 ! mov a,c ! cpi num$disks ! rnc ; first, insure good select
ani 2 ! sta dbank ; then save it
lxi h,sel$table ! mvi b,0 ! dad b ! mov a,m ! sta iof
mov h,b ! mov l,c
dad h ! dad h ! dad h ! dad h ; times 16
lxi d,dpbase ! dad d
ret
home: ;move to home position
; treat as track 00 seek
mvi c,0
;
settrk: ;set track address given by c
lxi h,iot
mov m,c
ret
;
setsec: ;set sector number given by c
mov a,c ;sector number to accum
sta ios ;store sector number to iopb
ret
;
setdma: ;set dma address given by regs b,c
mov l,c
mov h,b
shld iod
ret
sect$tran: ; translate the sector # in <c> if needed
mov h,b ! mov l,c ! inx h ; in case of no translation
mov a, d ! ora e ! rz
xchg ! dad b ; point to physical sector
mov l,m ! mvi h,0
ret
read: ;read next disk record (assuming disk/trk/sec/dma set)
mvi c,readf ;set to read function
jmp setfunc
;
write: ;disk write function
mvi c,writf
;
setfunc:
; set function for next i/o (command in reg-c)
lxi h,iof ;io function address
mov a,m ;get it to accumulator for masking
ani 1111$1000b ;remove previous command
ora c ;set to new command
mov m,a ;replaced in iopb
; single density drive 1 requires bit 5 on in sector #
; mask the bit from the current i/o function
ani 0010$0000b ;mask the disk select bit
lxi h,ios ;address the sector select byte
ora m ;select proper disk bank
mov m,a ;set disk select bit on/off
;
waitio:
mvi c,retry ;max retries before perm error
rewait:
; start the i/o function and wait for completion
call intype ;in rtype
call inbyte ;clears the controller
lda dbank ;set bank flags
ora a ;zero if drive 0,1 and nz if 2,3
mvi a,iopb and 0ffh ;low address for iopb
mvi b,iopb shr 8 ;high address for iopb
jnz iodr1 ;drive bank 1?
out ilow ;low address to controller
mov a,b
out ihigh ;high address
jmp wait0 ;to wait for complete
iodr1: ;drive bank 1
out ilow+10h ;88 for drive bank 10
mov a,b
out ihigh+10h
wait0: call instat ;wait for completion
ani iordy ;ready?
jz wait0
; check io completion ok
call intype ;must be io complete (00) unlinked
; 00 unlinked i/o complete, 01 linked i/o complete (not used)
; 10 disk status changed 11 (not used)
cpi 10b ;ready status change?
jz wready
; must be 00 in the accumulator
ora a
jnz werror ;some other condition, retry
; check i/o error bits
call inbyte
ral
jc wready ;unit not ready
rar
ani 11111110b ;any other errors? (deleted data ok)
jnz werror
; read or write is ok, accumulator contains zero
ret
wready: ;not ready, treat as error for now
call inbyte ;clear result byte
jmp trycount
werror: ;return hardware malfunction (crc, track, seek, etc.)
; the MDS controller has returned a bit in each position
; of the accumulator, corresponding to the conditions:
; 0 - deleted data (accepted as ok above)
; 1 - crc error
; 2 - seek error
; 3 - address error (hardware malfunction)
; 4 - data over/under flow (hardware malfunction)
; 5 - write protect (treated as not ready)
; 6 - write error (hardware malfunction)
; 7 - not ready
; (accumulator bits are numbered 7 6 5 4 3 2 1 0)
trycount:
; register c contains retry count, decrement 'til zero
dcr c
jnz rewait ;for another try
; cannot recover from error
mvi a,1 ;error code
ret
; intype, inbyte, instat read drive bank 00 or 10
intype: lda dbank
ora a
jnz intyp1 ;skip to bank 10
in rtype
ret
intyp1: in rtype+10h ;78 for 0,1 88 for 2,3
ret
inbyte: lda dbank
ora a
jnz inbyt1
in rbyte
ret
inbyt1: in rbyte+10h
ret
instat: lda dbank
ora a
jnz insta1
in dstat
ret
insta1: in dstat+10h
ret
; utility subroutines
prmsg: ;print message at h,l to 0
mov a,m ! ora a ! rz
push h ! mov c,a ! call conout ! pop h
inx h ! jmp prmsg
; data areas (must be in ram)
dbank: db 0 ;disk bank 00 if drive 0,1
; 10 if drive 2,3
iopb: ;io parameter block
db 80h ;normal i/o operation
iof: db readf ;io function, initial read
ion: db 1 ;number of sectors to read
iot: db 2 ;track number
ios: db 1 ;sector number
iod: dw buff ;io address
;
;
sel$table:
if sgl
db 00h, 30h, 00h, 30h ; drive select bits
endif
if dbl
db 00h, 10h, 00h, 30h ; drive select bits
endif
if mac and sgl
disks numdisks ; generate drive tables
diskdef 0,1,26,6,1024,243,64,64,2
endef
endif
if mac and dbl
disks numdisks ; generate drive tables
diskdef 0,1,52,,2048,243,128,128,2,0
endef
endif
if asm
dpbase equ $ ;base of disk param blks
dpe0: dw xlt0,0000h ;translate table
dw 0000h,0000h ;scratch area
dw dirbuf,dpb0 ;dir buff, parm block
dw csv0,alv0 ;check, alloc vectors
dpb0 equ $ ;disk param block
endif
if asm and sgl
dw 26 ;sec per track
db 3 ;block shift
db 7 ;block mask
db 0 ;extnt mask
dw 242 ;disk size-1
dw 63 ;directory max
db 192 ;alloc0
db 0 ;alloc1
dw 16 ;check size
dw 2 ;offset
xlt0 equ $ ;translate table
db 1
db 7
db 13
db 19
db 25
db 5
db 11
db 17
db 23
db 3
db 9
db 15
db 21
db 2
db 8
db 14
db 20
db 26
db 6
db 12
db 18
db 24
db 4
db 10
db 16
db 22
endif
if asm and dbl
xlt0 equ 0
endif
if asm
begdat equ $
dirbuf: ds 128 ;directory access buffer
alv0: ds 31
csv0: ds 16
endif
if asm and dbl
ds 16
endif
if asm
enddat equ $
datsiz equ $-begdat
endif
end


View File

@@ -0,0 +1,77 @@
; MACRO LIBRARY FOR 8-BIT COMPARISON OPERATION
;
TEST? MACRO X,Y
;; UTILTITY MACRO TO GENERATE CONDITION CODES
IF NOT NUL X ;;THEN LOAD X
LDA X ;;X ASSUMED TO BE IN MEMORY
ENDIF
IRPC ?Y,Y ;;Y MAY BE CONSTANT OPERAND
TDIG? SET '&?Y'-'0' ;;FIRST CHAR DIGIT?
EXITM ;;STOP IRPC AFTER FIRST CHAR
ENDM
IF TDIG? <= 9 ;;Y NUMERIC?
SUI Y ;;YES, SO SUB IMMEDIATE
ELSE
LXI H,Y ;;Y NOT NUMERIC
SUB M ;;SO SUB FROM MEMORY
ENDM
;
LSS MACRO X,Y,TL,FL
;; X LSS THAN Y TEST,
;; IF TL IS PRESENT, ASSUME TRUE TEST
;; IF TL IS ABSENT, THEN INVERT TEST
IF NUL TL
GEQ X,Y,FL
ELSE
TEST? X,Y ;;SET CONDITION CODES
JC TL
ENDM
;
LEQ MACRO X,Y,TL,FL
;; X LESS THAN OR EQUAL TO Y TEST
IF NUL TL
GEQ X,Y,FL
ELSE
LSS X,Y,TL
JZ TL
ENDM
;
EQL MACRO X,Y,TL,FL
;; X EQUAL TO Y TEST
IF NUL TL
NEQ X,Y,FL
ELSE
TEST? X,Y
JZ TL
ENDM
;
NEQ MACRO X,Y,TL,FL
;; X NOT EQUAL TO Y TEST
IF NUL TL
EQL X,Y,FL
ELSE
TEST? X,Y
JNZ TL
ENDM
;
GEQ MACRO X,Y,TL,FL
;; X GREATER THAN OR EQUAL TO Y TEST
IF NUL TL
LSS X,Y,FL
ELSE
TEST? X,Y
JNC TL
ENDM
;
GTR MACRO X,Y,TL,FL
;; X GREATER THAN Y TEST
IF NUL TL
LEQ X,Y,FL
ELSE
LOCAL GFL ;;FALSE LABEL
TEST? X,Y
JC GFL
DCR A
JNC TL
GFL: ENDM


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
; MACRO LIBRARY FOR "SELECT" CONSTRUCT
;
; LABEL GENERATORS
GENSLXI MACRO NUM
;; LOAD HL WITH ADDRESS OF CASE LIST
LXI H,SELV&NUM
ENDM
;
GENCASE MACRO NUM,ELT
;; GENERATE JMP TO END OF CASES
IF ELT GT 0
JMP ENDS&NUM ;;PAST ADDR LIST
ENDIF
;; GENERATE LABEL FOR THIS CASE
CASE&NUM&@&ELT:
ENDM
;
GENELT MACRO NUM,ELT
;; GENERATE ONE ELEMENT OF CASE LIST
DW CASE&NUM&@&ELT
ENDM
;
GENSLAB MACRO NUM,ELTS
;; GENERATE CASE LIST
SELV&NUM:
ECNT SET 0 ;;COUNT ELEMENTS
REPT ELTS ;;GENERATE DW'S
GENELT NUM,%ECNT
ECNT SET ECNT+1
ENDM ;;END OF DW'S
;; GENERATE END OF CASE LIST LABEL
ENDS&NUM:
ENDM
;
SELNEXT MACRO
;; GENERATE THE NEXT CASE
GENCASE %CCNT,%ECNT
;; INCREMENT THE CASE ELEMENT COUNT
ECNT SET ECNT+1
ENDM
;
SELECT MACRO VAR
;; GENERATE CASE SELECTION CODE
CCNT SET 0 ;;COUNT "SELECTS"
SELECT MACRO V ;;REDEFINITION OF SELECT
;; SELECT ON V OR ACCUMULATOR CONTENTS
IF NOT NUL V
LDA V ;;LOAD SELECT VARIABLE
ENDIF
GENSLXI %CCNT ;;GENERATE THE LXI H,SELV#
MOV E,A ;;CREATE DOUBLE PRECISION
MVI D,0 ;;V IN D,E PAIR
DAD D ;;SINGLE PREC INDEX
DAD D ;;DOUBLE PREC INDEX
MOV E,M ;;LOW ORDER BRANCH ADDR
INX H ;;TO HIGH ORDER BYTE
MOV D,M ;;HIGH ORDER BRANCH INDEX
XCHG ;;READY BRANCH ADDRESS IN HL
PCHL ;;GONE TO THE PROPER CASE
ECNT SET 0 ;;ELEMENT COUNTER RESET
SELNEXT ;;SELECT CASE 0
ENDM
;; INVOKE REDEFINED SELECT THE FIRST TIME
SELECT VAR
ENDM
;
ENDSEL MACRO
;; END OF SELECT, GENERATE CASE LIST
GENCASE %CCNT,%ECNT ;;LAST CASE
GENSLAB %CCNT,%ECNT ;;CASE LIST
;; INCREMENT "SELECT" COUNT
CCNT SET CCNT+1
ENDM


View File

@@ -0,0 +1,439 @@
; SEQUENTIAL FILE I/O LIBRARY
;
FILERR SET 0000H ;REBOOT AFTER ERROR
@BDOS EQU 0005H ;BDOS ENTRY POINT
@TFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK
@TBUF EQU 0080H ;DEFAULT BUFFER ADDRESS
;
; BDOS FUNCTIONS
@MSG EQU 9 ;SEND MESSAGE
@OPN EQU 15 ;FILE OPEN
@CLS EQU 16 ;FILE CLOSE
@DIR EQU 17 ;DIRECTORY SEARCH
@DEL EQU 19 ;FILE DELETE
@FRD EQU 20 ;FILE READ OPERATION
@FWR EQU 21 ;FILE WRITE OPERATION
@MAK EQU 22 ;FILE MAKE
@REN EQU 23 ;FILE RENAME
@DMA EQU 26 ;SET DMA ADDRESS
;
@SECT EQU 128 ;SECTOR SIZE
EOF EQU 1AH ;END OF FILE
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
TAB EQU 09H ;HORIZONTAL TAB
;
@KEY EQU 1 ;KEYBOARD
@CON EQU 2 ;CONSOLE DISPLAY
@RDR EQU 3 ;READER
@PUN EQU 4 ;PUNCH
@LST EQU 5 ;LIST DEVICE
;
; KEYWORDS FOR "FILE" MACRO
INFILE EQU 1 ;INPUT FILE
OUTFILE EQU 2 ;OUTPUTFILE
SETFILE EQU 3 ;SETUP NAME ONLY
;
; THE FOLLOWING MACROS DEFINE SIMPLE SEQUENTIAL
; FILE OPERATIONS:
;
FILLNAM MACRO FC,C
;; FILL THE FILE NAME/TYPE GIVEN BY FC FOR C CHARACTERS
@CNT SET C ;;MAX LENGTH
IRPC ?FC,FC ;;FILL EACH CHARACTER
;; MAY BE END OF COUNT OR NUL NAME
IF @CNT=0 OR NUL ?FC
EXITM
ENDIF
DB '&?FC' ;;FILL ONE MORE
@CNT SET @CNT-1 ;;DECREMENT MAX LENGTH
ENDM ;;OF IRPC ?FC
;;
;; PAD REMAINDER
REPT @CNT ;;@CNT IS REMAINDER
DB ' ' ;;PAD ONE MORE BLANK
ENDM ;;OF REPT
ENDM
;
FILLDEF MACRO FCB,?FL,?LN
;; FILL THE FILE NAME FROM THE DEFAULT FCB
;; FOR LENGTH ?LN (9 OR 12)
LOCAL PSUB
JMP PSUB ;;JUMP PAST THE SUBROUTINE
@DEF: ;;THIS SUBROUTINE FILLS FROM THE TFCB (+16)
MOV A,M ;;GET NEXT CHARACTER TO A
STAX D ;;STORE TO FCB AREA
INX H
INX D
DCR C ;;COUNT LENGTH DOWN TO 0
JNZ @DEF
RET
;; END OF FILL SUBROUTINE
PSUB:
FILLDEF MACRO ?FCB,?F,?L
LXI H,@TFCB+?F ;;EITHER @TFCB OR @TFCB+16
LXI D,?FCB
MVI C,?L ;;LENGTH = 9,12
CALL @DEF
ENDM
FILLDEF FCB,?FL,?LN
ENDM
;
FILLNXT MACRO
;; INITIALIZE BUFFER AND DEVICE NUMBERS
@NXTB SET 0 ;;NEXT BUFFER LOCATION
@NXTD SET @LST+1 ;;NEXT DEVICE NUMBER
FILLNXT MACRO
ENDM
ENDM
;
FILLFCB MACRO FID,DN,FN,FT,BS,BA
;; FILL THE FILE CONTROL BLOCK WITH DISK NAME
;; FID IS AN INTERNAL NAME FOR THE FILE,
;; DN IS THE DRIVE NAME (A,B..), OR BLANK
;; FN IS THE FILE NAME, OR BLANK
;; FT IS THE FILE TYPE
;; BS IS THE BUFFER SIZE
;; BA IS THE BUFFER ADDRESS
LOCAL PFCB
;;
;; SET UP THE FILE CONTROL BLOCK FOR THE FILE
;; LOOK FOR FILE NAME = 1 OR 2
@C SET 1 ;;ASSUME TRUE TO BEGIN WITH
IRPC ?C,FN ;;LOOK THROUGH CHARACTERS OF NAME
IF NOT ('&?C' = '1' OR '&?C' = '2')
@C SET 0 ;;CLEAR IF NOT 1 OR 2
ENDM
;; @C IS TRUE IF FN = 1 OR 2 AT THIS POINT
IF @C ;;THEN FN = 1 OR 2
;; FILL FROM DEFAULT AREA
IF NUL FT ;;TYPE SPECIFIED?
@C SET 12 ;;BOTH NAME AND TYPE
ELSE
@C SET 9 ;;NAME ONLY
ENDIF
FILLDEF FCB&FID,(FN-1)*16,@C ;;TO SELECT THE FCB
JMP PFCB ;;PAST FCB DEFINITION
DS @C ;;SPACE FOR DRIVE/FILENAME/TYPE
FILLNAM FT,12-@C ;;SERIES OF DB'S
ELSE
JMP PFCB ;;PAST INITIALIZED FCB
IF NUL DN
DB 0 ;;USE DEFAULT DRIVE IF NAME IS ZERO
ELSE
DB '&DN'-'A'+1 ;;USE SPECIFIED DRIVE
ENDIF
FILLNAM FN,8 ;;FILL FILE NAME
;; NOW GENERATE THE FILE TYPE WITH PADDED BLANKS
FILLNAM FT,3 ;;AND THREE CHARACTER TYPE
ENDIF
FCB&FID EQU $-12 ;;BEGINNING OF THE FCB
DB 0 ;;EXTENT FIELD 00 FOR SETFILE
;; NOW DEFINE THE 3 BYTE FIELD, AND DISK MAP
DS 20 ;;X,X,RC,DM0...DM15,CR FIELDS
;;
IF FID&TYP<=2 ;;IN/OUTFILE
;; GENERATE CONSTANTS FOR INFILE/OUTFILE
FILLNXT ;;@NXTB=0 ON FIRST CALL
IF BS+0<@SECT
;; BS NOT SUPPLIED, OR TOO SMALL
@BS SET @SECT ;;DEFAULT TO ONE SECTOR
ELSE
;; COMPUTE EVEN BUFFER ADDRESS
@BS SET (BS/@SECT)*@SECT
ENDIF
;;
;; NOW DEFINE BUFFER BASE ADDRESS
IF NUL BA
;; USE NEXT ADDRESS AFTER @NXTB
FID&BUF SET BUFFERS+@NXTB
;; COUNT PAST THIS BUFFER
@NXTB SET @NXTB+@BS
ELSE
FID&BUF SET BA
ENDIF
;; FID&BUF IS BUFFER ADDRESS
FID&ADR:
DW FID&BUF
;;
FID&SIZ EQU @BS ;;LITERAL SIZE
FID&LEN:
DW @BS ;;BUFFER SIZE
FID&PTR:
DS 2 ;;SET IN INFILE/OUTFILE
;; SET DEVICE NUMBER
@&FID SET @NXTD ;;NEXT DEVICE
@NXTD SET @NXTD+1
ENDIF ;;OF FID&TYP<=2 TEST
PFCB: ENDM
;
FILE MACRO MD,FID,DN,FN,FT,BS,BA
;; CREATE FILE USING MODE MD:
;; INFILE = 1 INPUT FILE
;; OUTFILE = 2 OUTPUT FILE
;; SETFILE = 3 SETUP FCB
;; (SEE FILLFCB FOR REMAINING PARAMETERS)
LOCAL PSUB,MSG,PMSG
LOCAL PND,EOD,EOB,PNC
;; CONSTRUCT THE FILE CONTROL BLOCK
;;
FID&TYP EQU MD ;;SET MODE FOR LATER REF'S
FILLFCB FID,DN,FN,FT,BS,BA
IF MD=3 ;;SETUP FCB ONLY, SO EXIT
EXITM
ENDIF
;; FILE CONTROL BLOCK AND RELATED PARAMETERS
;; ARE CREATED INLINE, NOW CREATE IO FUNCTION
JMP PSUB ;;PAST INLINE SUBROUTINE
IF MD=1 ;;INPUT FILE
GET&FID:
ELSE
PUT&FID:
PUSH PSW ;;SAVE OUTPUT CHARACTER
ENDIF
LHLD FID&LEN ;;LOAD CURRENT BUFFER LENGTH
XCHG ;;DE IS LENGTH
LHLD FID&PTR ;;LOAD NEXT TO GET/PUT TO HL
MOV A,L ;;COMPUTE CUR-LEN
SUB E
MOV A,H
SBB D ;;CARRY IF NEXT<LENGTH
JC PNC ;;CARRY IF LEN GTR CURRENT
;; END OF BUFFER, FILL/EMPTY BUFFERS
LXI H,0
SHLD FID&PTR ;;CLEAR NEXT TO GET/PUT
PND:
;; PROCESS NEXT DISK SECTOR:
XCHG ;;FID&PTR TO DE
LHLD FID&LEN ;;DO NOT EXCEED LENGTH
;; DE IS NEXT TO FILL/EMPTY, HL IS MAX LEN
MOV A,E ;;COMPUTE NEXT-LEN
SUB L ;;TO GET CARRY IF MORE
MOV A,D
SBB H ;;TO FILL
JNC EOB
;; CARRY GEN'ED, HENCE MORE TO FILL/EMPTY
LHLD FID&ADR ;;BASE OF BUFFERS
DAD D ;;HL IS NEXT BUFFER ADDR
XCHG
MVI C,@DMA ;;SET DMA ADDRESS
CALL @BDOS ;;DMA ADDRESS IS SET
LXI D,FCB&FID ;;FCB ADDRESS TO DE
IF MD=1 ;;READ BUFFER FUNCTION
MVI C,@FRD ;;FILE READ FUNCTION
ELSE
MVI C,@FWR ;;FILE WRITE FUNCTION
ENDIF
CALL @BDOS ;;RD/WR TO/FROM DMA ADDRESS
ORA A ;;CHECK RETURN CODE
JNZ EOD ;;END OF FILE/DISK?
;; NOT END OF FILE/DISK, INCREMENT LENGTH
LXI D,@SECT ;;SECTOR SIZE
LHLD FID&PTR ;;NEXT TO FILL
DAD D
SHLD FID&PTR ;;BACK TO MEMORY
JMP PND ;;PROCESS ANOTHER SECTOR
;;
EOD:
;; END OF FILE/DISK ENCOUNTERED
IF MD=1 ;;INPUT FILE
LHLD FID&PTR ;;LENGTH OF BUFFER
SHLD FID&LEN ;;RESET LENGTH
ELSE
;; FATAL ERROR, END OF DISK
LOCAL EMSG
MVI C,@MSG ;;WRITE THE ERROR
LXI D,EMSG
CALL @BDOS ;;ERROR TO CONSOLE
POP PSW ;;REMOVE STACKED CHARACTER
JMP FILERR ;;USUALLY REBOOTS
EMSG: DB CR,LF
DB 'DISK FULL: &FID'
DB '$'
ENDIF
;;
EOB:
;; END OF BUFFER, RESET DMA AND POINTER
LXI D,@TBUF
MVI C,@DMA
CALL @BDOS
LXI H,0
SHLD FID&PTR ;;NEXT TO GET
;;
PNC:
;; PROCESS THE NEXT CHARACTER
XCHG ;;INDEX TO GET/PUT IN DE
LHLD FID&ADR ;;BASE OF BUFFER
DAD D ;;ADDRESS OF CHAR IN HL
XCHG ;;ADDRESS OF CHAR IN DE
IF MD=1 ;;INPUT PROCESSING DIFFERS
LHLD FID&LEN ;;FOR EOF CHECK
MOV A,L ;;0000?
ORA H
MVI A,EOF ;;END OF FILE?
RZ ;;ZERO FLAG IF SO
LDAX D ;;NEXT CHAR IN ACCUM
ELSE
;; STORE NEXT CHARACTER FROM ACCUMULATOR
POP PSW ;;RECALL SAVED CHAR
STAX D ;;CHARACTER IN BUFFER
ENDIF
LHLD FID&PTR ;;INDEX TO GET/PUT
INX H
SHLD FID&PTR ;;POINTER UPDATED
;; RETURN WITH NON ZERO FLAG IF GET
RET
;;
PSUB: ;;PAST INLINE SUBROUTINE
XRA A ;;ZERO TO ACC
STA FCB&FID+12 ;;CLEAR EXTENT
STA FCB&FID+32 ;;CLEAR CUR REC
LXI H,FID&SIZ ;;BUFFER SIZE
SHLD FID&LEN ;;SET BUFF LEN
IF MD=1 ;;INPUT FILE
SHLD FID&PTR ;;CAUSE IMMEDIATE READ
MVI C,@OPN ;;OPEN FILE FUNCTION
ELSE ;;OUTPUT FILE
LXI H,0 ;;SET NEXT TO FILL
SHLD FID&PTR ;;POINTER INITIALIZED
MVI C,@DEL
LXI D,FCB&FID ;;DELETE FILE
CALL @BDOS ;;TO CLEAR EXISTING FILE
MVI C,@MAK ;;CREATE A NEW FILE
ENDIF
;; NOW OPEN (IF INPUT), OR MAKE (IF OUTPUT)
LXI D,FCB&FID
CALL @BDOS ;;OPEN/MAKE OK?
INR A ;;255 BECOMES 00
JNZ PMSG
MVI C,@MSG ;;PRINT MESSAGE FUNCTION
LXI D,MSG ;;ERROR MESSAGE
CALL @BDOS ;;PRINTED AT CONSOLE
JMP FILERR ;;TO RESTART
MSG: DB CR,LF
IF MD=1 ;;INPUT MESSAGE
DB 'NO &FID FILE'
ELSE
DB 'NO DIR SPACE: &FID'
ENDIF
DB '$'
PMSG:
ENDM
;
PUT MACRO DEV
;; WRITE CHARACTER FROM ACCUM TO DEVICE
IF @&DEV <= @LST
;; SIMPLE OUTPUT
PUSH PSW ;;SAVE CHARACTER
MVI C,@&DEV ;;WRITE CHAR FUNCTION
MOV E,A ;;READY FOR OUTPUT
CALL @BDOS ;;WRITE CHARACTER
POP PSW ;;RESTORE FOR TESTING
ELSE
CALL PUT&DEV
ENDM
;
FINIS MACRO FID
;; CLOSE THE FILE(S) GIVEN BY FID
IRP ?F,<FID>
;; SKIP ALL BUT OUTPUT FILES
IF ?F&TYP=2
LOCAL EOB?,PEOF,MSG,PMSG
;; WRITE ALL PARTIALLY FILLED BUFFERS
EOB?: ;;ARE WE AT THE END OF A BUFFER?
LHLD ?F&PTR ;;NEXT TO FILL
MOV A,L ;;ON BUFFER BOUNDARY?
ANI (@SECT-1) AND 0FFH
JNZ PEOF ;;PUT EOF IF NOT 00
IF @SECT>255
;; CHECK HIGH ORDER BYTE ALSO
MOV A,H
ANI (@SECT-1) SHR 8
JNZ PEOF ;;PUT EOF IF NOT 00
ENDIF
;; ARRIVE HERE IF END OF BUFFER, SET LENGTH
;; AND WRITE ONE MORE BYTE TO CLEAR BUFFS
SHLD ?F&LEN ;;SET TO SHORTER LENGTH
PEOF: MVI A,EOF ;;WRITE ANOTHER EOF
PUSH PSW ;;SAVE ZERO FLAG
CALL PUT&?F
POP PSW ;;RECALL ZERO FLAG
JNZ EOB? ;;NON ZERO IF MORE
;; BUFFERS HAVE BEEN WRITTEN, CLOSE FILE
MVI C,@CLS
LXI D,FCB&?F ;;READY FOR CALL
CALL @BDOS
INR A ;;255 IF ERR BECOMES 00
JNZ PMSG
;; FILE CANNOT BE CLOSED
MVI C,@MSG
LXI D,MSG
CALL @BDOS
JMP PMSG ;;ERROR MESSAGE PRINTED
MSG: DB CR,LF
DB 'CANNOT CLOSE &?F'
DB '$'
PMSG:
ENDIF
ENDM ;;OF THE IRP
ENDM
;
ERASE MACRO FID
;; DELETE THE FILE(S) GIVEN BY FID
IRP ?F,<FID>
MVI C,@DEL
LXI D,FCB&?F
CALL @BDOS
ENDM ;;OF THE IRP
ENDM
;
DIRECT MACRO FID
;; PERFORM DIRECTORY SEARCH FOR FILE
;; SETS ZERO FLAG IF NOT PRESENT
LXI D,FCB&FID
MVI C,@DIR
CALL @BDOS
INR A ;00 IF NOT PRESENT
ENDM
;
RENAME MACRO NEW,OLD
;; RENAME FILE GIVEN BY "OLD" TO "NEW"
LOCAL PSUB,REN0
;; INCLUDE THE RENAME SUBROUTINE ONCE
JMP PSUB
@RENS: ;;RENAME SUBROUTINE, HL IS ADDRESS OF
;;OLD FCB, DE IS ADDRESS OF NEW FCB
PUSH H ;;SAVE FOR RENAME
LXI B,16 ;;B=00,C=16
DAD B ;;HL = OLD FCB+16
REN0: LDAX D ;;NEW FCB NAME
MOV M,A ;;TO OLD FCB+16
INX D ;;NEXT NEW CHAR
INX H ;;NEXT FCB CHAR
DCR C ;;COUNT DOWN FROM 16
JNZ REN0
;; OLD NAME IN FIRST HALF, NEW IN SECOND HALF
POP D ;;RECALL BASE OF OLD NAME
MVI C,@REN ;;RENAME FUNCTION
CALL @BDOS
RET ;;RENAME COMPLETE
PSUB:
RENAME MACRO N,O ;;REDEFINE RENAME
LXI H,FCB&O ;;OLD FCB ADDRESS
LXI D,FCB&N ;;NEW FCB ADDRESS
CALL @RENS ;;RENAME SUBROUTINE
ENDM
RENAME NEW,OLD
ENDM
;
GET MACRO DEV
;; READ CHARACTER FROM DEVICE
IF @&DEV <= @LST
;; SIMPLE INPUT
MVI C,@&DEV
CALL @BDOS
ELSE
CALL GET&DEV
ENDM
;


View File

@@ -0,0 +1,26 @@
; MACRO LIBRARY FOR SIMPLE I/O
BDOS EQU 0005H ;BDOS ENTRY
CONIN EQU 1 ;CONSOLE INPUT FUNCTION
MSGOUT EQU 9 ;PRINT MESSAGE TIL $
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
READ MACRO VAR
;; READ A SINGLE CHARACTER INTO VAR
MVI C,CONIN ;CONSOLE INPUT FUNCTION
CALL BDOS ;CHARACTER IS IN A
STA VAR
ENDM
;
WRITE MACRO MSG
;; WRITE MESSAGE TO CONSOLE
LOCAL MSGL,PMSG
JMP PMSG
MSGL: DB CR,LF ;;LEADING CRLF
DB '&MSG' ;;INLINE MESSAGE
DB '$' ;;MESSAGE TERMINATOR
PMSG: MVI C,MSGOUT ;;PRINT MESSAGE TIL $
LXI D,MSGL
CALL BDOS
ENDM


View File

@@ -0,0 +1,56 @@
SIZ MACRO SIZE
;; SET "ORG" AND CREATE STACK
LOCAL STACK ;;LABEL ON THE STACK
ORG 100H ;;AT BASE OF TPA
LXI SP,STACK
JMP STACK ;;PAST STACK
DS SIZE*2 ;;DOUBLE PRECISION
STACK: ENDM
;
DUP MACRO
;; DUPLICATE TOP OF STACK
PUSH H
ENDM
;
SUM MACRO
;; ADD THE TOP TWO STACK ELEMENTS
POP D ;;TOP-1 TO DE
DAD D ;;BACK TO HL
ENDM
;
LSR MACRO LEN
;; LOGICAL SHIFT RIGHT BY LEN
REPT LEN ;;GENERATE INLINE
XRA A ;;CLEAR CARRY
MOV A,H
RAR ;;ROTATE WITH HIGH 0
MOV H,A
MOV A,L
RAR
MOV L,A ;;BACK WITH HIGH BIT
ENDM
ENDM
;
ADC0 EQU 1080H ;A-D CONVERTER 0
ADC1 EQU 1082H ;A-D CONVERTER 1
ADC2 EQU 1084H ;A-D CONVERTER 2
ADC3 EQU 1086H ;A-D CONVERTER 3
;
DAC0 EQU 1090H ;D-A CONVERTER 0
DAC1 EQU 1092H ;D-A CONVERTER 1
DAC2 EQU 1094H ;D-A CONVERTER 2
DAC3 EQU 1096H ;D-A CONVERTER 3
;
RDM MACRO ?C
;; READ A-D CONVERTER NUMBER "?C"
PUSH H ;;CLEAR THE STACK
;; READ FROM MEMORY MAPPED INPUT ADDRESS
LHLD ADC&?C
ENDM
;
WRM MACRO ?C
;; WRITE D-A CONVERTER NUMBER "?C"
SHLD DAC&?C ;;VALUE WRITTEN
POP H ;;RESTORE STACK
ENDM


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
; MACRO LIBRARY FOR STREET TREADLES
;
TRINP EQU 01H ;TREADLE INPUT PORT
TROUT EQU 01H ;TREADLE OUTPUT PORT
;
TREAD? MACRO TR,IFTRUE
;; "TREAD?" IS INVOKED TO CHECK IF
;; TREADLE GIVEN BY TR HAS BEEN SENSED.
;; IF SO, THE LATCH IS CLEARED AND CONTROL
;; TRANSFERS TO THE LABEL "IFTRUE"
LOCAL IFFALSE ;;IN CASE NOT SET
;;
IN TRINP ;;READ TREADLE SWITCHES
ANI 1 SHL TR ;;MASK PROPER BIT
JZ IFFALSE ;;SKIP RESET IF 0
MVI A,1 SHL TR ;;TO RESET THE BIT
OUT TROUT ;;CLEAR IT
JMP IFTRUE ;;GO TO TRUE LABEL
IFFALSE:
ENDM


View File

@@ -0,0 +1,36 @@
; MACRO LIBRARY FOR "WHEN" CONSTRUCT
;
; "WHEN" COUNTERS
; LABEL GENERATORS
GENWTST MACRO TST,X,Y,NUM
;; GENERATE A "WHEN" TEST (NEGATED FORM),
;; INVOKE MACRO "TST" WITH PARAMETERS
;; X,Y WITH JUMP TO ENDW & NUM
TST X,Y,,ENDW&NUM
ENDM
;
GENLAB MACRO LAB,NUM
;; PRODUCE THE LABEL "LAB" & "NUM"
LAB&NUM:
ENDM
;
; "WHEN" MACROS FOR START AND END
;
WHEN MACRO XV,REL,YV
;; INITIALIZE COUNTERS FIRST TIME
WCNT SET 0 ;;NUMBER OF WHENS
WHEN MACRO X,R,Y
GENWTST R,X,Y,%WCNT
WLEV SET WCNT ;;NEXT ENDW TO GENERATE
WCNT SET WCNT+1 ;;NUMBER OF "WHEN"S
ENDM
WHEN XV,REL,YV
ENDM
;
ENDW MACRO
;; GENERATE THE ENDING CODE FOR A "WHEN"
GENLAB ENDW,%WLEV
WLEV SET WLEV-1 ;;COUNT CURRENT LEVEL DOWN
;; WLEV MUST NOT GO BELOW 0 (NOT CHECKED)
ENDM


View File

@@ -0,0 +1,402 @@
Z-80 Macro Library Documentation
--------------------------------
I.
The purpose of this library is to enable the assembly of the Z-80
instruction set on a CP/M sytem using the CP/M MAC macro assembler.
This library is invoked with the pseudo-op:
" MACLIB Z80 "
II.
The following symbols and notations are used in the individual macro
descriptions;
r - Any of the 8 bit registers: A, B, C, D, E, H, L, or M
rr - Any of the 16 bit register pairs: BC, DE, HL, or SP
nn - 8 bit immediate data (0 through 255)
d - 8 bit signed displacment (-128 through +127)
nnnn - 16 bit address or immediate data (0 through 65535)
b - bit number (0-7, 7 is most significant, 0 is least)
addr - 16 bit address within PC+127 through PC-128
m(zzz) - Memory at address "zzz"
III.
MACLIB ver. Zilog ver TDL ver
-------------- ------------- -------------
LDX r,d LD r,(IX+d) MOV r,d(IX)
Load register from indexed memory (with IX)
LDY r,d LD r,(IY+d) MOV r,d(IY)
Load register from indexed memory (with IY)
STX r,d LD (IX+d),r MOV d(IX),r
Store register to indexed memory (with IX)
STY r,d LD (IY+d),r MOV d(IY),r
Store register to indexed memory (with IY)
MVIX nn,d LD (IX+d),nn MVI d(IX)
Move immediate to indexed memory (with IX)
MVIY nn,d LD (IY+d),nn MVI d(IY)
Move immediate to indexed memory (with IY)
LDAI LD A,I LDAI
Move I to A
LDAR LD A,R LDAR
Move R to A
STAI LD I,A STAI
Move A to I
STAR LD R,A STAR
Move A to R
LXIX nnnn LD IX,nnnn LXI IX,nnnn
Load IX immediate (16 bits)
LXIY nnnn LD IY,nnnn LXI IY,nnnn
Load IY immediate (16 bits)
LBCD nnnn LD BC,(nnnn) LBCD nnnn
Load BC direct (from memory at nnnn)
LDED nnnn LD DE,(nnnn) LDED nnnn
Load DE direct
LSPD nnnn LD SP,(nnnn) LSPD nnnn
Load SP direct
LIXD nnnn LD IX,(nnnn) LIXD nnnn
Load IX direct
LIYD nnnn LD IY,(nnnn) LIYD nnnn
Load IY direct
SBCD nnnn LD (nnnn),BC SBCD nnnn
Store BC direct (to memory at nnnn)
SDED nnnn LD (nnnn),DE SDED nnnn
Store DE direct
SSPD nnnn LD (nnnn),SP SSPD nnnn
Store SP direct
SIXD nnnn LD (nnnn),IX SIXD nnnn
Store IX direct
SIYD nnnn LD (nnnn),IY SIYD nnnn
Store IY direct
SPIX LD SP,IX SPIX
Copy IX to the SP
SPIY LD SP,IY SPIY
Copy IY to the SP
PUSHIX PUSH IX PUSH IX
Push IX into the stack
PUSHIY PUSH IY PUSH IY
Push IY into the stack
POPIX POP IX POP IX
Pop IX from the stack
POPIY POP IY POP IY
Pop IY from the stack
EXAF EX AF,AF' EXAF
Exchange AF and the alternate, AF'
EXX EXX EXX
Exchange BC DE HL with BC' DE' HL'
XTIX EX (SP),IX XTIX
Exchange IX with the top of the stack
XTIY EX (SP),IY XTIY
Exchange IY with the top of the stack
LDI LDI LDI
Move m(HL) to m(DE), increment DE and HL, decrement BC
LDIR LDIR LDIR
Repeat LDI until BC = 0
LDD LDD LDD
Move m(HL) to m(DE), decrement HL, DE, and BC
LDDR LDDR LDDR
Repeat LDD until BC = 0
CCI CPI CCI
Compare A with m(HL), increment HL, decrement BC
CCIR CPIR CCIR
Repeat CCI until BC = 0 or A = m(HL)
CCD CPD CCD
Compare A with m(HL), decrement HL and BC
CCDR CPDR CCDR
Repeat CCD until BC = 0 or A = m(HL)
ADDX d ADD (IX+d) ADD d(IX)
Indexed add to A
ADDY d ADD (IY+d) ADD d(IY)
Indexed add to A
ADCX d ADC (IX+d) ADC d(IX)
Indexed add with carry
ADCY d ADC (IY+d) ADC d(IY)
Indexed add with carry
SUBX d SUB (IX+d) SUB d(IX)
Indexed subtract
SUBY d SUB (IY+d) SUB d(IY)
Indexed Subtract
SBCX d SBC (IX+d) SBB d(IX)
Indexed subtract with "borrow"
SBCY d SBC (IY+d) SBB d(IY)
Indexed subtract with borrow
ANDX d AND (IX+d) ANA d(IX)
Indexed logical and
ANDY d AND (IY+d) ANA d(IY)
Indexed logical and
XORX d XOR (IX+d) XRA d(IX)
Indexed logical exclusive or
XORY d XOR (IY+d) XRA d(IY)
Indexed logical exclusive or
ORX d OR (IX+d) ORA d(IX)
Indexed logical or
ORY d OR (IY+d) ORA d(IY)
Indexed logical exclusive or
CMPX d CP (IX+d) CMP d(IX)
Indexed compare
CMPY d CP (IY+d) CMP d(IY)
Index compare
INRX d INC (IX+d) INR d(IX)
Increment memory at m(IX+d)
INRY d INC (IY+d) INR d(IY)
Increment memory at m(IY+d)
DCRX d INC (IX+d) INR d(IX)
Decrement memory at m(IX+d)
DCRY d DEC (IY+d) DCR d(IY)
Decrement memory at m(IX+d)
NEG NEG NEG
Negate A (two's complement)
IM0 IM0 IM0
Set interrupt mode 0
IM1 IM1 IM1
Set interrupt mode 1
IM2 IM2 IM2
Set interrupt mode 2
DADC rr ADC HL,rr DADC rr
Add with carry rr to HL
DSBC rr SBC HL,rr DSBC rr
Subtract with "borrow" rr from HL
DADX rr ADD IX,rr DADX rr
Add rr to IX (rr may be BC, DE, SP, IX)
DADY rr ADD IY,rr DADY rr
Add rr to IY (rr may be BC, DE, SP, IY)
INXIX INC IX INX IX
Increment IX
INXIY INC IY INX IY
Increment IY
DCXIX DEC IX DCX IX
Decrement IX
DCXIY DEC IY DCX IY
Decrement IY
BIT b,r BIT b,r BIT b,r
Test bit b in register r
SETB b,r SET b,r SET b,r
Set bit b in register r
RES b,r RES b,r RES b,r
Reset bit b in register r
BITX b,d BIT b,(IX+d) BIT b,d(IX)
Test bit b in memory at m(IX+d)
BITY b,d BIT b,(IY+d) BIT b,d(IY)
Test bit b in memory at m(IY+d)
SETX b,d SET b,(IX+d) SET b,d(IX)
Set bit b in memory at m(IX+d)
SETY b,d SET b,(IY+d) SET b,d(IY)
Set bit b in memory at m(IY+d)
RESX b,d RES b,(IX+d) RES b,d(IX)
Reset bit b in memory at m(IX+d)
RESY b,d RES b,(IY+d) RES b,d(IY)
Reset bit b in memory at m(IY+d)
JR addr JR addr-$ JMPR addr
Jump relative unconditional
JRC addr JR C,addr-$ JRC addr
Jump relative if Carry indicator true
JRNC addr JR NC,addr-$ JRNC addr
Jump relative if carry indicator false
JRZ addr JR Z,addr-$ JRC addr
Jump relative if Zero indicator true
JRNZ addr JR NZ,addr-$ JRNZ addr
Jump relative if Zero indicator false
DJNZ addr DJNZ addr-$ DJNZ addr
Decrement B, jump relative if non-zero
PCIX JMP (IX) PCIX
Jump to address in IX ie, Load PC from IX
PCIY JMP (IY) PCIY
Jump to address in IY
RETI RETI RETI
Return from interrupt
RETN RETN RETN
Return from non-maskable interrupt
INP r IN r,(C) INP r
Input from port C to register r
OUTP r OUT (C),r OUTP r
Output from register r to port (C)
INI INI INI
Input from port (C) to m(HL), increment HL, decrement b
INIR INIR INIR
Input from port (C) to m(HL), increment HL, decrement B, repeat if B <> 0
OUTI OTI OUTI
Output from m(HL) to port (C), increment HL, decrement B
OUTIR OTIR OUTIR
Repeat OUTI until B = 0
IND IND IND
Input from port (C) to m(HL), decrement HL & B
INDR INDR INDR
Repeat IND until B = 0
OUTD OTD OUTD
Output from m(HL) to port (C), decrement HL & B
OUTDR OTDR OUTDR
Repeat OUTD until B = 0
RLCR r RLC r RLCR r
Rotate left circular register
RLCX d RLC (IX+d) RLCR d(IX)
Rotate left circular indexed memory
RLCY d RLC (IY+d) RLCR d(IY)
Rotate left circular indexed memory
RALR r RL r RALR r
Rotate left arithmetic register
RALX d RL (IX+d) RALR d(IX)
Rotate left arithmetic indexed memory
RALY d RL (IY+d) RALR d(IY)
Rotate left arithmetic indexed memory
RRCR r RRC r RRCR r
Rotate right circular register
RRCX d RRC (IX+d) RRCR d(IX)
Rotate right circular indexed
RRCY d RRC (IY+d) RRCR d(IY)
Rotate right circular indexed
RARR r RR r RARR r
Rotate right arithmetic register
RARX d RR (IX+d) RARR d(IX)
Rotate right arithmetic indexed memory
RARY d RR (IY+d) RARR d(IY)
Rotate right arithmetic indexed memory
SLAR r SLA r SLAR r
Shift left register
SLAX d SLA (IX+d) SLAR d(IX)
Shift left indexed memory
SLAY d SLA (IY+d) SLAR d(IY)
Shift left indexed memory
SRAR r SRA r SRAR r
Shift right arithmetic register
SRAX d SRA (IX+d) SRAR d(IX)
Shift right arithmetic indexed memory
SRAY d SRA (IY+d) SRAR d(IY)
Shift right arithmetic indexed memory
SRLR r SRL r SRLR r
Shift right logical register
SRLX d SRL (IX+d) SRLR d(IX)
Shift right logical indexed memory
SRLY d SRL (IY+d) SRLR d(IY)
Shift right logical indexed memory
RLD RLD RLD
Rotate left digit
RRD RRD RRD
Rotate right digit


View File

@@ -0,0 +1,457 @@
; @CHK MACRO USED FOR CHECKING 8 BIT DISPLACMENTS
;
@CHK MACRO ?DD ;; USED FOR CHECKING RANGE OF 8-BIT DISP.S
IF (?DD GT 7FH) AND (?DD LT 0FF80H)
'DISPLACEMENT RANGE ERROR - Z80 LIB'
ENDIF
ENDM
LDX MACRO ?R,?D
@CHK ?D
DB 0DDH,?R*8+46H,?D
ENDM
LDY MACRO ?R,?D
@CHK ?D
DB 0FDH,?R*8+46H,?D
ENDM
STX MACRO ?R,?D
@CHK ?D
DB 0DDH,70H+?R,?D
ENDM
STY MACRO ?R,?D
@CHK ?D
DB 0FDH,70H+?R,?D
ENDM
MVIX MACRO ?N,?D
@CHK ?D
DB 0DDH,36H,?D,?N
ENDM
MVIY MACRO ?N,?D
@CHK ?D
DB 0FDH,36H,?D,?N
ENDM
LDAI MACRO
DB 0EDH,57H
ENDM
LDAR MACRO
DB 0EDH,5FH
ENDM
STAI MACRO
DB 0EDH,47H
ENDM
STAR MACRO
DB 0EDH,4FH
ENDM
LXIX MACRO ?NNNN
DB 0DDH,21H
DW ?NNNN
ENDM
LXIY MACRO ?NNNN
DB 0FDH,21H
DW ?NNNN
ENDM
LDED MACRO ?NNNN
DB 0EDH,5BH
DW ?NNNN
ENDM
LBCD MACRO ?NNNN
DB 0EDH,4BH
DW ?NNNN
ENDM
LSPD MACRO ?NNNN
DB 0EDH,07BH
DW ?NNNN
ENDM
LIXD MACRO ?NNNN
DB 0DDH,2AH
DW ?NNNN
ENDM
LIYD MACRO ?NNNN
DB 0FDH,2AH
DW ?NNNN
ENDM
SBCD MACRO ?NNNN
DB 0EDH,43H
DW ?NNNN
ENDM
SDED MACRO ?NNNN
DB 0EDH,53H
DW ?NNNN
ENDM
SSPD MACRO ?NNNN
DB 0EDH,73H
DW ?NNNN
ENDM
SIXD MACRO ?NNNN
DB 0DDH,22H
DW ?NNNN
ENDM
SIYD MACRO ?NNNN
DB 0FDH,22H
DW ?NNNN
ENDM
SPIX MACRO
DB 0DDH,0F9H
ENDM
SPIY MACRO
DB 0FDH,0F9H
ENDM
PUSHIX MACRO
DB 0DDH,0E5H
ENDM
PUSHIY MACRO
DB 0FDH,0E5H
ENDM
POPIX MACRO
DB 0DDH,0E1H
ENDM
POPIY MACRO
DB 0FDH,0E1H
ENDM
EXAF MACRO
DB 08H
ENDM
EXX MACRO
DB 0D9H
ENDM
XTIX MACRO
DB 0DDH,0E3H
ENDM
XTIY MACRO
DB 0FDH,0E3H
ENDM
LDI MACRO
DB 0EDH,0A0H
ENDM
LDIR MACRO
DB 0EDH,0B0H
ENDM
LDD MACRO
DB 0EDH,0A8H
ENDM
LDDR MACRO
DB 0EDH,0B8H
ENDM
CCI MACRO
DB 0EDH,0A1H
ENDM
CCIR MACRO
DB 0EDH,0B1H
ENDM
CCD MACRO
DB 0EDH,0A9H
ENDM
CCDR MACRO
DB 0EDH,0B9H
ENDM
ADDX MACRO ?D
@CHK ?D
DB 0DDH,86H,?D
ENDM
ADDY MACRO ?D
@CHK ?D
DB 0FDH,86H,?D
ENDM
ADCX MACRO ?D
@CHK ?D
DB 0DDH,8EH,?D
ENDM
ADCY MACRO ?D
@CHK ?D
DB 0FDH,8EH,?D
ENDM
SUBX MACRO ?D
@CHK ?D
DB 0DDH,96H,?D
ENDM
SUBY MACRO ?D
@CHK ?D
DB 0FDH,96H,?D
ENDM
SBCX MACRO ?D
@CHK ?D
DB 0DDH,9EH,?D
ENDM
SBCY MACRO ?D
@CHK ?D
DB 0FDH,9EH,?D
ENDM
ANDX MACRO ?D
@CHK ?D
DB 0DDH,0A6H,?D
ENDM
ANDY MACRO ?D
@CHK ?D
DB 0FDH,0A6H,?D
ENDM
XORX MACRO ?D
@CHK ?D
DB 0DDH,0AEH,?D
ENDM
XORY MACRO ?D
@CHK ?D
DB 0FDH,0AEH,?D
ENDM
ORX MACRO ?D
@CHK ?D
DB 0DDH,0B6H,?D
ENDM
ORY MACRO ?D
@CHK ?D
DB 0FDH,0B6H,?D
ENDM
CMPX MACRO ?D
@CHK ?D
DB 0DDH,0BEH,?D
ENDM
CMPY MACRO ?D
@CHK ?D
DB 0FDH,0BEH,?D
ENDM
INRX MACRO ?D
@CHK ?D
DB 0DDH,34H,?D
ENDM
INRY MACRO ?D
@CHK ?D
DB 0FDH,34H,?D
ENDM
DCRX MACRO ?D
@CHK ?D
DB 0DDH,035H,?D
ENDM
DCRY MACRO ?D
@CHK ?D
DB 0FDH,35H,?D
ENDM
NEG MACRO
DB 0EDH,44H
ENDM
IM0 MACRO
DB 0EDH,46H
ENDM
IM1 MACRO
DB 0EDH,56H
ENDM
IM2 MACRO
DB 0EDH,5EH
ENDM
BC EQU 0
DE EQU 2
HL EQU 4
IX EQU 4
IY EQU 4
DADC MACRO ?R
DB 0EDH,?R*8+4AH
ENDM
DSBC MACRO ?R
DB 0EDH,?R*8+42H
ENDM
DADX MACRO ?R
DB 0DDH,?R*8+09H
ENDM
DADY MACRO ?R
DB 0FDH,?R*8+09H
ENDM
INXIX MACRO
DB 0DDH,23H
ENDM
INXIY MACRO
DB 0FDH,23H
ENDM
DCXIX MACRO
DB 0DDH,2BH
ENDM
DCXIY MACRO
DB 0FDH,2BH
ENDM
BIT MACRO ?N,?R
DB 0CBH,?N*8+?R+40H
ENDM
SETB MACRO ?N,?R
DB 0CBH,?N*8+?R+0C0H
ENDM
RES MACRO ?N,?R
DB 0CBH,?N*8+?R+80H
ENDM
BITX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+46H
ENDM
BITY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+46H
ENDM
SETX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+0C6H
ENDM
SETY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+0C6H
ENDM
RESX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+86H
ENDM
RESY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+86H
ENDM
JR MACRO ?N
DB 18H,?N-$-1
ENDM
JRC MACRO ?N
DB 38H,?N-$-1
ENDM
JRNC MACRO ?N
DB 30H,?N-$-1
ENDM
JRZ MACRO ?N
DB 28H,?N-$-1
ENDM
JRNZ MACRO ?N
DB 20H,?N-$-1
ENDM
DJNZ MACRO ?N
DB 10H,?N-$-1
ENDM
PCIX MACRO
DB 0DDH,0E9H
ENDM
PCIY MACRO
DB 0FDH,0E9H
ENDM
RETI MACRO
DB 0EDH,4DH
ENDM
RETN MACRO
DB 0EDH,45H
ENDM
INP MACRO ?R
DB 0EDH,?R*8+40H
ENDM
OUTP MACRO ?R
DB 0EDH,?R*8+41H
ENDM
INI MACRO
DB 0EDH,0A2H
ENDM
INIR MACRO
DB 0EDH,0B2H
ENDM
IND MACRO
DB 0EDH,0AAH
ENDM
INDR MACRO
DB 0EDH,0BAH
ENDM
OUTI MACRO
DB 0EDH,0A3H
ENDM
OUTIR MACRO
DB 0EDH,0B3H
ENDM
OUTD MACRO
DB 0EDH,0ABH
ENDM
OUTDR MACRO
DB 0EDH,0BBH
ENDM
RLCR MACRO ?R
DB 0CBH, 00H + ?R
ENDM
RLCX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 06H
ENDM
RLCY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 06H
ENDM
RALR MACRO ?R
DB 0CBH, 10H+?R
ENDM
RALX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 16H
ENDM
RALY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 16H
ENDM
RRCR MACRO ?R
DB 0CBH, 08H + ?R
ENDM
RRCX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 0EH
ENDM
RRCY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 0EH
ENDM
RARR MACRO ?R
DB 0CBH, 18H + ?R
ENDM
RARX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 1EH
ENDM
RARY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 1EH
ENDM
SLAR MACRO ?R
DB 0CBH, 20H + ?R
ENDM
SLAX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 26H
ENDM
SLAY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 26H
ENDM
SRAR MACRO ?R
DB 0CBH, 28H+?R
ENDM
SRAX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 2EH
ENDM
SRAY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 2EH
ENDM
SRLR MACRO ?R
DB 0CBH, 38H + ?R
ENDM
SRLX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 3EH
ENDM
SRLY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 3EH
ENDM
RLD MACRO
DB 0EDH, 6FH
ENDM
RRD MACRO
DB 0EDH, 67H
ENDM


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
stat gensys.com $$r/w
ren gensys.gen=gensys.com
era *.lst
era *.lin
era *.sym
era *.bak
era gensys.plm
pip a:=e:gensys.plm
seteof gensys.plm
era ldrlwr.asm
pip a:=e:ldrlwr.asm
seteof ldrlwr.asm
stat a:x0100.* $$r/w
era x0100.asm
pip a:=e:x0100.asm
seteof x0100.asm
isx
plm80 gensys.plm debug
era gensys.plm
asm80 ldrlwr.asm debug
era ldrlwr.asm
asm80 x0100.asm debug
era x0100.asm
link gensys.obj,ldrlwr.obj,x0100.obj,plm80.lib to gensys.mod
era gensys.obj
era ldrlwr.obj
era x0100.obj
locate gensys.mod code(0100H) stacksize(100)
era gensys.mod
cpm
objcpm gensys
era gensys
vax gensys.lst $$stan
vax gensys.sym $$stan
vax gensys.lin $$stan
vax ldrlwr.lst $$stan
vax x0100.lst $$stan
pip b:=a:gensys.com
pip e:=a:gensys.com
era *.lst
era *.sym
era *.lin
era gensys.com
ren gensys.com=gensys.gen
;end gensys submit


View File

@@ -0,0 +1,39 @@
stat gensys.com $$r/w
era *.lst
era *.lin
era *.sym
era *.bak
era gensys.plm
pip a:=a:gensys.plm[g9]
seteof gensys.plm
era ldrlwr.asm
pip a:=a:ldrlwr.asm[g9]
seteof ldrlwr.asm
era x0100.asm
pip a:=a:x0100.asm[g9]
seteof x0100.asm
isx
plm80 gensys.plm debug
era gensys.plm
asm80 ldrlwr.asm debug
era ldrlwr.asm
asm80 x0100.asm debug
era x0100.asm
link gensys.obj,ldrlwr.obj,x0100.obj,plm80.lib to gensys.mod
era gensys.obj
era ldrlwr.obj
era x0100.obj
locate gensys.mod code(0100H) stacksize(100)
era gensys.mod
cpm
objcpm gensys
era gensys
vax gensys.lst $$stan
vax gensys.sym $$stan
vax gensys.lin $$stan
vax ldrlwr.lst $$stan
vax x0100.lst $$stan
era *.lst
era *.sym
era *.lin


View File

@@ -0,0 +1,28 @@
$title ('MP/M II V2.0 Loader BDOS Interface')
name ldmonx
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
cseg
public ldmon1,ldmon2
ldmon1 equ 0d06h
ldmon2 equ 0d06h
offset equ 0000h
fcb equ 005ch+offset
fcb16 equ 006ch+offset
tbuff equ 0080h+offset
public fcb,fcb16,tbuff
END


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
title 'MP/M II V2.0 Skeleton Ldrbios'
; Copyright (C) 1978, 1979, 1980, 1981
; Digital Research
; Box 579, Pacific Grove
; California, 93950
; Revised:
; 14 Sept 81 by Thomas Rolander
false equ 0
true equ not false
org 1700h
buff equ 0080h ;default buffer address
; jump vector for indiviual routines
jmp boot
wboote: jmp wboot
jmp const
jmp conin
jmp conout
jmp list
jmp punch
jmp reader
jmp home
jmp seldsk
jmp settrk
jmp setsec
jmp setdma
jmp read
jmp write
jmp list$st ; list status poll
jmp sect$tran ; sector translation
boot:
wboot:
gocpm:
ret
crtin: ; crt: input
ret
crtout: ; crt: output
ret
crtst: ; crt: status
ret
ttyin: ; tty: input
ret
ttyout: ; tty: output
ret
lptout: ; lpt: output
ret
lpt$st:
ret
conin equ crtin
const equ crtst
conout equ crtout
reader equ ttyin
punch equ ttyout
list equ lptout
listst equ lptst
seldsk: ;select disk given by register c
ret
;
home: ;move to home position
ret
;
settrk: ;set track number given by c
ret
;
setsec: ;set sector number given by c
ret
;
setdma: ;set dma address given by regs b,c
ret
;
sect$tran: ; translate the sector # in <c> if needed
ret
;
read: ;read next disk record (assuming disk/trk/sec/dma set)
ret
;
write: ;disk write function
ret
;
end


View File

@@ -0,0 +1,226 @@
$title ('MP/M II V2.0 Load, Relocate, and Write File')
name ldrlwr
;
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
cseg
extrn mon1 ;BDOS entry point
extrn FCBin ;FCB for input
extrn FCBout ;FCB for output
extrn sctbfr ;sector buffer
extrn offset ;relocation offset
extrn prgsiz ;program size
extrn bufsiz ;buffer size
;
; Procedure to Load, Relocate, and Write an SPR or RSP
;
LdRl:
public LdRl
;compute number of sectors to be read
lhld prgsiz
lxi d,007fh
dad d
mov a,l
ral ;carry = high order bit
mov a,h
ral ;A = # sectors
sta wrcnt
lxi h,sctbfr
rdloop:
sta rdcnt
shld DMA
xchg
mvi c,26
call mon1 ;set DMA address for next sector
call read ;read next sector
lhld DMA
lxi d,0080h
dad d
lda rdcnt
dcr a
jnz rdloop
lxi h,bitmap
xchg
mvi c,26
call mon1 ;set DMA address to bit map
;
;file loaded, ready for relocation
lhld prgsiz
mov b,h
mov c,l ;BC = program size
xchg
lxi h,sctbfr
xchg ;DE = base of program
dad d ;HL = bit map base
push h ;save bit map base in stack
lda DMA
adi 128
sta btmptp
lda offset
mov h,a ;H = relocation offset
pgrel0:
mov a,b ;bc=0?
ora c
jz ExitLdRl
;
; not end of the relocation,
; may be into next byte of bit map
dcx b ;count length down
mov a,e
sui low(sctbfr)
ani 111b ;0 causes fetch of next byte
jnz pgrel3
; fetch bit map from stacked address
xthl
lda btmptp
cmp l
jnz pgrel2
mvi a,low(bitmap+128)
sta btmptp
push b
push d
lxi d,FCBin
mvi c,20
call mon1
pop d
pop b
lxi h,bitmap
ora a
jnz errtn ;return with error condition
pgrel2:
mov a,m ;next 8 bits of map
inx h
xthl ;base address goes back to stack
mov l,a ;l holds map as 8 bytes done
pgrel3:
mov a,l
ral ;cy set to 1 if reloc necessary
mov l,a ;back to l for next time around
jnc pgrel4 ;skip relocation if cy=0
;
; current address requires relocation
ldax d
add h ;apply bias in h
stax d
pgrel4:
inx d ;to next address
jmp pgrel0 ;for another byte to relocate
;
; Write out relocated data (top to bottom)
;
ExitLdRl:
pop h
lxi h,0
mov a,h
ret
;
FxWr:
public FxWr
;prefill buffer with zeros for filler record
lhld DMA
lxi b,128
dad b
xra a
filloop:
mov m,a
inx h
dcr c
jnz filloop
lhld bufsiz
mov a,l
ora h
jz nobuf
lxi d,255
dad d
mov a,h
add a
push psw
lhld DMA
lxi b,128
dad b
xchg
mvi c,26
call mon1 ;set DMA address for next sector
pop psw
bufwr:
push psw
call write ;write next sector
pop psw
dcr a
jnz bufwr
nobuf:
lxi b,0
lxi h,wrcnt
mov a,m
ani 1
jz evenrecord
inr m ;force even # of records
mvi c,128
evenrecord:
lhld DMA
dad b
Wrloop:
shld DMA
xchg
mvi c,26
call mon1 ;set DMA address for next sector
call write ;write next sector
lhld DMA
lxi d,-0080h
dad d
lda wrcnt
dcr a
sta wrcnt
jnz Wrloop
;
; Load, Relocation, and Write finished
;
ret
;
; Local Procedures
;
write:
lxi h,FCBout
xchg
mvi c,21 ;write sequential
call mon1
ora a
jnz errtn
ret
read:
lxi h,FCBin
xchg
mvi c,20 ;read sequential
call mon1
ora a
rz
errtn:
pop h ;discard return address
lxi h,0ffffh
mov a,h
ret ;return with error condition
;
; Local Data Segment
;
rdcnt: ds 2 ;read counter
wrcnt: ds 2 ;write counter
DMA: ds 2 ;DMA address
bitmap: ds 128 ;bit map buffer
btmptp: ds 1 ;bit low (bitmap+128)
end


View File

@@ -0,0 +1,553 @@
$title ('MP/M II V2.0 Loader')
mpmldr:
do;
/*
Copyright (C) 1979,1980,1981
Digital Research
P.O. Box 579
Pacific Grove, CA 93950
Revised:
14 Sept 81 by Thomas Rolander
*/
declare true literally '0FFH';
declare false literally '0';
declare forever literally 'while true';
declare boolean literally 'byte';
declare start label;
declare jmp$to$start structure (
jmp$instr byte,
jmp$location address ) data (
0C3H,.start-3);
declare signon (*) byte data (
0dh, /* Filler */
0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,
0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,0ah,
'MP/M II V2.0 Loader ',0dh,0ah,
'Copyright (C) 1981, Digital Research',0dh,0dh,0ah,'$');
/**************** Warning ******************/
/* */
/* This location must be at or above 015CH */
/* */
/*********************************************/
declare copyright (*) byte data (
'COPYRIGHT (C) 1981,');
declare company$name (*) byte data (
' DIGITAL RESEARCH ');
declare serial$number (6) byte data (
'654321');
declare err$msgadr address initial (.default$err$msg);
declare err$msg based err$msgadr (1) byte;
declare default$err$msg (*) byte data (
'Dsk rd err','$');
declare mon1 literally 'ldmon1';
declare mon2 literally 'ldmon2';
mon1:
procedure (func,info) external;
declare func byte;
declare info address;
end mon1;
mon2:
procedure (func,info) byte external;
declare func byte;
declare info address;
end mon2;
declare fcb (1) byte external;
declare fcb16 (1) byte external;
declare tbuff (1) byte external;
/**************************************
* *
* B D O S Externals *
* *
**************************************/
write$console:
procedure (char);
declare char byte;
call mon1 (2,char);
end write$console;
print$buffer:
procedure (buffer$address);
declare buffer$address address;
call mon1 (9,buffer$address);
end print$buffer;
reset$disk$system:
procedure;
call mon1 (13,0);
end reset$disk$system;
open$file:
procedure (fcb$address) byte;
declare fcb$address address;
return mon2 (15,fcb$address);
end open$file;
read$record:
procedure (fcb$address) byte;
declare fcb$address address;
return mon2 (20,fcb$address);
end read$record;
set$DMA$address:
procedure (DMA$address);
declare DMA$address address;
call mon1 (26,DMA$address);
end set$DMA$address;
/**************************************
* *
* Misc. BDOS procs *
* *
**************************************/
crlf:
procedure;
call write$console (0dh);
call write$console (0ah);
end crlf;
printdecimal:
procedure (n);
declare n byte;
declare (digit,pdigit) byte;
pdigit = false;
digit = '0';
do while n >= 100;
pdigit = true;
digit = digit + 1;
n = n - 100;
end;
if pdigit then
do;
call write$console (digit);
digit = '0';
end;
do while n >= 10;
pdigit = true;
digit = digit + 1;
n = n - 10;
end;
if pdigit then
call write$console (digit);
call write$console ('0'+n);
end printdecimal;
printnib:
procedure (n);
declare n byte;
if n > 9
then call write$console (n+'A'-10);
else call write$console (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 write$console (' ');
call write$console (' ');
call printhex (high(a));
call printhex (low(a));
call write$console ('H');
end printaddr;
printstring:
procedure (sadr,sz);
declare sadr address;
declare sz byte;
declare s based sadr (1) byte;
declare i byte;
do i = 0 to sz-1;
call write$console (s(i) and 7fh);
end;
end printstring;
printname:
procedure (nadr);
declare nadr address;
call printstring (nadr,11);
end printname;
printitems:
procedure (nadr,base,size);
declare (nadr,base,size) address;
call print$name (nadr);
call printaddr (base);
call printaddr (size);
call crlf;
end printitems;
printitemsadr:
procedure (nadr,base,size);
declare nadr address;
declare (base,size) byte;
call printitems (nadr,
double (base)*256,
double (size)*256);
end printitemsadr;
match$serial:
procedure (cpyrtadr,memadr);
declare (cpyrtadr,memadr) address;
declare (i,j) byte;
declare cpyrt based cpyrtadr (1) byte;
declare mem based memadr (1) byte;
do forever;
i,j = -1;
do while cpyrt(i:=i+1) = mem(j:=j+1);
;
end;
if i > 23 then return;
if (memadr = 0) or (i > 17) then
do;
err$msgadr = .('Synchronization: Serial numbers do not match','$');
go to error;
end;
memadr = memadr + 1;
end;
end match$serial;
declare (base,cur$top,prev$top) address;
declare cur$record address;
declare sysdatadr address;
declare wordadr address;
declare word based wordadr address;
declare xios$common based cur$top structure (
jmpinstr byte,
base address );
declare actual$xios$common$base address;
declare nrec byte;
declare notdone boolean;
declare rspname (11) byte initial (
'????????RSP');
declare brspname (11) byte initial (
'????????BRS');
declare mpm$sys$fcb (36) byte initial (
0,'MPM ','SYS',0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
declare entry$point (3) address;
declare system$data (256) byte at (.fcb);
$include (sysdat.lit)
declare break boolean;
declare debug$RST byte;
declare destination based cur$top (1) byte;
declare link based cur$top address;
declare test$byte based cur$top byte;
declare rspcnt byte;
print2addr:
procedure;
call printaddr (cur$top);
call printaddr (prev$top-cur$top);
call crlf;
end print2addr;
load$system$data:
procedure;
declare cntr byte;
call set$DMA$address (.system$data);
if open$file (.mpm$sys$fcb) = 0ffh then
do;
call move (4,.(' ?','$'),.mpm$sys$fcb(12));
err$msgadr = .mpm$sys$fcb(1);
go to error;
end;
if read$record (.mpm$sys$fcb) <> 0 then
do;
go to error;
end;
call set$DMA$address (.system$data(128));
if read$record (.mpm$sys$fcb) <> 0 then
do;
go to error;
end;
sysdatadr,
cur$top = shl(double(mem$top),8);
call print$buffer (.(
'Nmb of consoles = ','$'));
call printnib (nmb$cns);
call print$buffer (.(0dh,0ah,
'Breakpoint RST # = ','$'));
call printnib (brkpt$RST);
/**********************************************************
if z80$cpu then
call print$buffer (.(0dh,0ah,
'Z80 Alternate register set saved/restored',
' by dispatcher','$'));
if bank$switched <> 0 then
do;
call print$buffer (.(0dh,0ah,
'Common base addr =','$'));
call printaddr (double (common$base) * 256);
end;
if banked$bdos then
call print$buffer (.(0dh,0ah,
'Banked BDOS file manager','$'));
call print$buffer (.(0dh,0ah,
'Nmb of ticks/second = ','$'));
call printdecimal (ticks$per$second);
call print$buffer (.(0dh,0ah,
'System drive = ','$'));
call write$console ('A'+system$drive-1);
call write$console (':');
call print$buffer (.(0dh,0ah,
'Max lckd recs/proc = ','$'));
call printdecimal (max$locked$records);
call print$buffer (.(0dh,0ah,
'Totl lckd recs/sys = ','$'));
call printdecimal (total$system$locked$records);
call print$buffer (.(0dh,0ah,
'Max open files/proc = ','$'));
call printdecimal (max$open$files);
call print$buffer (.(0dh,0ah,
'Totl open files/sys = ','$'));
call printdecimal (total$system$open$files);
call print$buffer (.(0dh,0ah,
'To<54> o<> MP/M-80 =','$'));
call printaddr (cur$top + 255);
*************************************************************/
call print$buffer (.(0dh,0ah,
'Memory Segment Table:',0dh,0ah,'$'));
call printitems (.('SYSTEM DAT'),cur$top,256);
cur$top = cur$top
- (prev$top := (shr(nmb$cns-1,2)+1)*256);
call printitems (.('TMPD DAT'),cur$top,prev$top);
if sys$call$stks then
do;
cur$top = cur$top
- (prev$top := (shr(nmb$mem$seg-2,2)+1)*256);
call printitems (.('USERSYS STK'),cur$top,prev$top);
end;
end load$system$data;
display$OS:
procedure;
declare (base,cntr) byte;
declare rspsadr (16) address;
declare temp$rspl address;
declare temp$rspl$adr based temp$rspl address;
call printitemsadr (.('XIOSJMP TBL'),
xios$jmp$tbl$base,
1);
call printitemsadr (.('RESBDOS SPR'),
resbdos$base,
xios$jmp$tbl$base-resbdos$base);
call printitemsadr (.('XDOS SPR'),
xdos$base,
resbdos$base-xdos$base);
if nmb$rsps <> 0 then
do;
cntr = 0;
temp$rspl = rspl;
do while (rspsadr(cntr):=temp$rspl) <> 0;
cntr = cntr + 1;
temp$rspl = temp$rspl$adr;
end;
rspsadr(cntr) = double (xdos$base)*256;
do while (cntr:=cntr-1) <> -1;
call move (8,rspsadr(cntr)+6+2,.rspname);
call printitems (.rspname,
rspsadr(cntr),
rspsadr(cntr+1)-rspsadr(cntr));
end;
end;
call printitemsadr (.('BNKXIOS SPR'),
bnkxios$base,
rsp$base-bnkxios$base);
call printitemsadr (.('BNKBDOS SPR'),
bnkbdos$base,
bnkxios$base-bnkbdos$base);
call printitemsadr (.('BNKXDOS SPR'),
bnkxdos$base,
bnkbdos$base-bnkxdos$base);
call printitemsadr (.('TMP SPR'),
tmp$base,
bnkxdos$base-tmp$base);
if nmb$brsps <> 0 then
do;
cntr = 0;
temp$rspl = brspl;
do while (rspsadr(cntr):=temp$rspl) <> 0;
cntr = cntr + 1;
temp$rspl = temp$rspl + 2;
temp$rspl = temp$rspl$adr;
end;
rspsadr(cntr) = double (tmp$base)*256;
do while (cntr:=cntr-1) <> -1;
call move (8,rspsadr(cntr)+4,.brspname);
call printitems (.brspname,
rspsadr(cntr),
rspsadr(cntr+1)-rspsadr(cntr));
end;
base = brsp$base;
end;
else
do;
base = tmp$base;
end;
cntr = base - high (total$list$items*10 + 255);
call printitemsadr (.('LCKLSTS DAT'),
cntr,
base-cntr);
if nmb$cns <> 0 then
do;
base = cntr;
cntr = base - nmb$cns;
call printitemsadr (.('CONSOLE DAT'),
cntr,
base-cntr);
end;
end display$OS;
display$mem$map:
procedure;
declare msgadr address;
call print$buffer (.(
'-------------------------',0dh,0ah,'$'));
msgadr = .('MP/M II Sys','$');
do nrec = 0 to nmb$mem$seg-1;
call print$buffer (msgadr);
msgadr = .('Memseg Usr','$');
call printaddr (shl(double(mem$seg$tbl(nrec).base),8));
call printaddr (shl(double(mem$seg$tbl(nrec).size),8));
if bank$switched <> 0 then
do;
call print$buffer (.(' Bank ','$'));
call printdecimal (mem$seg$tbl(nrec).bank);
end;
call crlf;
end;
end display$mem$map;
Restart$instr:
procedure;
disable; /* this disable is overlayed with RST x */
end Restart$instr;
xeq$mpm:
procedure;
declare brkpt$adr address data (.Restart$instr);
declare brkpt based brkpt$adr byte;
declare loc$0007 byte at (0007h);
stack$ptr = .entry$point(2);
/* if command tail starts with 'B' then break */
if break then
do;
if mem$top >= loc$0007 then
do;
errmsg$adr = .('No break, CP/M debugger overlaid by MP/M',
'$');
go to error;
end;
brkpt = 1100$0111b or shl(debug$RST,3);
call Restart$instr;
end;
end xeq$mpm;
command$tail:
procedure;
declare fcbstr$adr address;
declare fcbstr based fcbstr$adr (1) byte;
break = false;
fcbstr$adr = .fcb;
if fcbstr(1) = ' ' then
return;
if fcbstr(1) = '$' then
do;
if fcbstr(2) = 'B' then
do;
break = true;
if fcbstr(3) = ' '
then debug$RST = 7;
else debug$RST = fcbstr(3) and 0000$0111b;
end;
fcbstr$adr = .fcb16;
end;
if (fcbstr( 9) = 'S') and
(fcbstr(10) = 'Y') and
(fcbstr(11) = 'S') then
do;
call move (9,fcbstr$adr,.mpm$sys$fcb);
end;
end command$tail;
/*
Main Program
*/
start:
/* disable; -> removed from base of MP/M 1.x loader */
call reset$disk$system;
call command$tail;
call print$buffer (.signon);
call load$system$data;
cur$top = sysdatadr;
cur$record = 1;
do while (cur$record:=cur$record+1) <> nmb$records;
call set$DMA$address (cur$top:=cur$top-128);
if read$record (.mpm$sys$fcb) <> 0 then
do;
errmsg$adr = .('failed to read MPM.SYS','$');
go to error;
end;
end;
entry$point(2) = double (xdos$base)*256;
call match$serial (.company$name,.system$data);
call display$OS;
call display$mem$map;
call move (256,.system$data,sysdatadr);
call xeq$mpm;
error:
call print$buffer (.(0dh,0ah,
'MPMLDR error: ','$'));
call print$buffer (err$msgadr);
do forever;
stackptr = 0;
disable;
halt;
end;
end mpmldr;


View File

@@ -0,0 +1,60 @@
stat mpmldr.com $$r/w
ren mpmldr.gen=mpmldr.com
era *.lst
era *.bak
era *.sym
era *.lin
era mpmldr.plm
pip a:=e:mpmldr.plm
seteof mpmldr.plm
era ldmonx.asm
pip a:=e:ldmonx.asm
seteof ldmonx.asm
isx
plm80 mpmldr.plm debug
era mpmldr.plm
asm80 ldmonx.asm debug
era ldmonx.asm
link mpmldr.obj,ldmonx.obj,plm80.lib to mpmldr.mod
era mpmldr.obj
era ldmonx.obj
locate mpmldr.mod stacksize(20) code(0100h)
era mpmldr.mod
objhex mpmldr to impmldr.hex
cpm
objcpm mpmldr
vax mpmldr.lst $$stan
vax mpmldr.sym $$stan
vax mpmldr.lin $$stan
vax ldmonx.lst $$stan
era *.lst
era *.lin
era *.sym
era ldrbdos.asm
pip a:=e:ldrbdos.asm
seteof ldrbdos.asm
era ldrbios.asm
pip a:=e:ldrbios.asm
seteof ldrbios.asm
mac ldrbdos
xref ldrbdos
era ldrbdos.asm
vax ldrbdos.xrf $$stan
vax ldrbdos.sym $$stan
mac ldrbios
xref ldrbios
era ldrbios.asm
vax ldrbios.xrf $$stan
vax ldrbios.sym $$stan
pip mpmldr.hex=impmldr.hex[I],ldrbdos.hex[I],ldrbios.hex[H]
era impmldr.hex
era ldrbdos.hex
era ldrbios.hex
load mpmldr
era mpmldr.hex
pip e:=a:mpmldr.com
pip b:=a:mpmldr.com
era mpmldr.com
ren mpmldr.com=mpmldr.gen
;end mpmldr submit


View File

@@ -0,0 +1,52 @@
stat mpmldr.com $$r/w
era *.lst
era *.bak
era *.sym
era *.lin
era mpmldr.plm
pip a:=a:mpmldr.plm[g9]
seteof mpmldr.plm
era ldmonx.asm
pip a:=a:ldmonx.asm[g9]
seteof ldmonx.asm
isx
plm80 mpmldr.plm debug
era mpmldr.plm
asm80 ldmonx.asm debug
era ldmonx.asm
link mpmldr.obj,ldmonx.obj,plm80.lib to mpmldr.mod
era mpmldr.obj
era ldmonx.obj
locate mpmldr.mod stacksize(20) code(0100h)
era mpmldr.mod
objhex mpmldr to impmldr.hex
cpm
objcpm mpmldr
vax mpmldr.lst $$stan
vax mpmldr.sym $$stan
vax mpmldr.lin $$stan
vax ldmonx.lst $$stan
era *.lst
era *.lin
era *.sym
era ldrbdos.asm
pip a:=a:ldrbdos.asm[g9]
seteof ldrbdos.asm
era ldrbios.asm
pip a:=a:ldrbios.asm[g9]
seteof ldrbios.asm
mac ldrbdos
era ldrbdos.asm
vax ldrbdos.prn $$stan
vax ldrbdos.sym $$stan
mac ldrbios
era ldrbios.asm
vax ldrbios.prn $$stan
vax ldrbios.sym $$stan
pip mpmldr.hex=impmldr.hex[I],ldrbdos.hex[I],ldrbios.hex[H]
era impmldr.hex
era ldrbdos.hex
era ldrbios.hex
load mpmldr
era mpmldr.hex


View File

@@ -0,0 +1,34 @@
$title ('MP/M II V2.0 Externals')
name x0100
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
CSEG
offset equ 0000h
mon1 equ 0005h+offset
mon2 equ 0005h+offset
mon2a equ 0005h+offset
public mon1,mon2,mon2a
fcb equ 005ch+offset
fcb16 equ 006ch+offset
tbuff equ 0080h+offset
public fcb,fcb16,tbuff
bdisk equ 0004h+offset
maxb equ 0006h+offset
buff equ 0080h+offset
boot equ 0000h+offset
public bdisk,maxb,buff,boot
END


View File

@@ -0,0 +1,219 @@
title 'MP/M II V2.0 Attach Process'
name 'attch'
dseg
@@attch:
public @@attch
cseg
;attch:
@attch:
public @attch
;do;
;/*
; Copyright (C) 1979, 1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
;$include (common.lit)
;$nolist
;$include (proces.lit)
;$nolist
;$include (queue.lit)
;$nolist
;$include (xdos.lit)
;$nolist
;$include (datapg.ext)
;$nolist
;$include (xdos.ext)
;$nolist
;$include (bdos.ext)
;$nolist
; declare rlr address external;
extrn rlr
; nfxdos:
; procedure (func,info) external;
extrn nfxdos
; declare func byte;
; declare info address;
; end nfxdos;
; xdos:
; procedure (func,info) byte external;
extrn xdos
; declare func byte;
; declare info address;
; end xdos;
; printb:
; procedure (bufferadr) external;
extrn printb
; declare bufferadr address;
; end printb;
; declare rlrpd based rlr process$descriptor;
;/*
dseg
; Attach Process Data Segment
;*/
; declare attch$pd process$descriptor public
; initial (0,rtr$status,20,.attch$entrypt,
; 'ATTACH ',' '+80h,0,0ffh,0);
attchpd:
public attchpd
dw 0 ; pl
db 0 ; status
db 20 ; priority
dw attchentrypt ; stkptr
db 'ATTACH ',' '+80h ; name
db $-$ ; console
db 0ffh ; memseg (system)
dw $-$ ; b
dw $-$ ; thread
dw $-$ ; disk set DMA
db $-$ ; disk select / user code
dw $-$ ; dcnt
db $-$ ; searchl
dw $-$ ; searcha
ds 2 ; drvact
ds 20 ; registers
ds 2 ; sratch
; declare attch$stk (14) address
; initial (restarts,.attch);
attchstk:
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h
attchentrypt:
dw attch
; declare attch$lqcb structure (
; lqueue,
; buf (12) byte )
; initial (0,'ATTACH ',10,1);
attchlqcb:
dw $-$ ; ql
db 'ATTACH ' ; name
dw 10 ; msglen
dw 1 ; nmbmsgs
dw $-$ ; dqph
dw $-$ ; nqph
dw $-$ ; mh
dw $-$ ; mt
dw $-$ ; bh
ds 12 ; buf (12) byte
; declare attch$uqcb userqcbhead public
; initial (.attch$lqcb,.field);
attchuqcb:
dw attchlqcb ; pointer
dw field ; msgadr
; declare field (11) byte;
field:
ds 11
; declare console byte at (.field(1));
console equ field+1
cseg
atfail:
db 0dh,0ah
db 'Attach failed.'
db '$'
;/*
; attch:
; The purpose of the attach process is to attach
; the console to the specified process.
; Entry Conditions:
; None
; Exit Conditions:
; None
;*/
; attch:
attch:
; procedure public;
public attch
; declare i byte;
; call nfxdos (make$queue,.attch$lqcb);
LXI D,ATTCHLQCB
MVI C,86H
; do forever;
@4:
CALL NFXDOS
; call nfxdos (read$queue,.attch$uqcb);
LXI D,ATTCHUQCB
MVI C,89H
CALL NFXDOS
; rlrpd.console = console;
LXI B,0EH
LHLD RLR
DAD B
LDA CONSOLE
MOV M,A
; i = 2;
MVI C,8
LXI H,FIELD+2
; do while i <> 10;
@6:
; if field(i) = 0 then
MOV A,M
ORA A
JNZ @1
; do while i <> 10;
@8:
; field(i) = ' ';
MVI M,20H
; i = i + 1;
INX H
DCR C
JNZ @8
JMP @7
; end;
@1:
; else i = i + 1;
INX H
DCR C
JNZ @6
; end;
@7:
; /* specify that console of attached process must
; match that currently of the attach process */
; field(10) = 0ffh;
MVI M,0FFH
; if xdos (assign$console,.field(1)) = 255 then
LXI D,FIELD+1H
MVI C,95H
CALL XDOS
INR L
; do;
; call printb (.('Attach failed.','$'));
LXI B,atfail
CZ PRINTB
; end;
; call nfxdos (detlst,0);
mvi c,9fh
call xdos
; call nfxdos (detach,0);
MVI C,93H
; end; /* forever */
JMP @4
; end attch;
;end attch;
END


View File

@@ -0,0 +1,31 @@
ren resbdos.rps=resbdos.spr
ren bnkbdos.rps=bnkbdos.spr
era resbdos.asm
pip a:=e:*.asm
pip resbdos.asm=resbdos1.asm,conbdos.asm
rmac resbdos
era resbdos.asm
xref resbdos
vax resbdos.xrf $$stan
link resbdos[os]
era bnkbdos.asm
pip bnkbdos.asm=bnkbdos1.asm,bdos30.asm
rmac bnkbdos
era bnkbdos.asm
xref bnkbdos
vax bnkbdos.xrf $$stan
link bnkbdos[os]
pip e:=a:resbdos.spr
pip e:=a:bnkbdos.spr
pip b:=a:resbdos.spr
pip b:=a:bnkbdos.spr
era resbdos.spr
era bnkbdos.spr
ren resbdos.spr=resbdos.rps
ren bnkbdos.spr=bnkbdos.rps
era bdos30.asm
era bnkbdos1.asm
era conbdos.asm
era resbdos1.asm
;end bdos submit


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
era resbdos.asm
pip resbdos.asm=resbdos1.asm,conbdos.asm
rmac resbdos
era resbdos.asm
xref resbdos
vax resbdos.xrf $$stan
link resbdos[os]
era bnkbdos.asm
pip bnkbdos.asm=bnkbdos1.asm,bdos30.asm
rmac bnkbdos
era bnkbdos.asm
xref bnkbdos
vax bnkbdos.xrf $$stan
link bnkbdos[os]


View File

@@ -0,0 +1,288 @@
title 'Non-Resident Portion of Banked BDOS'
cseg
;***************************************************************
;***************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** N o n - R e s i d e n t P o r t i o n **
;** B a n k e d B D O S **
;** **
;***************************************************************
;***************************************************************
;/*
; Copyright (C) 1978,1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by David K. Brown
;*/
on equ 0ffffh
off equ 00000h
MPM EQU ON
MPMENV EQU ON
BNKBDOS EQU ON
ctlc equ 03h ;control-c
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
;
; BDOS call equates
dskinit equ 13
dskslct equ 14
dsksetDMA equ 26
setusercode equ 32
;
; Process Descriptor Offsets
pname equ 6
console equ 14
memseg equ 15
thread equ 18
disksetDMA equ 20
diskselect equ 22
diskparams equ 23
MULT$CNT$OFF EQU 50
PD$CNT$OFF EQU 51
;
; System Data Page Offsets
userstackflag equ 3
brkvctr equ 48
usrstkregion equ 80
;
;
; MP/M Data Page Offsets
rlros equ 5
thrdrt equ 17
msegtbl equ 150
;
;**************************************************
;* *
;**************************************************
;
org 0000h
base equ $
jmp bnkbdose
JMP BNKBDOSINIT
JMP REMOVE$FILES
XDMAAD: DW $-$
SYSDAT: DW $-$
BUFFA: DW $-$
bnkbdosinit:
pop h! push h! inx h! inx h! inx h
lxi d,extjmptbl! mvi c,24! xchg
CALL MOVE
;INITIALIZE OPEN FILE AND LOCKED RECORD LIST
LHLD SYSDAT! MVI L,187
MOV A,M! STA LOCK$MAX! INX H
MOV A,M! STA OPEN$MAX
INX H! MOV E,M! INX H! MOV D,M! INX H
PUSH D
MOV E,M! INX H! MOV D,M! XCHG! SHLD FREE$ROOT
POP D! DCX D! LXI B,10
ILIST:
PUSH D
MOV D,H! MOV E,L! DAD B! XCHG
MOV M,E! INX H! MOV M,D! XCHG
POP D! DCX D! MOV A,D! ORA E! JNZ ILIST
MOV M,A! DCX H! MOV M,A! RET
extjmptbl:
reboot: jmp $-$
rlr: jmp $-$
rlradr: jmp $-$
dsplynm: jmp $-$
xprint: jmp $-$
xcrlf: jmp $-$
conoutx: jmp $-$
getmemseg: jmp $-$
;
;************************************************
;* *
;************************************************
;
bnkbdose:
push d! push b
LXI H,DELETED$FILES
DI
MOV A,M! ORA A! MVI M,0
EI
CNZ DELETE$FILES
;perform the necessary BDOS parameter initialization
;disk set DMA
call rlr! SHLD PDADDR
lxi b,disksetDMA! dad b
mov e,m! inx h! mov d,m! push h! xchg! shld dmaad
mov b,h! mov c,l! call setdmaf
;disk select
pop h! inx h
mov a,m! rrc! rrc! rrc! rrc! ani 0fh! STA SELDSK
;set user code
mov a,m! ani 0fh! STA USRCODE
;copy local disk params
inx h! push h! lxi d,dcnt
XCHG! MVI C,2! CALL MOVE
LXI H,SEARCHL! LDAX D! MOV M,A
LXI H,MULT$CNT$OFF-DISKPARAMS-2! DAD D
MOV A,M! STA MULT$CNT
INX H! MOV A,M! ANI 0F0H! CMP M! JZ BNKBDOS1
ADI 10H! MOV M,A
BNKBDOS1:
STA PDCNT
;perform requested BDOS function
pop h! pop b! pop d! push h
call bdose
;save results
pop d! push h ; save results in HL
;copy disk params
lxi h,dcnt
XCHG! MVI C,2! CALL MOVE
LXI D,SEARCHL! LDAX D! MOV M,A
;return to non-banked bdos, will restore calling bank
; and release disk mutual exclusion message
pop h! ret
bdose:
xchg! shld info! xchg ;save parameter
mov a,e! sta linfo ;linfo = low(info) - don't equ
lxi h,0! shld aret ;return value defaults to 0000
SHLD RESEL ; RESEL,FCBDSK = 0
SHLD COMP$FCB$CKS ; COMP$FCB$CKS,SEARCH$USER0 = 0
SHLD MAKE$XFCB ; MAKE$XFCB,FIND$XFCB = 0
DAD SP! SHLD ENTSP ; SAVE STACK POSITION
lxi h,goback! push h ;fake return address
;compute disk function code address
mov a,c! STA FX! mov c,e! mov b,d
CPI NFUNCS+12! JNC HIGH$FXS
LXI H,DISKF-24! JMP BDOS$JMP
HIGH$FXS:
LXI H,XDISKF-200
BDOS$JMP:
mov e,a! mvi d,0 ;DE=func, HL=.diskf-24
dad d! dad d! mov e,m! inx h! mov d,m ;DE=functab(func)
LHLD INFO ;INFO IN DE FOR LATER EXCHANGE
xchg! pchl ;dispatched
;
; dispatch table for disk functions
diskf:
dw func12,func13,func14,func15
dw func16,func17,func18,func19
dw func20,func21,func22,func23
dw func24,func25,func26,func27
dw func28,func29,func30,func31
dw func32,func33,func34,func35
dw func36,func37,func38,func39
DW FUNC40,FUNC41,FUNC42,FUNC43
DW FUNC44,FUNC45,FUNC46,FUNC47
DW FUNC48,FUNC49,FUNC50
nfuncs equ ($-diskf)/2
XDISKF:
DW FUNC100,FUNC101,FUNC102,FUNC103
DW FUNC104,FUNC105,FUNC106,FUNC107
PERERR: DW PERSUB ;PERMANENT ERROR SUBROUTINE
RODERR: DW RODSUB ;RO DISK ERROR SUBROUTINE
ROFERR: DW ROFSUB ;RO FILE ERROR SUBROUTINE
SELERR: DW SELSUB ;SELECT ERROR SUBROUTINE
;
; error subroutines
PERSUB:
;report permanent error
lxi h,permsg! jmp report$err ;to report the error
;
SELSUB:
;report select error
lxi h,selmsg! jmp report$err ;wait console before boot
;
RODSUB:
;report write to read/only disk
lxi h,rodmsg! jmp report$err ;wait console
;
ROFSUB:
;report read/only file
lxi h,rofmsg ;drop through to wait for console
;
report$err:
;report error to console, message address in HL
push h ;stack msg address
;set D=console #
call rlr! lxi d,console! dad d! mov d,m
call xcrlf ;new line
LDA SELDSK! adi 'A'! sta dskerr ;current disk name
lxi b,dskmsg! call xprint ;the error message
pop b! call xprint ;error mssage tail
lda fx! mvi b,30h
lxi h,pr$fx1
cpi 100! jc rpt$err1
mvi m,31h! inx h! sui 100
rpt$err1:
sui 10! jc rpt$err2
inr b! jmp rpt$err1
rpt$err2:
mov m,b! inx h! adi 3ah! mov m,a
inx h! mvi m,20h
lxi h,pr$fcb! mvi m,0
lda resel! ora a! jz rpt$err3
mvi m,20h! push d
lhld info! inx h! xchg! lxi h,pr$fcb1
mvi c,8! call move! mvi m,'.'! inx h
mvi c,3! call move! pop d
rpt$err3:
call xcrlf
lxi b,pr$fx! call xprint
CALL GET$MEM$SEG
ORA A! JZ RTN$PHY$ERRS
INR A! JZ RTN$PHY$ERRS
LXI D,PNAME+5! CALL TEST$ERROR$MODE1! JNZ RTN$PHY$ERRS
jmp reboot ;terminate process
;ret
xerr$list:
dw xe3,xe4,xe5,xe6,xe7,xe8,xe9,xe10,xe11
xe3: db 'File Opened in Read/Only Mode',0
xe4: db 0
xe5: db 'File Currently Open',0
xe6: db 'Close Checksum Error',0
xe7: db 'Password Error',0
xe8: db 'File Already Exists',0
xe9: db 'Illegal ? in FCB',0
xe10: db 'Open File Limit Exceeded',0
xe11: db 'No Room in System Lock List',0
pr$fx: db 'Bdos Function: '
pr$fx1: db ' '
pr$fcb: db ' File: '
pr$fcb1:ds 12
db 0
fx: ds 1


View File

@@ -0,0 +1,181 @@
title 'MP/M II V2.0 Banked XDOS '
name 'bnkxdos'
cseg
;do;
;/*
; Copyright (C) 1979, 1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
; declare sysdatadr address;
sysdatadr:
dw $-$
; declare cmnbufferadr address;
cmnbufferadr:
dw $-$
; declare Proc$Address$Table (20) address data (
; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
ProcAddressTable:
dw parse,patch,0,0,0
dw 0,0,0,0,0
dw 0,0,0,0,0
dw 0,0,0,0,0
;
; /* Banked XDOS Procedures */
;
parse: ; BC->.(.filename,.fcb)
;
; filename = [d:]file[.type][;password]
;
; fcb assignments
;
; 0 => drive, 0 = default, 1 = A, 2 = B, ...
; 1-8 => file, converted to upper case,
; padded with blanks
; 9-11 => type, converted to upper case,
; padded with blanks
; 12-15 => set to zero
; 16-23 => password, converted to upper case,
; padded with blanks
; 24-25 => address of password field in 'filename',
; set to zero if password length = 0
; 26 => length of password (0 - 8)
;
; Upon return, HL is set to FFFFH if BC locates
; an invalid file name;
; otherwise, HL is set to 0000H if the delimiter
; following the file name is a 00H (NULL)
; or a 0DH (CR);
; otherwise, HL is set to the address of the delimiter
; following the file name.
;
lxi h,0! push h! push h! push h
mov h,b! mov l,c
mov e,m! inx h! mov d,m! inx h
mov a,m! inx h! mov h,m! mov l,a
call deblank
call delim! jnz parse1
mov a,c! ora a! jnz parse9
mov m,a! jmp parse3
parse1:
mov b,a! inx d! ldax d! cpi ':'! jnz parse2
mov a,b! sui 'A'! jc parse9
cpi 16! jnc parse9
inr a! mov m,a! inx d! call delim! jnz parse3
cpi '.'! jz parse9
cpi ':'! jz parse9
cpi ';'! jz parse9
jmp parse3
parse2:
dcx d! mvi m,0
parse3:
mvi b,8! call setfld
mvi b,3! cpi '.'! jz parse4
call padfld! jmp parse5
parse4:
inx d! call setfld
parse5:
mvi b,4
parse6:
inx h! mvi m,0! dcr b! jnz parse6
mvi b,8! cpi ';'! jz parse7
call padfld! jmp parse8
parse7:
inx d! call pw$fld
parse8:
push d! call deblank! call delim! jnz parse81
inx sp! inx sp! jmp parse82
parse81:
pop d
parse82:
mov a,c! ora a
pop b! mov a,c! pop b
inx h! mov m,c! inx h! mov m,b! inx h! mov m,a
pop b! xchg! rnz
lxi h,0! ret
parse9:
pop h! pop h! lxi h,0ffffh! pop b
pop b! mov a,b! ora c! rz
push b! ret
setfld:
call delim! jz padfld
inx h! cpi '*'! jnz setfld1
mvi m,'?'! dcr b! jnz setfld! jmp setfld2
setfld1:
mov m,a! dcr b
setfld2:
inx d! jnz setfld
setfld3:
call delim! rz
pop h! jmp parse9
pw$fld:
call delim! jz padfld
inx sp! inx sp! inx sp
inx sp! inx sp! inx sp
push d! push h! mvi l,0! xthl
dcx sp! dcx sp
pw$fld1:
inx sp! inx sp! xthl! inr l! xthl! dcx sp! dcx sp
inx h! mov m,a! inx d! dcr b! jz setfld3
call delim! jnz pw$fld1
;jmp padfld
padfld:
inx h! mvi m,' '! dcr b! jnz padfld
ret
delim:
ldax d! mov c,a! ora a! rz
mvi c,0! cpi 0dh! rz! mov c,a
cpi 09h! rz
cpi ' '! jc delim2! rz
cpi '.'! rz
cpi ':'! rz
cpi ';'! rz
cpi '='! rz
cpi ','! rz
cpi '/'! rz
cpi '['! rz
cpi ']'! rz
cpi '<'! rz
cpi '>'! rz
cpi 'a'! rc
cpi 'z'+1! jnc delim1
ani 05fh
delim1:
ani 07fh! ret
delim2:
pop h! jmp parse9
deblank:
ldax d! cpi ' '! jz deblank1
cpi 09h! jz deblank1
ret
deblank1:
inx d! jmp deblank
Patch:
dw 0,0,0,0,0,0,0,0 ;0000-000fh
dw 0,0,0,0,0,0,0,0 ;0010-001fh
dw 0,0,0,0,0,0,0,0 ;0020-002fh
dw 0,0,0,0,0,0,0,0 ;0030-003fh
dw 0,0,0,0,0,0,0,0 ;0040-004fh
dw 0,0,0,0,0,0,0,0 ;0050-005fh
dw 0,0,0,0,0,0,0,0 ;0060-006fh
;end bnkxdos;
END


View File

@@ -0,0 +1,356 @@
title 'MP/M II V2.0 CLBDOS Procedures'
name 'clbdos'
dseg
@@clbdos:
public @@clbdos
cseg
@clbdos:
public @clbdos
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
; open:
open:
; procedure (fcb$adr) byte reentrant public;
public open
; declare fcb$adr address;
; declare fcb based fcb$adr fcb$descriptor;
;
mov d,b
mov e,c
mvi c,15
jmp mon2
; return mon2 (15,fcb$adr);
; end open;
;
; close:
close:
; procedure (fcb$adr) reentrant public;
public close
; declare fcb$adr address;
; declare ret byte;
;
mov d,b
mov e,c
mvi c,16
jmp mon2
; ret = mon2 (16,fcb$adr);
; end close;
;
; readbf:
readbf:
; procedure (fcb$adr) byte reentrant public;
public readbf
; declare fcb$adr address;
;
mov d,b
mov e,c
mvi c,20
jmp mon2
; return mon2 (20,fcb$adr);
; end readbf;
;
; init:
init:
; procedure reentrant public;
public init
;
mvi c,13
jmp mon1
; call mon1 (13,0);
; end init;
;
; set$dma:
setdma:
; procedure (dma$adr) public;
public setdma
; declare dma$adr address;
;
mov d,b
mov e,c
mvi c,26
jmp mon1
; call mon1 (26,dma$adr);
; end set$dma;
;
; flshbf:
flshbf:
; procedure public;
public flshbf
;
mvi c,48
jmp mon1
; call mon1 (48,0);
; end flshbf;
;
; lo:
lo:
; procedure (char) reentrant public;
public lo
; declare char byte;
;
mov e,c
mvi c,5
jmp mon1
; call mon1 (5,char);
; end lo;
;
; co:
co:
; procedure (char) reentrant public;
public co
; declare char byte;
;
mov e,c
mvi c,2
jmp mon1
; call mon1 (2,char);
; end co;
;
; ci:
ci:
; procedure byte reentrant public;
public ci
;
mvi c,1
jmp mon2
; return mon2 (1,0);
; end ci;
;
; rawci:
rawci:
; procedure byte reentrant public;
public rawci
;
mvi c,6
mvi e,0ffh
jmp mon2
; return mon2 (6,0ffh);
; end rawci;
;
; rawlst:
rawlst:
; procedure (string$address) reentrant public;
; declare string$address address;
; declare char based string$address byte;
public rawlst
;
; do while char <> '$';
ldax b
cpi '$'
rz
push b
mvi c,6
mov e,a
call mon1
; call mon1 (6,char);
pop b
inx b
jmp rawlst
; end;
; end rawlst;
;
; print$buffer:
printb:
; procedure (bufferadr) reentrant public;
public printb
; declare bufferadr address;
;
mov d,b
mov e,c
mvi c,9
jmp mon1
; call mon1 (9,bufferadr);
; end print$buffer;
;
; read$buffer:
readbu:
; procedure (bufferadr) reentrant public;
public readbu
; declare bufferadr address;
;
mov d,b
mov e,c
mvi c,10
jmp mon1
; call mon1 (10,bufferadr);
; end read$buffer;
;
; crlf:
crlf:
; procedure reentrant public;
public crlf
;
; call co (0DH);
mvi c,0dh
call co
; call co (0AH);
mvi c,0ah
jmp co
; end crlf;
;
terminate equ 143
public endp
endp:
push psw
push b
push d
push h
mvi c,terminate ;143
lxi d,0
call xbdos
pop h
pop d
pop b
pop psw
ret
public exitr
extrn indisp
exitr:
lda indisp
ora a
jz exitregion ;exit region only if not in dispatcher
ret
xiosoffset equ 33h
public xiosms
xiosms:
jmp $-$
public xiospl
xiospl:
jmp $-$
public strclk
strclk:
jmp $-$
public stpclk
stpclk:
jmp $-$
; public exitr
exitregion:
jmp $-$
public maxcns
maxcns:
jmp $-$
; public sysinit
;sysinit:
jmp $-$
public xidle
xidle:
jmp $-$
extrn sysdat,datapg
public syinit
syinit:
mvi l,252
lxi d,datapg
mov m,e
inx h
mov m,d ; datapg[252] = system data pg adr
lxi h,mpmtop
mvi l,-6
lxi d,xjmptbl
mvi b,6
moveloop:
ldax d
mov m,a
inx d
inx h
dcr b
jnz moveloop
inx h
mov e,m
inx h
mov d,m
xchg
shld xbdosadr
xchg
inx h
inx h
mov e,m
inx h
mov d,m
inx h
push h
lxi h,xiosoffset
dad d
; copy XIOS jump table
mvi b,24 ; 8 entries * 3 bytes
lxi d,xiosms
mvxiostbl:
mov a,m
stax d
inx h
inx d
dcr b
jnz mvxiostbl
extrn dspsvz80,dsprsz80
lxi h,-3
dad d
mvi a,0c3h
cmp m ;is XIOS idle routine present?
jz idleok
mov m,a
lxi d,pdisp
inx h
mov m,e
inx h
mov m,d
idleok:
lhld sysdat
mvi l,5
mov a,m
ora a
jz notz80 ;test z80 flag in sys dat page
xra a
sta dspsvz80
lxi h,0
shld dspsvz80+1
sta dsprsz80
shld dsprsz80+1
notz80:
lhld sysdat ;passed parameter, HL = sysdat
ret
public nfxdos
nfxdos:
extrn xdos,pdisp
xjmptbl:
jmp xdos
jmp pdisp
public xbdos
xbdos:
public mon1,mon2
mon1:
mon2:
lhld xbdosadr
pchl
dseg
xbdosadr:
ds 2
ds 3 ; make room for BDOS external jump table
ds 3
mpmtop:
db 0 ; force byte at end of mpm nucleus module
end


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
title 'MP/M II V2.0 Clock Process'
name 'clock'
dseg
@@clock:
public @@clock
cseg
;clock:
@clock:
public @clock
;do;
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
;$include (common.lit)
;$nolist
;$include (proces.lit)
;$nolist
;$include (xdos.lit)
;$nolist
;$include (xdos.ext)
;$nolist
;$include (datapg.ext)
;$nolist
; xdos:
extrn xdos
; procedure (func,info) address external;
; declare func byte;
; declare info address;
; end xdos;
; declare tod structure (
extrn tod
; day address,
; hr byte,
; min byte,
; sec byte ) external;
dseg
;/*
; Clock Process Data Segment
;*/
; declare clock$pd process$descriptor public
; initial (0,rtr$status,20,.tick$entrypt,
; 'Clock ',0,0ffh,0);
clockpd:
public clockpd
extrn clipd
dw clipd ; pl
db 0 ; status
db 20 ; priority
dw clockentrypt ; stkptr
db 'Clock ' ; name
db $-$ ; console
db 0ffh ; memseg (system)
dw $-$ ; b
dw $-$ ; thread
dw $-$ ; disk set DMA
db $-$ ; disk select / user code
dw $-$ ; dcnt
db $-$ ; searchl
dw $-$ ; searcha
ds 2 ; drvact
ds 20 ; registers
ds 2 ; scratch
; declare clock$stk (10) address
; initial (restarts,.clock);
clockstk:
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h
clockentrypt:
dw clock
cseg
;/*
; clock:
; The purpose of the clock process is to maintain a time
; of day clock. It utilizes the XDOS delay function to
; increment the PUBLIC clock every one second.
;*/
; clock:
clock:
; procedure;
; declare ret byte;
; do forever;
@4:
; ret = xdos (flag$wait,2);
MVI E,2H
MVI C,84H
CALL XDOS
; if (tod.sec := dec (tod.sec + 1)) = 60h then
LXI H,TOD+4H
MOV A,M
INR A
DAA
MOV M,A
SUI 60H
JNZ @4
; do;
; tod.sec = 0;
MOV M,A
; ret = xdos (flag$set,3);
MVI E,3H
MVI C,85H
CALL XDOS
; if (tod.min := dec (tod.min + 1)) = 60h then
LXI H,TOD+3H
MOV A,M
INR A
DAA
MOV M,A
SUI 60H
JNZ @4
; do;
; tod.min = 0;
MOV M,A
; if (tod.hr := dec (tod.hr + 1)) = 24h then
DCX H
MOV A,M
INR A
DAA
MOV M,A
SUI 24H
JNZ @4
; do;
; tod.hr = 0;
MOV M,A
; tod.day = tod.day + 1;
LHLD TOD
INX H
SHLD TOD
; end;
; end;
; end;
; end;
JMP @4
; end clock;
;end clock;
END


View File

@@ -0,0 +1,674 @@
;***************************************************************
;***************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** C o n s o l e P o r t i o n **
;** **
;***************************************************************
;***************************************************************
cnsfunc:
mov a,c! mov c,e! mov b,d
lxi h,functab! mov e,a! mvi d,0 ;DE=func, HL=.functab
dad d! dad d! mov e,m! inx h! mov d,m ;DE=functab(func)
xchg! pchl ;dispatched
;
; dispatch table for functions
functab:
dw bootf,func1,func2,func3
dw func4,func5,func6,func7
dw cmnret,func9,func10,func11
diskf equ ($-functab)/2
nfuncs equ 41 ;must match with banked bdos # fns
;
func1:
;return console character with echo
call conech
mov l,a! ret
;
func2:
;write console character with tab expansion
call attcns! jmp tabout
;
func3:
;return raw unattached console character
call rawattcns
jmp dirinp
;
func4:
;write raw unattached console character
call rawattcns
jmp conoutf
;
func5:
;write list character
call testlstatt
;write to list device if already attached
jz listf
;else must attach list device first
push b! push d
mvi c,attlst! call xdos
pop d! pop b
jmp listf
;
func6:
;direct console i/o - 0ffh = read/status
; 0feh = status
; 0fdh = read
call rawattcns
mov a,c! inr a! jz stsdirinp
inr a! jz stsinp
inr a! jz dirinp
;direct output function
jmp conoutf
stsdirinp:
push d! call constf! pop d
ora a! jnz dirinp
mvi c,dispatch! call xdos
xra a! mov l,a! ret
stsinp:
;direct console status input
call constf ;to A
mov l,a! ret
dirinp:
lxi h,kbchar! call ofsthl
mov a,m! mvi m,0! ora a
cz coninf ;to A
mov l,a! ret
;
func7:
;return io byte
;*** Not implemented in MP/M ***
xra a
mov l,a! ret
;
;func8:
;set i/o byte
;*** Not implemented in MP/M ***
;ret
;
func9:
;write line until $ encountered
;BC = string address
call attcns! jmp print ;out to console
;
func10:
;read a buffered console line
call attcns! jmp read
;
func11:
;check console status
call testcnsatt
jz doconbrk
mvi c,dispatch! call xdos
xra a! mov l,a! ret
doconbrk:
call conbrk
mov l,a
;
cmnret:
ret
;
tstlivekbd:
;test for simulated 'live keyboard'
;pd.name(3)' = off
call rlr! lxi b,pname+3! dad b! mov a,m! ani 80h
ret
;
testlstatt:
;test to determine if list is attached
;Zero = attached, D = List #
di
call rlr! xchg ;DE = Ready List Root
lxi h,console! dad d! mov a,m! ani 0f0h
rrc! rrc! rrc! rrc! push psw! push b
lxi b,lstatt-rlros! jmp attcmn
;ret
;
testcnsatt:
;test to determine if console is attached
;Zero = attached, D = Console #
di
call rlr! xchg ;DE = Ready List Root
lxi h,console! dad d! mov a,m! ani 0fh
push psw! push b
lxi b,cnsatt-rlros
attcmn:
lhld rlradr! dad b
add a! mov c,a! mvi b,0! dad b
mov a,m! cmp e! inx h! jnz notatt
mov a,m! cmp d! jz testext
notatt:
mov a,m! dcx h! ora m! jnz testext
mov m,e! inx h! mov m,d! xra a ;attach ok
testext:
ei! pop b! pop d
mvi e,0 ;cns req'd flag false
ret
;
rawattcns:
push b! mvi b,80h! jmp attcns0
attcns:
push b! mvi b,0
attcns0:
call rlr
inx h! inx h! inx h! inx h! inx h! inx h
mov a,m! ani 7fh! ora b! mov m,a ;set/reset direct i/o
inx h! inx h! inx h
mov a,m! ani 7fh! ora b! mov m,a ;set/reset simul. live kbd
pop b
;attach console if req'd
call testcnsatt
mvi e,0ffh! rz ;cns req'd flag true
push b! push d!
mvi c,attach! call xdos
pop d! push d ;restore DE
call dsplyatchmsg
pop d! pop b
ret
;
ofsthl:
;offset HL by console # (in D)
push psw
mov a,d! add l! mov l,a
mvi a,0! adc h! mov h,a
pop psw
ret
;
; console handlers
constx:
push d! call constf! pop d! ret
coninx:
;returns char & cond code = NZ if raw input
push d! call rlr! lxi d,pname! dad d
pop d! push d! ;restore console #
mov a,m! ani 80h! push psw
call coninf
mov b,a! pop psw! mov a,b
pop d! ret
conoutx:
mov a,c! ani 7fh! mov c,a
push d! call conoutf! pop d! ret
conin:
;read console character to A
;attach console first
call attcns
lxi h,kbchar! call ofsthl
mov a,m! mvi m,0! ora a! rnz
;no previous keyboard character ready
call getchr ;get character externally and test it
jmp conin ;only exit is with kbchar <> 0
;ret
;
conech:
;read character with echo
call conin! call echoc! rc ;echo character?
;character must be echoed before return
push psw! mov c,a! call tabout! pop psw
ret ;with character in A
;
echoc:
;echo character if graphic
;cr, lf, tab, or backspace
cpi cr! rz ;carriage return?
cpi lf! rz ;line feed?
cpi tab! rz ;tab?
cpi ctlh! rz ;backspace?
cpi ' '! ret ;carry set if not graphic
;
conbrk: ;check for character ready
call constx! ani 1
lxi h,kbchar! call ofsthl
jnz pgetchr ;jump if char to be read in
mov a,m! ora a! rz ;return if no char in kbchar either
jmp conb1 ;active kbchar
pgetchr:
mvi m,0 ;clear kbchar to prepare for new char
;character ready, read it
getchr: ;entry point used by conin
call coninx ;to A
jnz conb0; skip char testing if pd.pname.f0 is "on"
cpi ctls! jnz notcts ;check stop screen function
;found ctls, read next character
getctlq:
call coninx ;to A
cpi ctlc! jz controlc ;ctlc implies re-boot
cpi ctlq! jz gotctlq
mvi c,7! call conoutx ;send bell character
jmp getctlq
gotctlq:
;resume after ^Q
xra a! ret ;with zero in accumulator
notcts:
;not a control s, control q?
cpi ctlq! jz gotctlq
;ignore control Q's
notctq:
;not a control s, control d?
cpi ctld! jnz notctd
;found ctld, detach console
;^D is ignored if submit in progress
lhld sysdat! mvi l,128! call ofsthl
mov a,m! ora a! mvi a,0! rnz
push d! lxi h,listcp! call ofsthl
;if ^D and ^P then detach list
mov a,m! ora a! jz notctlp
mvi c,detlst! call XDOS
notctlp:
mvi c,detach! call XDOS
;then attach console back
; unless cns not req'd
pop d! mov a,e! ora a
rz! push d ;return if cns not req'd
mvi c,attach! call XDOS! pop d
dsplyatchmsg:
;print console attach message
lxi b,atchmsg! call xprint
call rlr
dsplynm:
call pdsplynm
xcrlf:
;output crlf without CONBRK calls
mvi c,cr! call conoutx
mvi c,lf! call conoutx
xra a! ret ;with zero in A
pdsplynm:
lxi b,pname! dad b! mvi e,8
dsploop:
mov c,m! push h! push d! call conoutx
pop d! pop h! inx h! dcr e
jnz dsploop
inr e ;cns req'd set true
ret
notctd:
;not a control d, control c?
cpi ctlc! jnz conb0
controlc: ;entry point
lhld sysdat! mvi l,128! call ofsthl
mov a,m! ora a! jz ctlcnt
push h! lxi b,submsg! call query
pop h! jnz ctlcnt
mvi m,0
ctlcnt:
;test for suppress abort flag
call rlr! lxi b,(pname+7)! dad b
mov a,m! ani 80h! jz notctlcsupr
dcx h! mov a,m! ori 80h! mov m,a
xra a! ret
notctlcsupr:
;test to see if this is a user process
inx h! inx h
mov a,m! ora a! rz
inr a! rz ;ignore ^C if system process running
;print Abort (Y/N) ?
lxi b,abtmsg1! call xprint
call rlr! call pdsplynm
lxi b,abtmsg2! call query! jz xreboot
xra a! ret ;with zero in A
conb0:
;character in accum, save it
lxi h,kbchar! call ofsthl! mov m,a
conb1:
;return with true set in accumulator
mvi a,1! ret
;
query:
call xprint
eatctlc:
call coninx! ani 7fh
cpi ctlc! jz eatctlc! push psw
mov c,a! call conoutx
mvi c,cr! call conoutx
mvi c,lf! call conoutx
pop psw
ani 5fh! cpi 'Y'
ret
;
conout:
;compute character position/write console char from C
;compcol = true if computing column position
lxi h,compcol! call ofsthl
mov a,m! ora a! jnz compout
;write the character, then compute the column
;write console character from C
push b! call conoutx ;externally, to console
call tstlivekbd ;conbrk only if simulated 'live kbd'
cz conbrk ;check for screen stop function
pop b! push b! push d ;recall/save character & con #
;may be copying to the list device
lxi h,listcp! call ofsthl
mov a,m! ani 01h! cnz func5 ;to printer, if so
pop d! pop b ;recall the character & con #
compout:
mov a,c ;recall the character
;and compute column position
lxi h,column! call ofsthl ;A = char, HL = .column
cpi rubout! rz ;no column change if nulls
inr m ;column = column + 1
cpi ' '! rnc ;return if graphic
;not graphic, reset column position
dcr m ;column = column - 1
mov a,m! ora a! rz ;return if at zero
;not at zero, may be backspace or end line
mov a,c ;character back to A
cpi ctlh! jnz notbacksp
;backspace character
dcr m ;column = column - 1
ret
notbacksp:
;not a backspace character, eol?
cpi lf! rnz ;return if not
;end of line, column = 0
mvi m,0 ;column = 0
ret
;
ctlout:
;send C character with possible preceding up-arrow
mov a,c! call echoc ;cy if not graphic (or special case)
jnc tabout ;skip if graphic, tab, cr, lf, or ctlh
;send preceding up arrow
push psw! mvi c,ctl! call conout ;up arrow
pop psw! ori 40h ;becomes graphic letter
mov c,a ;ready to print
;(drop through to tabout)
;
tabout:
;expand tabs to console
mov a,c! cpi tab! jnz conout ;direct to conout if not
;tab encountered, move to next tab position
tab0:
mvi c,' '! call conout ;another blank
call ldacolumn! ani 111b ;column mod 8 = 0 ?
jnz tab0 ;back for another if not
ret
;
backup:
;back-up one screen position
call pctlh! mvi c,' '! call conoutx ;jmp pctlh
;
pctlh:
;send ctlh to console without affecting column count
mvi c,ctlh! jmp conoutx
;ret
;
crlfp:
;print #, cr, lf for ctlx, ctlu, ctlr functions
;then move to strtcol (starting column)
mvi c,'#'! call conout
call crlf
;column = 0, move to position strtcol
crlfp0:
call ldacolumn! lxi h,strtcol! call ofsthl
cmp m! rnc ;stop when column reaches strtcol
mvi c,' '! call conout ;print blank
jmp crlfp0
;;
;
crlf:
;carriage return line feed sequence
mvi c,cr! call conout! mvi c,lf! jmp conout
;ret
;
xprint:
;print routine which does not CONBRK
;BC = string address, string terminated with a '$'
ldax b! ORA A! rz
push b! mov c,a! call conoutx! pop b
inx b! jmp xprint
;
print:
;print message until M(BC) = '$'
ldax b! cpi '$'! rz ;stop on $
;more to print
inx b! push b! mov c,a ;char to C
call tabout ;another character printed
pop b! jmp print
;
pread: ;entry to read, restores buffer address
pop b
read: ;BC = address (max length, current length, buffer)
push b ;save buffer address for possible ^X or ^U
call ldacolumn
lxi h,strtcol! call ofsthl
mov m,a ;save start for ctl-x, ctl-h
mov h,b! mov l,c! mov c,m! inx h! push h! mvi b,0
;B = current buffer length,
;C = maximum buffer length,
;HL= next to fill - 1
readnx:
;read next character, BC, HL active
push b! push h ;blen, cmax, HL saved
readn0:
call conin ;next char in A
ani 7fh ;mask parity bit
pop h! pop b ;reactivate counters
cpi cr! jz readen ;end of line?
cpi lf! jz readen ;also end of line
cpi ctlh! jnz noth ;backspace?
;do we have any characters to back over?
mov a,b! ora a! jz readnx
;characters remain in buffer, backup one
dcr b ;remove one character
call ldacolumn
lxi h,compcol! call ofsthl
mov m,a ;col > 0
;compcol > 0 marks repeat as length compute
jmp linelen ;uses same code as repeat
noth:
;not a backspace
cpi rubout! jnz notrub ;rubout char?
;rubout encountered, rubout if possible
mov a,b! ora a! jz readnx ;skip if len=0
;buffer has characters, resend last char
mov a,m! dcr b! dcx h ;A = last char
;blen=blen-1, next to fill - 1 decremented
jmp rdech1 ;act like this is an echo
;
notrub:
;not a rubout character, check end line
cpi ctle! jnz note ;physical end line?
;yes, save active counters and force eol
push b! push h! call crlf
lxi h,strtcol! call ofsthl
xra a! mov m,a ;start position = 00
jmp readn0 ;for another character
note:
;not end of line, list toggle?
cpi ctlp! jnz notp ;skip if not ctlp
lda kbproc! ora a! jnz notp
;list toggle - change parity
push h ;save next to fill - 1
push b! push d
lxi h,listcp! call ofsthl ;HL=.listcp flag
mvi a,01h! xra m! mov m,a ;listcp=-listcp
push h ;save address of listcp
jnz prntron ; jump if printer to be turned on
prntroff:
;return list mutex queue message
mvi m,0! ;zero listcp(console)
mvi c,detlst! call XDOS
pop h! jmp ctlpxit
prntron:
call testlstatt
pop h! jz ctlpxit
;printer busy, could not ^p
mvi m,0! lxi b,pbsymsg
;D = console #
pop d! push d
call xprint
ctlpxit:
pop d! pop b
pop h! jmp readnx ;for another char
notp:
;not a ctlp, line delete?
cpi ctlx! jnz notx
pop h ;discard start position
;loop while column > strtcol
backx:
lxi h,strtcol! call ofsthl
mov a,m! lxi h,column! call ofsthl
cmp m! jnc pread ;start again
dcr m ;column = column - 1
call backup ;one position
jmp backx
notx:
;not a control x, control u?
cpi ctlu! jnz notu ;skip if not
;delete line (ctlu)
call crlfp ;physical eol
pop h ;discard starting position
jmp pread ;to start all over
notu:
;not line delete, repeat line?
cpi ctlr! jnz notr
linelen:
;repeat line, or compute line len (ctlh)
;if compcol > 0
push b! call crlfp ;save line length
pop b! pop h! push h! push b
;bcur, cmax active, beginning buff at HL
rep0:
mov a,b! ora a! jz rep1 ;count len to 00
inx h! mov c,m ;next to print
dcr b! push b! push h ;count length down
call ctlout ;character echoed
pop h! pop b ;recall remaining count
jmp rep0 ;for the next character
rep1:
;end of repeat, recall lengths
;original BC still remains pushed
push h ;save next to fill
lxi h,compcol! call ofsthl
mov a,m! ora a ;>0 if computing length
jz readn0 ;for another char if so
;column position computed for ctlh
lxi h,column! call ofsthl! sub m ;diff > 0
lxi h,compcol! call ofsthl
mov m,a ;count down below
;move back compcol-column spaces
backsp:
;move back one more space
call backup ;one space
lxi h,compcol! call ofsthl! dcr m
jnz backsp
jmp readn0 ;for next character
notr:
;not a ctlr, place into buffer
rdecho:
inx h! mov m,a ;character filled to mem
inr b ;blen = blen + 1
rdech1:
;look for a random control character
push b! push h ;active values saved
mov c,a ;ready to print
call ctlout ;may be up-arrow C
pop h! pop b! mov a,b ;len to A
;are we at end of buffer?
cmp c! jc readnx ;go for another if not
readen:
;end of read operation, store blen
pop h! mov m,b ;M(current len) = B
pop h ;discard buffer address
mvi c,cr! jmp conout ;return carriage
;ret
;
ldacolumn:
lxi h,column! call ofsthl! mov a,m! ret
pbsymsg:
db cr,lf,'Printer Busy.',cr,lf,0
abtmsg1:
db cr,lf,'Abort ',0
abtmsg2:
db ' (Y/N) ?',0
atchmsg:
db cr,lf,'Attach:',0
submsg:
db cr,lf,'Terminate Submit ?',0
;
; data areas
;
nmbcns equ 16
compcol:db 0 ;true if computing column position
rept nmbcns-1
db 0
endm
strtcol:db 0 ;starting column position after read
rept nmbcns-1
db 0
endm
column: db 0 ;column position
rept nmbcns-1
db 0
endm
kbchar: db 0 ;initial key char = 00
rept nmbcns-1
db 0
endm
listcp: db 0 ;listing toggle
rept nmbcns-1
db 0
endm
kbproc: db 0 ;kb proc resident flag
;
patch$size equ 80
ds patch$size
patch:
org (((patch-base)+255) AND 0ff00h)-patch$size
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
; bios external jump table
;
bios equ $ ;base of the bios jump table
bootf equ bios ;cold boot function
wbootf equ bootf+3 ;warm boot function
constf equ wbootf+3 ;console status function
coninf equ constf+3 ;console input function
conoutf equ coninf+3 ;console output function
listf equ conoutf+3 ;list output function
punchf equ listf+3 ;punch output function
readerf equ punchf+3 ;reader input function
homef equ readerf+3 ;disk home function
seldskf equ homef+3 ;select disk function
settrkf equ seldskf+3 ;set track function
setsecf equ settrkf+3 ;set sector function
setdmaf equ setsecf+3 ;set dma function
readf equ setdmaf+3 ;read disk function
writef equ readf+3 ;write disk function
liststf equ writef+3 ;list status function
sectran equ liststf+3 ;sector translate
;
; xios access table
xiosms equ sectran+3 ;memory select / protect
xiospl equ xiosms+3 ;device poll
strclk equ xiospl+3 ;start clock
stpclk equ strclk+3 ;stop clock
exitr equ stpclk+3 ;exit critical region
maxcns equ exitr+3 ;max console #
syinitf equ maxcns+3 ;MP/M system initialization
;
end


Some files were not shown because too many files have changed in this diff Show More