mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 01:14:21 +00:00
251 lines
6.5 KiB
Plaintext
251 lines
6.5 KiB
Plaintext
title 'Concurrent CP/M Loader Program'
|
||
;*******************************************************
|
||
;
|
||
; The Loader Program opens the file 'CCPM.SYS'
|
||
; using the LBDOS and LBIOS and then reads it into
|
||
; memory. The DS register is set to the start of
|
||
; the Concurrent CP/M DATA area, and a JMPF to the first
|
||
; byte of the Concurrent CP/M code is executed.
|
||
;
|
||
; The first 128 byte record of the CCPM.SYS file is
|
||
; a header with the following format:
|
||
;
|
||
; +----+----+----+----+----+----+----+----+----+
|
||
; |TYPE| LEN | ABS | MIN | MAX |
|
||
; +----+----+----+----+----+----+----+----+----+
|
||
;
|
||
; type rb 1 ;seg type
|
||
; len rw 1 ;length
|
||
; abs dw 1 ;absolute segment address for LOADER
|
||
; min rw 1 ;minimum mem
|
||
; max rw 1 ;max mem needed
|
||
;
|
||
; The code is expected first and then the data
|
||
; within the CCPM.SYS File. This header record
|
||
; is constructed automatically by the system
|
||
; generation utility GENCCPM. See the variables
|
||
; declared at 'SEC1:' where the first sector of
|
||
; the CCPM.SYS will be read.
|
||
;
|
||
; The following commands are used to generate CPMLDR.SYS
|
||
; RASM86 LBIOS
|
||
; RASM86 LPROG
|
||
; LINK86 LBIOS3.SYS = LBIOS,LPROG [DATA[ORIGIN[0180]]]
|
||
; GENLDR [nnnn]
|
||
;
|
||
; The following commands are used to generate the
|
||
; boot tracks image BOOTTRKS
|
||
; SID86
|
||
; #RDSKBOOT.SYS ;strips header and
|
||
; #WBOOT,180,37F ;default base page
|
||
; PIP BOOTTRKS = BOOT[O],CPMLDR.SYS[O]
|
||
;
|
||
;*******************************************************
|
||
|
||
CR equ 13
|
||
LF equ 10
|
||
|
||
CTYPE equ byte ptr 00h
|
||
CLEN equ word ptr 01h
|
||
CLDSEG equ word ptr 03h
|
||
DTYPE equ byte ptr 09h
|
||
DLEN equ word ptr 0Ah
|
||
DLDSEG equ word ptr 0Ch
|
||
|
||
CODETYPE equ 1 ;code type CMD header
|
||
DATATYPE equ 2 ;data type CMD header
|
||
|
||
; bdos function numbers
|
||
|
||
DRV_SET equ 14
|
||
F_OPEN equ 15
|
||
F_READ equ 20
|
||
F_DMASET equ 26
|
||
F_USERNUM equ 32
|
||
F_MULTISEC equ 44
|
||
F_DMA equ 51
|
||
|
||
|
||
;*******************************************************
|
||
;
|
||
; LOADER starts here
|
||
;
|
||
;*******************************************************
|
||
|
||
CSEG
|
||
org 0000h
|
||
|
||
public ?start
|
||
extrn ?conout:near, ?pmsg:near
|
||
|
||
?start: ; loader entry from BDOS init
|
||
;------
|
||
mov si,offset signon ;print signon message
|
||
call ?pmsg
|
||
|
||
mov dl,0
|
||
mov cl,DRV_SET ! int 224 ;select boot drive
|
||
|
||
mov dl,0
|
||
mov cl,F_USERNUM ! int 224 ;set user number
|
||
|
||
mov dx,offset ccpm_fcb
|
||
mov cl,F_OPEN ! int 224 ;open CCPM.SYS file
|
||
cmp al,255 ! jne perr ;insure no error on open
|
||
mov si,offset nofile
|
||
error:
|
||
call ?pmsg ;print no SYSTEM file message
|
||
halt:
|
||
sti
|
||
hlt ;then halt the machine
|
||
jmps halt
|
||
perr:
|
||
mov dx,offset sec1
|
||
mov cl,F_DMASET ! int 224 ;set DMA offset address
|
||
|
||
mov dl,1 ;set Multi-sector count to 1
|
||
mov si,ds ;SI = DMA segment address
|
||
call read_rec ;read first record
|
||
|
||
mov bx,offset sec1
|
||
cmp CTYPE[bx],CODETYPE ;code type must = 1
|
||
je chk_data
|
||
badhdr:
|
||
mov si,offset hdrerr
|
||
jmp error
|
||
chk_data:
|
||
cmp DTYPE[bx],DATATYPE ;data type must = 2
|
||
jne badhdr
|
||
mov ax,CLDSEG[bx] ;code abs + code length
|
||
add ax,CLEN[bx] ;should be = to data abs
|
||
cmp ax,DLDSEG[bx] ! jne badhdr
|
||
add ax,DLEN[bx]
|
||
cmp ax,CLDSEG[bx] ;check for wrap around
|
||
jbe badhdr
|
||
mov ccpm_init,0000h ;set O.S. entry offset to 0000h
|
||
mov ax,CLDSEG[bx]
|
||
mov ccpm_init+2,ax ;set O.S. entry segment
|
||
hdrok:
|
||
mov si,offset csegmsg ;print out starting code and data
|
||
call ?pmsg ; on console
|
||
mov ax,word ptr sec1+CLDSEG
|
||
call phex ;print base code segment
|
||
mov si,offset dsegmsg
|
||
call ?pmsg ;print base data segment
|
||
mov ax,word ptr sec1+DLDSEG
|
||
call phex
|
||
|
||
mov dx,0
|
||
mov cl,F_DMASET ! int 224 ;set DMA offset to 0
|
||
;set multi_sector count to 127
|
||
mov dl,127 ;to align reads with physical sectors
|
||
mov si,word ptr sec1+CLDSEG ;initial DMA segment
|
||
call read_rec ;read next 127 sectors
|
||
jz done ;Z flag set -> EOF
|
||
add si,8*127 ;increment dma segment
|
||
mov dl,128 ;set multi-sector count to 128
|
||
call read_rec ;read next 128 sectors
|
||
jz done ;Z flag set -> EOF
|
||
readit1:
|
||
add si,8*128 ;increment dma segment
|
||
call read_data ;read next 128 sectors
|
||
jnz readit1 ;Z flag set -> EOF
|
||
done:
|
||
mov si,offset crlf ;print carriage return, line feed
|
||
call ?pmsg
|
||
|
||
mov ds,word ptr sec1+DLDSEG ;CCP/M data segment
|
||
|
||
jmpf cs:dword ptr ccpm_init ;leap to CCP/M initialization
|
||
|
||
;-------------------------------------------------------
|
||
; subroutines
|
||
;-------------------------------------------------------
|
||
read_rec:
|
||
;--------
|
||
; Entry: DL = multisector count
|
||
; SI = dma segment
|
||
|
||
mov cl,F_MULTISEC ! int 224 ;set multi-sector count to 128
|
||
|
||
read_data:
|
||
;---------
|
||
; Entry: SI = dma segment
|
||
; Exit: Z flag set if EOF
|
||
; Z flag reset if no error
|
||
|
||
mov dx,si
|
||
mov cl,F_DMA ! int 224 ;set DMA segment for disk IO
|
||
mov dx,offset ccpm_fcb
|
||
mov cl,F_READ ! int 224 ;next 128 sector read
|
||
cmp al,1! jnbe read_error
|
||
ret
|
||
read_error:
|
||
mov si,offset rerr ;print READ ERROR message
|
||
jmp error
|
||
|
||
phex: ;print 4 hex characters from ax
|
||
;----
|
||
; Entry: AX = hex value to print
|
||
|
||
mov cx,0404h ;4 in both CH and CL
|
||
lhex:
|
||
rol ax,cl ;rotate left 4
|
||
push cx ! push ax ;save crucial registers
|
||
call pnib ;print hex nibble
|
||
pop ax ! pop cx ;restore registers
|
||
dec ch ! jnz lhex ;and loop four times
|
||
ret
|
||
pnib: ;print low nibble in AL as hex char
|
||
;----
|
||
; Entry: AL = hex character to print
|
||
|
||
and al,0fh
|
||
cmp al,9 ! ja p10 ;above 9 ?
|
||
add al,'0' ;digit
|
||
jmps prn
|
||
p10:
|
||
add al,'A'-10 ;hex digit A-F
|
||
prn:
|
||
mov dl,al
|
||
|
||
putchar:
|
||
;-------
|
||
; Entry: DL = character to send to console
|
||
|
||
mov cl,dl
|
||
jmp ?conout
|
||
|
||
; code segment variable
|
||
|
||
ccpm_init rw 2 ;double word entry to Concurrent CP/M
|
||
|
||
;*******************************************************
|
||
;
|
||
; DATA AREA
|
||
;
|
||
;*******************************************************
|
||
DSEG
|
||
|
||
signon db 'Concurrent CP/M System Loader V1.0 (02/16/84)',0
|
||
nofile db CR,LF,'CCPM.SYS Not Found On Boot Disk',0
|
||
rerr db CR,LF,'Error Reading CCPM.SYS',0
|
||
hdrerr db CR,LF,'Bad Header Record in CCPM.SYS',0
|
||
csegmsg db CR,LF,'Code Paragraph Address = ',0
|
||
dsegmsg db CR,LF,'Data Paragraph Address = ',0
|
||
crlf db CR,LF,0
|
||
|
||
ccpm_fcb db 0,'CCPM ','SYS',0,0,0,0
|
||
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
|
||
db 0
|
||
|
||
;-------------------------------------------------------
|
||
|
||
sec1 rb 128 ;read first sector of CCPM.SYS
|
||
;here (header record)
|
||
|
||
;*******************************************************
|
||
|
||
END
|
||
|