1 REM Ins{nd av Bert Holgersson <560>	1987-12-12 19.02.35 (DUMP);	ZPROG Ramdisc;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;;	* *	U F D - d o s	R A M - D i s c	Ver. 2.0	* *;;	RAM-disc routine for	ABC 80 and UFD-Dos.;;	Bert Holgersson <560> 86-03-03;	Kvarnv{gen 14;	454 00 Brastad;	Tel: 0523/40513;;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;	PREREQ;	------;	Routines are designed for an ABC80 with 64k RAM, built as;	shown in MIKRODATORN. There should, however, be no problem;	in changing the hardware specific part of the code and to;	implement it on 80's expanded in other ways. Of course;	the machine must have ABC-klubben's UFD-dos.;;	PROGRAM;	-------;	Program consists of two parts: One installation part and one;	driver part. Installation part reservs space on stack, puts;	driver in reserved space and links driver to DOS. Driver part;	Checks every DOS acces to disc, and takes action when access;	is made to disc choosen to be RAM-drive;;	INTERRUPTS;	----------;	If you mean to use he routine together with interrupt driven;	communication drivers like SOFTSIO and TERM100, then you must;	be aware that interrupts are disabled during block transfers.;	This can (and must probably, will) cause junk characters to;	to be received/transmitted. However, if you have interrupt;	service routines in place during RAM-disc acces, you dont't;	have to turn interrupts off.( This is no problems for me, as;	I have an external SIO-card );;	USE OF RAM-DISC;	---------------;	RAM-disc is used the same way as ordinary drives.;	Ex:If you select SF0 as RAMDRIVE, then a BASIC line like:;	10 PREPARE "SF0:FOO.BAR" AS FILE 1;	would create the file FOO.BAR in RAM.;	Every time you specify "SF0:" as device, DOS will use;	the "RAM-disc".;;	FORMATTING;	----------;	Like other disc:s, RAM has to be formatted before DOS can;	use it. The formatting is, of course, only the logical;	formatting, that inits bitmap,lockoutsector and lib sectors.;	The BASIC program RAMGEN.BAS can do the formatting for you.;;	;CALL(0);	--------;	The RAM-disc will stay intact between restarts of BASIC/;	DOS. You only have to install the driver again.;;	RESET BUTTON;	------------;	It might even survive a push of reset button if you;	make it a *VERY SHORT* push.( This is because there is no;	refresh of memory, as long as reset button is pressed );;	EVEN CASETTERS;	--------------;	There is no need for discdrives for this function;	Even the "casetters" can use this RAM-drive, if;	they install the UFD-Dos.;;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;;	List of select codes known to UFD-dos;MF0	EQU	8	; Clustersize 4MF1	EQU	9MF2	EQU	10MO0	EQU	12	; Clustersize 1MO1	EQU	13MO2	EQU	14SF0	EQU	16	; Clustersize 4SF1	EQU	17SF2	EQU	18HD0	EQU	4	; Clustersize 4HD1	EQU	5HD2	EQU	6HD3	EQU	7;RAMDRIVE EQU	SF0	; Selectcode for drive simulated in RAM;;	RAM border definitions;RAMSTART EQU	256	; Start adress of "RAM-disc"RAMEND	EQU	32767	
; End adress of "RAM-disc";;	RAM-disc definitions;FIRSTSEC EQU	14	; First adressable sectorMINSECT	EQU	FIRSTSEC-1	; Value to test withRAMSPAN	EQU	RAMEND-RAMSTART	; Available RAM spaceSECTSPAN EQU	RAMSPAN/256	; Number of sectors availableMAXSECT	EQU	SECTSPAN+FIRSTSEC	; Max adressable sectorBLOCKSIZ EQU	256 	; RAM sector size;;	Misc. symbols;JP	EQU	195	; Instruction "JP"STACK	EQU	65063;;	DOS-symbols;DOSBUF0	EQU	62720	
; Adress to	DOSBUF0DRIVBYTE EQU	64769	
; Adress of drive-select byteBCSAVE	EQU	64797	
; Place in system DOS-variablesDRDWRET	EQU	24689	
; Where to find a pointer to link in ram memoryDRVMSK	EQU	00011111B	; Mask for Drive no i Drive select byteREAD	EQU	3	; DOS Read command to controllerWRITE	EQU	12	; DOS Wrie command to controllerNOT_RDY	EQU	10000000B	; Disc error: "Not ready"WRITPROT EQU	01000000B	;	"Write protect"NOTFOUND EQU	00010000B	;	"Not found"CRC_ERR	EQU	00001000B	;	"CRC error"COMM_ERR EQU	00000010B	;	"Command error"BUSY	EQU	00000001B	;	"Busy";SIM_ERR	EQU	NOT_RDY	; Simulated disc error if outside sector bounds;;	External routines definitions;DR_DWEND EQU	25012	
; Terminating code in DR/DW routineGETBUF	EQU	25098	
; Gets adress to DOSBUF B*10H;;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =;;	* * *	I N I T I A L I Z A T I O N	R O U T I N E;		ORG	DOSBUF0	; Init routine in DOSBUF0. ( Only needed once ! )INIT	JP	RAMINITOSYSTACK DEFW 0	; Old system stackpointerNSYSTACK DEFW 0	; New system stackpointerOLDSTACK DEFW 0	; Old stackpointerNEWSTACK DEFW 0	; New stackpointerDEPTH	DEFW 0	; Stack depth when routine started;RAMINIT	LD	(BCSAVE),BC	; Save BC for BASIC;;	
Calculate new system stackpointer;		LD	HL,(STACK)	; Read current stack		LD	(OSYSTACK),HL	; Save that stack		LD	DE,DRIVLEN	; Length of RAM-dsic driver		AND	A	; Clear carry		SBC	HL,DE	
; Resrv space on stack		LD	(NSYSTACK),HL	; Save that stack		LD	(STACK),HL	; Set new system stackpointer;;		Calculate stackdepth and new stackpointer;		LD	(OLDSTACK),SP	; Get current stackpointer		LD	DE,(OLDSTACK)	; into DE		LD	HL,(OSYSTACK)	; Get old system stackpointer		SBC	HL,DE	
; Old system stack - Old stack = Stackdepth		LD	(DEPTH),HL	; Save stackdepth		LD	DE,(NSYSTACK)	;		EX	DE,HL	
; HL:= New system stackpointer, DE:= Stack depth		SBC	HL,DE	
; Make room for stack data		LD	(NEWSTACK),HL	; Save new stackpointer;;	Change stackpointer in CPU;		DI	; No interrupts during stack fixing		HALT	; Between NMI:s		LD	SP,HL	
; Set new stack;;	
Move stack data to new position;		LD	HL,(OLDSTACK)	; Source		LD	DE,(NEWSTACK)	; Destination		LD	BC,(DEPTH)	; Number of bytes to move		LDIR	; Move stack data to new position		EI	; Interrupts are possible to handle again;;	Put driver in space reserved on top of stack;		PUSH DE	; Save driver start adress		LD	HL,RAMFLOP	; Start of RAM-driver code ( Source )		LD	BC,DRIVLEN	; BC = Number of bytes		LDIR	; Put driver where it should be;;	Link driver into DOS;		LD	HL,(DRDWRET)	; Get adress to link		LD	A,JP	; Instruction "JP"		POP	DE	; Get adress to our driver		INC	DE	; Skip save of max sector for RAMGEN		LD	(HL),A		; Make DOS jump to our routine		INC	HL		LD	(HL),E		INC	HL		LD	(HL),D		LD	BC,(BCSAVE)	; Restore BC reg.;;	Move the first 256 bytes, so that NMI can be running in both bank's;		PUSH BC	; Save register for BASIC		DI	; No interrupts during BASIC move		HALT	; Can't stop NMI, so i'll do it between them		LD	HL,0	; Start adress		LD	B,0	; Number of bytes;LOOP	XOR	A	; Memory map 0		OUT	(7),A		LD	D,(HL)		LD	A,3	; Memory map 3 (All RAM)		OUT	(7),A		LD	(HL),D		INC	HL		DJNZ LOOP	; Move 256 bytes;		XOR	A	; Set memory map 0 before returning		OUT	(7),A		EI		POP	BC		LD	HL,(NEWSTACK)	; Tell operator what new stack will be		RET	; Return to whatever called us;;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =;;	* * *	R A M	D I S C	R O U T I N E	* * *;	
(This is the part that will stay in RAM, on top of stack);RAMFLOP	DEFB MAXSECT	; RAMGEN can get max sector here. Adress via DOS		LD	A,(DRIVBYTE)	; Get select code		AND	DRVMSK		; Mask drive number		CP	RAMDRIVE	; Is it RAM drive ?		RET	NZ	; This call was not for me;;	Check that sector are within limit;;	!!NB. Uses only 8 bit arithmetic. If you build a system with;	more than 255 sectors, you must change the calculating routine;		POP	AF	; Skip return from link call		PUSH DE	; Save registers ( BC already saved )		PUSH HL		LD	A,D	; Get high part of sector number		AND	A	; There should be no high part in this system !		JR	NZ,ERR		LD	A,MAXSECT		SUB	E	; Max - Actual sector, must not give carry !		JR	C,ERR	
; Jump if sector is to high;		LD	A,MINSECT		SUB	E	; Min sector - Actual sector, must giv carry		JR	NC,ERR;;	Calculate SOURCE for LDIR;		LD	A,E	; A:=Sectornumber		SUB	FIRSTSEC	; Logical sector -> Physical sector (i.e. 14->0)		LD	DE,RAMSTART	; Beginning of RAM-disc		ADD	A,D	; Offset to wanted sector		LD	D,A	; DE -> wanted RAM sector;		XOR	A	; A = 0		LD	L,A	; Low adress part = 0		CALL GETBUF		; Get high adress part to Dosbuf;		LD	A,C	; Get wanted operation		CP	WRITE	
; Read or write operation ?		JR	Z,MOVE		; Source,Dest OK if write		EX	DE,HL	
; If read operation, it's the other way aroundMOVE	LD	BC,BLOCKSIZ	; Number of bytes to transfer		DI	; No interruptroutines in place while RAM:ing !!		LD	A,3	; 64k All RAM ( Map 3 )		OUT	(7),A;		LDIR	; Move;		XOR	A	; Standard memory map ( 0 ) AND OK indicator		OUT	(7),A	
; Switch back		EI	; Now, interrupts are legal again		JR	OK	; Do an OK exit;ERR	LD	A,SIM_ERR	; Simulated error to DOS		SCF	; Error indicatorOK	JP	DR_DWEND	; Ret done by DR/DW routine.( Terminating part )	; ( Necessary POP:s are done by that routine ! )DRIVLEN	EQU	$-RAMFLOP	; How much to reserve on stack		END	INITD	A,SIM_ERR	; Simulated error to DOS		SCF	; Error indicatorOK	JP	DR_DWEND	; Ret done by DR/DW routine.( Terminating part )	; ( Necessary POP:s are done by that routine ! )DRIVLEN	EQU	$-RAMFLOP	; How much to reserve on stack		END	INIA,SIM_ERR	; Simulated error to DOS		SCF	; Error indicatorOK	JP	DR_DWEND	; Ret done by DR/DW routine.( Terminating part )	; ( Necessary POP:s are done by that routine ! )DRIVLEN	EQU	$-RAMFLOP	; How much to reserve on stack		END	INI0RAMDISC.ASM  Bert Holgersson <560>  1987-12-12 19.15.23 (DUMP)яяWEND	; Ret done by DR/DW routine.( Terminating part )	; ( Necessary POP:s are done by that routine ! )DRIVLEN	EQU	$-RAMFLOP	; How much to reserve on stack		END	INIеееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее