;	RAM.A	MS-DOS V2.0 RAM DISK PROGRAM
;	assemble with the DeSmet assembler
;	Like the IBM ramdisk but with a setram feature. - John N. White

SRH_LEN		EQU	13		;LENGTH
SRH_STA_FLD	EQU	3		;STATUS FIELD

DTA		EQU	SRH_LEN+1	;DATA TRANSFER ADDRESS
COUNT		EQU	DTA+4
SSN		EQU	COUNT+2		;START SECTOR NUMBER

RET_BYTE	EQU	DTA		;RETURN BYTE

BPBA_PTR	EQU	COUNT		;POINTER TO BPB
;	INITIALIZE
UNITS		EQU	SRH_LEN
BR_ADDR_0	EQU	SRH_LEN+1
BR_ADDR_1	EQU	BR_ADDR_0+2
BPB_PTR_OFF	EQU	BR_ADDR_0+4
BPB_PTR_SEG	EQU	BPB_PTR_OFF+2

	CSEG
;	DEVICE HEADER
NEXT_DEV	DW	-1,-1
ATTRIBUTE	DW	6000H		;IOCTL supported
STRATEGY	DW	DEV_STRATEGY
INTERRUPT	DW	DEV_INT
DEV_NAME	DB	1		;NUMBER OF DEVICES
		DB	0,0,0,0,0,0,0

RH_OFF		DW	0		;REQUEST HEADER OFFSET
RH_SEG		DW	0		;SEGMENT

;	CURRENT INFORMATION
TOTAL		DW	0		;NUMBER OF SECTORS TO TRANSFER
START_SEC	DW	0		;FIRST SECTOR
VDISK_PTR	DW	0
USER_DTA	DW	0,0		;USERS DATA TRANSFER ADDRESS
BPB		DW	512		;PER SECTOR
		DB	1		;ALLOCATION UNIT
		DW	0		;0 RESERVED
		DB	1		;1 FAT
		DW	32		;DIRECTORY ENTRIES
SECTORS		DW	10H		;SECTORS TOTAL
MEDIA_TYPE	DB	0FCH		;MEDIA BYTE
FAT_SIZE	DW	3		;SECTORS IN FATS
BPB_PTR		DW	BPB
MEDIA_IN	DB	-1		;MEDIA IN DRIVE IF 1

FUNTAB:
	DW	INIT
	DW	MEDIA_CHECK
	DW	BUILD_BPB
	DW	IOCTLI
	DW	INPUT
	DW	EXIT
	DW	EXIT
	DW	EXIT
	DW	OUTPUT
	DW	OUTPUT			;DONT BOTHER VERIFYING
	DW	EXIT
	DW	EXIT
	DW	IOCTLO

IN_SAVE:MOV	AX,ES:WORD [BX+DTA]	;SAVE CALLERS DTA
	MOV	DS:WORD USER_DTA,AX
	MOV	AX,ES:WORD [BX+DTA+2]
	MOV	DS:WORD USER_DTA+2,AX
	MOV	AX,ES:WORD [BX+SSN]	;START SECTOR
	MOV	DS:START_SEC,AX
	MOV	AX,ES:WORD [BX+COUNT]	;COUNT OF SECTORS
	MOV	AH,0
	MOV	DS:WORD TOTAL,AX
	RET

CALC_ADDR:
	MOV	AX,DS:START_SEC
	MOV	CL,5			;TURN SECTORS INTO PARAGRAPHS
	SHL	AX,CL
	ADD	AX,DS:VDISK_PTR
	MOV	CH,DS:BYTE TOTAL	;CX=LENGTH IN WORDS
	MOV	CL,0
	MOV	DS,AX			;MOVE ADDRESS TO DS:SI
	XOR	SI,SI
	RET

;	STRATEGY ENTRY
DEV_STRATEGY:
	MOV	CS:RH_SEG,ES		;SAVE ES:BX
	MOV	CS:RH_OFF,BX
	LRET

;	DEVICE INTERRUPT HANDLER
DEV_INT:
	PUSH	DS			;SAVE STATE
	PUSH	ES
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DI
;		SET STATUS TO ALL OK
	MOV	ES:WORD [BX+SRH_STA_FLD],100H
	MOV	AL,ES:[BX+2]		;GET FUNCTION BYTE
	SHL	AL,1			;TIMES 2
	MOV	AH,0
	MOV	DI,AX			;FUNCTION OFFSET
	PUSH	CS
	POP	DS
	JMP	WORD FUNTAB[DI]

;	MEDIA CHECK
;media status is -1 after release of memory
MEDIA_CHECK:
	MOV	AL,DS:MEDIA_IN
	MOV	ES:BYTE [BX+RET_BYTE],AL
	JMP	EXIT

;	BUILD BIOS PARAMETER BLOCK
BUILD_BPB:
	MOV	ES:WORD [BX+BPBA_PTR],OFFSET BPB
	MOV	ES:WORD [BX+BPBA_PTR+2],CS
	CMP	DS:MEDIA_IN,1
	JE	EXIT
	CMP	DS:VDISK_PTR,0
	JZ	EXIT
	MOV	DS:MEDIA_IN,1
	CLD
	MOV	ES,DS:VDISK_PTR
	MOV	DI,0			;ZERO OUT FAT
	MOV	AL,DS:MEDIA_TYPE
	XOR	AL,1			;FORCE MS-DOS TO LOOK AT SECTOR COUNT
	MOV	DS:MEDIA_TYPE,AL
	STOSB				;SET FIRST 3 BYTES OF FAT
	MOV	AX,0FFFFH
	STOSW
	MOV	CX,16*512-3		;SIZE OF REST OF FAT + DIRECTORY
	XOR	AL,AL
REP	STOSB				;FAT IS ZERO
	JMP	EXIT

;	READ A SECTOR
INPUT:
	CMP	DS:MEDIA_IN,1		;MAKE SURE MEDIA IN DRIVE
	JNE	BAD_EXIT
	CALL	IN_SAVE
	CALL	CALC_ADDR		;GET SECTOR ADDRESS
	LES	DI,CS:USER_DTA		;LOAD DESTINATION ADDRESS
	CLD
REP	MOVSW				;MOVE READ DATA
	JMP	EXIT

;	WRITE A SECTOR
OUTPUT:
	CMP	DS:MEDIA_IN,1		;MAKE SURE MEDIA IN DRIVE
	JNE	BAD_EXIT
	CALL	IN_SAVE
	CALL	CALC_ADDR		;GET DESTINATION ADDRESS
	PUSH	DS
	POP	ES			;PUT DESTINATION INTO ES:DI
	MOV	DI,SI
	LDS	SI,CS:USER_DTA		;LOAD SOURCE ADDRESS
	CLD
REP	MOVSW
	JMP	EXIT

BAD_EXIT:
	MOV	ES:WORD [BX+SRH_STA_FLD],8002H
	JMP	EXIT

;	IOCTLI
IOCTLI:
	CALL	IN_SAVE
	MOV	AX,DS:VDISK_PTR
	LDS	DI,DS:USER_DTA
	MOV	DS:[DI],AX
	JMP	EXIT

;	IOCTLO
IOCTLO:
	CALL	IN_SAVE
	PUSH	DS
	LDS	DI,CS:USER_DTA
	MOV	AX,DS:[DI]
	MOV	CX,DS:[DI+2]
	POP	DS
	MOV	DS:VDISK_PTR,AX
	MOV	AX,CX
	MOV	DS:SECTORS,AX
	SHR	AX,1			;FIND FAT SIZE
	ADD	AX,CX
	MOV	CL,9
	SHR	AX,CL
	INC	AX
	MOV	DS:WORD FAT_SIZE,AX
	MOV	DS:BYTE MEDIA_IN,-1


;	COMMON EXIT
EXIT:	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	POP	ES
	POP	DS
	LRET

;	INTILLIZATION
INIT:
	MOV	AX,OFFSET INIT		;RAM IS AT END OF THIS CODE
	MOV	CL,4			;MAKE PARAS
	SHR	AX,CL
	INC	AX			;1 FOR ROUND UP
	PUSH	CS
	POP	DI
	ADD	AX,DI			;ADD CURRENT CS
	PUSH	ES
	POP	DS
	MOV	DS:WORD [BX+BR_ADDR_0],0 ;SET FREE ADDRESS
	MOV	DS:WORD [BX+BR_ADDR_1],AX
	MOV	DS:BYTE [BX+UNITS],1	;ONE UNIT
	MOV	DS:WORD [BX+BPB_PTR_OFF],OFFSET BPB_PTR
	MOV	DS:WORD [BX+BPB_PTR_SEG],CS
	JMP	EXIT

	END
s more than 50 lines, or more than 600 key
words, then the record is broken at that point and subsequent
lines are