mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
237 lines
6.8 KiB
NASM
237 lines
6.8 KiB
NASM
;---------------------------------------------------------------------
|
||
; LOADCPM.ASM (FOR CAL-PC MSDOS 2.11 - ASSEMBLE USING A86.COM)
|
||
; 28-10-88
|
||
; STEPHEN HUNT
|
||
;---------------------------------------------------------------------
|
||
; 28-12-89
|
||
; Modified to attempt to open the CPM.SYS file in the root directory
|
||
; if it could not be found in the current directory
|
||
;---------------------------------------------------------------------
|
||
;
|
||
cr equ 0dh ; carriage return
|
||
lf equ 0ah ; line feed
|
||
eof equ 01ah ; end of file marker
|
||
;
|
||
dos equ 21h
|
||
;
|
||
;---------------------------------------------------------------------
|
||
; jump to start of code
|
||
;---------------------------------------------------------------------
|
||
;
|
||
loadcpm:
|
||
;
|
||
jmp start
|
||
;
|
||
db 'LOADCPM version 1.1 Copyright (C) Stephen Hunt'
|
||
db eof
|
||
;
|
||
;---------------------------------------------------------------------
|
||
; tell 'em what were up to
|
||
;---------------------------------------------------------------------
|
||
;
|
||
start:
|
||
;
|
||
mov dx,offset loading
|
||
call print_string
|
||
;
|
||
;---------------------------------------------------------------------
|
||
; open the CPM.SYS file
|
||
;---------------------------------------------------------------------
|
||
;
|
||
mov dx,offset cpm_sys+1 ; assume 'CPM.SYS'
|
||
call open_cpm ; open file
|
||
jnc read_cpm_sys ; ok - continue
|
||
;
|
||
mov dx,offset cpm_sys ; assume '\CPM.SYS'
|
||
call open_cpm ; open file
|
||
jnc read_cpm_sys ; ok - continue
|
||
;
|
||
mov dx,offset err_open ; 'cannot find CPM.SYS'
|
||
jmp error_exit ; exit with error
|
||
;---------------------------------------------------------------------
|
||
; read the CPM.SYS file (upto 32k bytes, usually only 16k bytes)
|
||
;---------------------------------------------------------------------
|
||
;
|
||
read_cpm_sys:
|
||
;
|
||
mov bx,word ptr cpm_hnd
|
||
mov dx,offset cpm_buf
|
||
mov cx,32768
|
||
mov ah,03fh
|
||
int dos ; read 32768 bytes of CPM.SYS
|
||
;
|
||
mov word ptr cpm_siz,ax ; store number of bytes read
|
||
;
|
||
pushf ; save read error status
|
||
call closecpm ; close CPM.SYS file
|
||
popf ; restore read error status
|
||
;
|
||
jnc check_header ; continue if read successful
|
||
;
|
||
mov dx,offset err_read ; 'error reading CPM.SYS'
|
||
jmp error_exit ; exit with error
|
||
;---------------------------------------------------------------------
|
||
; check that the CPM.SYS header record is valid
|
||
;---------------------------------------------------------------------
|
||
;
|
||
check_header:
|
||
;
|
||
cmp word ptr cpm_siz,0 ; q. was anything read ?
|
||
jz check_header_err ; no - error
|
||
;
|
||
mov si,offset cpm_buf
|
||
cmp byte ptr 0[si],1 ; q. code segment group type present ?
|
||
jnz check_header_err ; no - error
|
||
;
|
||
mov ax,word ptr 1[si] ; get group length in paragraphs
|
||
mov dx,010h
|
||
mul dx ; convert to length in bytes
|
||
mov word ptr cpm_len,ax ; and store it
|
||
;
|
||
mov bx,word ptr cpm_siz
|
||
cmp bx,ax ; q. file size greater than code length ?
|
||
jb check_header_err ; no - error
|
||
;
|
||
sub bx,080h ; subtract length of header record
|
||
sub bx,ax ; then the code length
|
||
cmp bx,080h ; q. (file size less header) more than
|
||
; ; 128 bytes larger than code length ?
|
||
jae check_header_err ; yes - error
|
||
;
|
||
cmp word ptr 3[si],0 ; q. base segment defined ?
|
||
jz check_header_err ; no - error
|
||
;
|
||
mov ax,word ptr 1[si]
|
||
cmp ax,word ptr 5[si] ; q. code length equal minimum length ?
|
||
jnz check_header_err ; no - error
|
||
;
|
||
cmp word ptr 7[si],0 ; q. maximum length defined ?
|
||
jnz check_header_err ; yes - error
|
||
;
|
||
add si,9 ; point to next group descriptor
|
||
mov cx,128 -9
|
||
cld
|
||
;
|
||
check_header_loop:
|
||
;
|
||
cmp byte ptr 0[si],0 ; q. any more descriptors defined ?
|
||
jnz check_header_err ; yes - error
|
||
loop check_header_loop ; loop until finished
|
||
;
|
||
jmp reset_int3 ; reset int 3 vector
|
||
;
|
||
check_header_err:
|
||
;
|
||
mov dx,offset err_head ; 'invalid CPM.SYS header'
|
||
jmp error_exit ; exit with error
|
||
;---------------------------------------------------------------------
|
||
; reset interrupt 3 to use the prom interrupt 3 routine (FC00:32BE).
|
||
;---------------------------------------------------------------------
|
||
;
|
||
reset_int3:
|
||
;
|
||
push ds
|
||
mov dx,0fc00h ; segment FC00h
|
||
mov ds,dx
|
||
mov dx,032beh ; offset 32BEh
|
||
mov al,3
|
||
mov ah,025h
|
||
int dos ; reset int 3
|
||
pop ds
|
||
|
||
;---------------------------------------------------------------------
|
||
; relocate cpm image, set segment registers and jump to it.
|
||
;---------------------------------------------------------------------
|
||
;
|
||
move_cpm:
|
||
;
|
||
mov ax,word ptr cpm_buf +3
|
||
mov es,ax ; es points to cpm segment
|
||
;
|
||
mov si,offset cpm_buf +080h
|
||
xor di,di ; set source + destination pointers
|
||
;
|
||
mov cx,word ptr cpm_len ; set length of code to move
|
||
;
|
||
cld ; clear the direction flag
|
||
cli ; plus the interrupt flag
|
||
;
|
||
rep movsb ; move it !!!!
|
||
;
|
||
mov ds,ax
|
||
push ax ; push cpm segment address on stack
|
||
mov ax,02500h
|
||
push ax ; push bios cold boot address on stack
|
||
;
|
||
retf ; return far to CPM-86 !!!
|
||
;---------------------------------------------------------------------
|
||
; Subroutines
|
||
;---------------------------------------------------------------------
|
||
; Open CPM.SYS file
|
||
;---------------------------------------------------------------------
|
||
;
|
||
open_cpm:
|
||
;
|
||
xor al,al
|
||
mov ah,03dh
|
||
int dos ; open CPM.SYS file
|
||
mov word ptr cpm_hnd,ax ; save file handle
|
||
;
|
||
ret
|
||
;---------------------------------------------------------------------
|
||
; Close CPM.SYS file
|
||
;---------------------------------------------------------------------
|
||
;
|
||
close_cpm:
|
||
;
|
||
mov bx,word ptr cpm_hnd
|
||
mov ah,03eh
|
||
int dos ; close CPM.SYS file
|
||
;
|
||
ret
|
||
;---------------------------------------------------------------------
|
||
; print string at offset dx
|
||
;---------------------------------------------------------------------
|
||
;
|
||
print_string:
|
||
;
|
||
mov ah,09h
|
||
int dos ; print string
|
||
;
|
||
ret
|
||
;---------------------------------------------------------------------
|
||
; print string and exit
|
||
;---------------------------------------------------------------------
|
||
;
|
||
error_exit:
|
||
;
|
||
call print_string
|
||
mov ah,04ch
|
||
xor al,al
|
||
int dos ; return to dos
|
||
;
|
||
;---------------------------------------------------------------------
|
||
; data
|
||
;---------------------------------------------------------------------
|
||
;
|
||
loading db cr,lf,'Loading CP/M-86 $'
|
||
;
|
||
err_open db cr,lf,lf,'Unable to open CPM.SYS',cr,lf,'$'
|
||
err_read db cr,lf,lf,'Error reading CPM.SYS',cr,lf,'$'
|
||
err_head db cr,lf,lf,'Invalid CPM.SYS header',cr,lf,'$'
|
||
;
|
||
cpm_sys db '\CPM.SYS',0 ; asciiz file name
|
||
cpm_hnd dw 0 ; file handle
|
||
cpm_siz dw 0 ; file size
|
||
cpm_len dw 0 ; code length
|
||
;
|
||
cpm_buf db 32768 dup (0) ; cpm.sys load buffer
|
||
;
|
||
db 0 ; spare
|
||
;
|
||
;---------------------------------------------------------------------
|
||
;
|
||
;---------------------------------------------------------------------
|
||
;
|
||
end
|
||
|