;===================[ Функции распределения памяти ]===================;
;        Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM
;!TEST все SLOT2 на SLOT1
;
;----------------------------------------------------------------------;
;                    Определение объема памяти.
;        Выход: BC - FREE MEM в блоках по 16k, HL - FULL MEM
EMM.GetMemSize:
	IN A,(SLOT1)
	LD B,A
	LD A,SYS_PAGE
	OUT (SLOT1),A
	LD HL,SYS_PAGE.RAMD_FAT - #4000 - #4000
	LD C,0
.loop:	LD A,(HL)
	INC L
	JR Z,.exit
	AND A
	JR NZ,.loop
	INC C
	JR .loop
.exit:	LD HL,#100	;!HARDCODE max mem pages
	LD A,B
	LD B,0
	OUT (SLOT1),A
	RET
;----------------------------------------------------------------------;
;

;!!!!! Если используется SLOT3 со своими страницами, то не пользоваться
;	стеком, там может быть SP в режиме спектрума

;
;----------------------------------------------------------------------;
;               Инициализация распределения памяти.
EMM.InitMem:
	PUSH	BC
	PUSH	HL
	PUSH	DE

	IN	A,(SLOT3)
	LD	C,A
	LD	A,SYS_PAGE
	OUT	(SLOT3),A
	LD	HL,SYS_PAGE.RAMD_FAT; - #4000 - #4000			; Адрес FAT ОЗУ.
	; обнуляем таблицу
	XOR	A
.loopFree:
	LD	(HL),A
	INC	L
	JR	NZ,.loopFree
	; резервируем спец.страницы и страницы ZX
        LD	B,RESERVED_PAGES.Blocks
	LD	DE,RESERVED_PAGES					; таблица занятых системных страниц
.loop:	LD	A,(DE)
	CP	#FF
	JR	Z,.exitLoop
.loopBlk:
	INC	DE
	LD	L,A
	LD	A,(DE)
	LD	(HL),A
	CP	#FF
	JR	NZ,.loopBlk
.exitLoop:
        INC	DE
        DJNZ	.loop
        LD	L,A
        LD	(HL),A
	; Инициализация ключей RAM-Disks
	XOR	A
	LD	HL,SYS_PAGE.RAMD_KEYS; - #4000 - #4000
	LD	B,SYS_PAGE.RAMD_KEYS.NUM
.loop2:	LD	(HL),A
	INC	L
	DJNZ	.loop2
	; [x] 04/11/2023
	 LD	HL,SYS_PAGE.Sp_RAMD_KEYS; - #4000 - #4000	
	 LD	B,SYS_PAGE.Sp_RAMD_KEYS.NUM
.loop3:	 LD	(HL),A
	 INC	L
	 DJNZ	.loop3
	;
	LD	A,C
	OUT	(SLOT3),A
	POP	DE
	POP	HL
	POP	BC
	RET
;---------------------------------------------------------------------[]
RESERVED_PAGES:
        ; [x] Block #1 - можно освободить по ID 1
	 DB	1,3,4,6,7,8,9,10,11,12,13,14,15				; for Spectrum
         ; эмулятор ПЗУ ;!FIXIT ROM-Emulator сделать динамические страницы
	  DB	#42,#43,#44,#45,#46,#47;,#48,#49,#4A,#4B		; For (BASIC128, BASIC48, TRDOS, SCORP_ROM)*2, vBIOS, vEXTENSION
	  DB	#FF							; End of the block
	 ;
	;
        ;; Block #2 - нельзя освобождать
         DB	0,2,5							; for Spectrum and BIOS starting
	 DB	DCP_PAGE 						; Ports map
	 DB	Spec_Page						; Page for Spectrum mode
         ; Screen pages
	  DB	#50,#51,#52,#53,#54,#55,#56,#57
          DB	#58,#59,#5A,#5B,#5C,#5D,#5E,#5F  
         ;
	 ;DB	MODE_PAGE						; ?????
	 DB	CBL.BUFFER_PAGE                                         ; Page for CBL audio
	 DB	SYS_PAGE                                                ; Page for system (BIOS) variables
	 DB	#FF                                                     ; End of the block
	;
.Blocks EQU 2
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;                  Получить блок памяти N bytes,
;               Вход:   B - число необходимых блоков
;               Выход:  L,A - КЛЮЧ RAM-Disk/код ошибки
;                       CF - признак ошибки
;EMM_FN2M:
EMM.GetMem:
	;PUSH DE
	PUSH BC
	IN A,(SLOT3)
	EX AF,AF'
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD C,B		; сохранить число нужных блоков
	LD HL,SYS_PAGE.RAMD_FAT; - #4000 - #4000
; Цикл проверки наличия нужных блоков.
.loop:	DEC L
	JR Z,.noRAM
	LD A,(HL)
	AND A
	JR NZ,.loop
	DJNZ .loop

        ; Место есть !
	LD B,C		; Восстановить нужный объем диска
	LD C,#FF	; МЕТКА КОНЦА RAM-Disk
	LD HL,SYS_PAGE.RAMD_FAT; - #4000 - #4000

; Заполнить RAMD_FAT
.loop2:	DEC L
	LD A,(HL)
	AND A
	JR NZ,.loop2
	LD (HL),C
	LD C,L
	DJNZ .loop2

        ; L - указатель цепочки.
	EX AF,AF'
	OUT (SLOT3),A
	LD A,L
	AND A
	POP BC
	;POP DE
	RET

.noRAM:	LD L,1		; НЕТ ПАМЯТИ
	EX AF,AF'
	OUT (SLOT3),A
	LD A,L
	SCF
	POP BC
	;POP DE
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;               Получить блок памяти N bytes, для RAM-Disk A
;               Вход:   B - число необходимых блоков, A - RAM-Disk
;               Выход:  L,A - КЛЮЧ RAM-Disk/код ошибки
;                       CF - признак ошибки
;EMM.GetMem:
EMM.GetMemRMD:
	PUSH AF
	CALL EMM.GetMem
	JR C,.error1

	LD B,A
	POP AF
	CALL BLK_TO_RAMD
	RET NC
.error2:
	LD L,2		; RAM-Disk занят                                ;!TODO перечислить все варианты ошибок и их номера как для ДСС
	LD A,L
	RET
.error1:
	POP HL		; чистим стек
	LD L,A
	;SCF
	RET
;----------------------------------------------------------------------;
;



;----------------------------------------------------------------------;
;               Освободить блок памяти ключа K
;               Вход:	A - КЛЮЧ RAM-Disk
EMM.FreeMemRMD:
	CALL GET_RAMD_ST
	RET C
	SCF
	RET Z
	LD C,A
	IN A,(SLOT3)
	LD B,A
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD H,high SYS_PAGE.RAMD_KEYS; - #4000 - #4000
	LD (HL),0
	LD A,B
	OUT (SLOT3),A
	LD A,C
	;JR EMM.FreeMem
;------[
;               Освободить блок памяти
;               Вход: A - НАЧАЛО ЦЕПОЧКИ
; НЕ ПОРТИТЬ DE!!!
;EMM_FN3M:
EMM.FreeMem:
	AND	A
	SCF
	RET	Z
	;
	LD	L,A
	CP	ZX_RAM_ID
	CALL	Z,SET_ROM_FLAG_ZX
	;
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,SYS_PAGE
	OUT	(SLOT3),A

	LD	H,high (SYS_PAGE.RAMD_FAT)
	LD	A,L
EMM_F3M_L1:
	LD L,A
	LD A,(HL)	; следующий блок
	AND A
	JR Z,EMM_FN3M_ERR
	LD (HL),0	; Освободить
	CP #FF		; Если не конец
	JR NZ,EMM_F3M_L1 ; продолжать

	EX AF,AF'
	OUT (SLOT3),A
	XOR A		; no error code
	RET

EMM_FN3M_ERR:
	EX AF,AF'
	OUT (SLOT3),A
	LD A,BIOS.Error.BadNumber
	SCF
	RET
;----------------------------------------------------------------------;
;



;		WARNING!!! не трогать DE
;----------------------------------------------------------------------;
;               Получить страницу N ключа K
;               Вход:	 A - КЛЮЧ RAM-Disk, B - номер страницы
;               Выход: A - страница
EMM.GetMemPageRMD:
	CALL GET_RAMD_ST
	RET C
	SCF
	RET Z
	;JR EMM.GetMemPage
;------[                                
;                   Получить страницу N блока K
;               Вход: A - блок, B - номер страницы
;     Выход: A - страница, IF CF - A=0 - нет блока, A=FF - END
;EMM_FN4M:
EMM.GetMemPage:
	LD L,A
	IN A,(SLOT1)
	EX AF,AF'
	LD A,SYS_PAGE
	OUT (SLOT1),A

	INC B
	LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
EMM_F4M_L1:
	LD A,(HL)
	AND A
	JR Z,EMM_F4M_ERR
	DEC B
	JR Z,EMM_F4M_END
	LD L,A
	CP #FF
	JR NZ,EMM_F4M_L1
EMM_F4M_ERR:
	LD L,A
	EX AF,AF'
	OUT (SLOT1),A
	LD A,L
	SCF
	RET

EMM_F4M_END:
	EX AF,AF'
	OUT (SLOT1),A
	LD A,L
	AND A
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;               Получить следующую страницу по FAT
;               Вход:	A - страница ОЗУ
;               Выход:	A - следующая страница ОЗУ
;EMM_FN5:
EMM.GetMemPageNext:
	LD L,A
	AND A
	SCF
	RET Z
	IN A,(SLOT1)
	LD H,A
	LD A,SYS_PAGE
	OUT (SLOT1),A
	LD A,H
	LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
	LD L,(HL)
	OUT (SLOT1),A
	LD A,L
	AND A
	SCF
	RET Z
	AND A
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;                  Получить список страниц блока в HL
;             Вход:   A - блок, HL - адрес буфера - 256 байт.
;        Выход:  HL - адрес блока, B - длина блока в страницах ОЗУ
;EMM_FN5M:
EMM.GetMemBlkPages:
	PUSH DE
	PUSH HL
	EX DE,HL
	LD B,0
	LD L,A

.loop:	LD A,L
	LD (DE),A
	INC DE
	AND A
	JR Z,.error
	CP #FF
	JR Z,.end
	;
	IN A,(SLOT1)
	LD C,A
	LD A,SYS_PAGE
	OUT (SLOT1),A
	LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
	LD L,(HL)
	LD A,C
	OUT (SLOT1),A
	;
	INC B
	JR NZ,.loop

.error:	SCF
.end:	POP HL
	POP DE
	RET

; RAMDRV.EXE вызывает эту функцию с адресом в SLOT1, поэтому лучше так не оптимизировать
; EMM.GetMemBlkPages:
; 	PUSH DE
; 	PUSH HL
; 	EX DE,HL
; 	LD B,0
; 	LD L,A

; 	IN A,(SLOT1)
; 	LD C,A
; 	LD A,SYS_PAGE
; 	OUT (SLOT1),A

; .loop:	LD A,L
; 	LD (DE),A
; 	INC DE
; 	AND A
; 	JR Z,.error
; 	CP #FF
; 	JR Z,.end
; 	;
; 	LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
; 	LD L,(HL)
; 	INC B
; 	JR NZ,.loop

; .error:	SCF
; .end:	LD A,C
; 	OUT (SLOT1),A
; 	POP HL
; 	POP DE
; 	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;	!FIXIT SAFE_RGADR
;RAMD_R_W:
;       ╔════════════════════════════════════════════════╗
;       ║ RD/WR SECTOR                                   ║\
;       ║ HL - BUFER                                     ║\
;       ║ DE - ABS sector в 256b блоках                  ║\
;       ║ B  - число данных в 256b блоках                ║\
;       ║ A  - block RAM                                 ║\
;       ║ A' - команда чтение/запись/чтение ROM Disk     ║\
;       ║      0 - read, 255 - write, 70 - read ROM DISK ║\
;       ║ ** NOT USED TR-DOS VARS **                     ║\
;       ╚════════════════════════════════════════════════╝\
;        \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
BLK_RD_WR:
	AND A
	SCF
	RET Z
	;
	AND A
	INC	B
	DEC	B
	RET	Z
        ;
        ; сохраняем состояние прерываний
        LD      C,A
        LD      A,R
        PUSH    AF
	; сохраняем PORT_Y
	IN	A,(PORT_Y)
	PUSH	AF
	LD	A,#C0
	OUT	(PORT_Y),A
	;
        LD      A,C
        DI
        CALL    .start
        EX      AF,AF'
        ; восстанавливаем PORT_Y
	POP	AF
	OUT	(PORT_Y),A
	; восстанавливаем состояние прерываний
        POP     AF
        JP PO,.noInterrupts
        EI
.noInterrupts:
 	EX AF,AF'
 	RET
        ;
        
.start:	EX AF,AF'
	AND A                   ; 0 - read
	JR Z,.reset_Z
	CP #FF                  ; write
	JR Z,.keep_Z

	CP 5                    ; old read 
	JR Z,.reset_Z
	CP 6                    ; old write 
	JR Z,.keep_Z

	CP #46
	JP Z,ROM_DISK

	EX AF,AF'
	SCF
	RET

.reset_Z:
	INC A                   ; set Z for WRITE
.keep_Z:
	EX AF,AF'
        ;

	PUSH HL
	PUSH BC
	LD C,SLOT1
	IN B,(C)
        LD H,A
	LD A,SYS_PAGE
	OUT (SLOT1),A
        LD A,H

	LD H,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
	LD L,A

	INC D
.RAMD_LOOP_D:
	DEC D
	JR Z,.NOT_FOUR_BLK
	LD L,(HL)
	LD L,(HL)
	LD L,(HL)
	LD L,(HL)
	JR .RAMD_LOOP_D

.NOT_FOUR_BLK:
	LD A,E
.loop:	SUB #40
	JR C,.NOT_ONE_BLK
	LD L,(HL)
	JR .loop

.NOT_ONE_BLK:
	AND #3F
	LD D,A			; DE - ADRESS in RAM-Disk
	LD E,0

	LD A,L			; L - текущий банк RAM-Disk

	OUT (C),B		; восстановить страницу

	POP BC			; длина данных
	POP HL			; адрес буфера

	BIT 7,H
	JR NZ,.BLK_PAGE1

	LD C,SLOT3
	IN C,(C)
	OUT (SLOT3),A
	SET 7,D
	SET 6,D
	JR .BLK_CONT1

.BLK_PAGE1:
	LD C,SLOT1
	IN C,(C)
	OUT (SLOT1),A
	RES 7,D
	SET 6,D

.BLK_CONT1:		        ; DE - RamDisk, HL - data
	EX AF,AF'
	JR Z,.NO_EX_RW1		; WRITE
	EX DE,HL		; for READ
.NO_EX_RW1:
	EX AF,AF'

	LD A,16
.BLK_LL1:
	DUP 16
	 LDI
	EDUP
                
	DEC A
	JR NZ,.BLK_LL1

	EX AF,AF'
	JR Z,.NO_EX_RW2		; WRITE
	EX DE,HL		; for READ
.NO_EX_RW2:
	EX AF,AF'       ; DEC C прокрутился 256 раз и вернулся
	INC B		; B уже уменьшился на 1,
	DEC B
	JP Z,.BLK_EXIT_1

	BIT 6,D
	JP NZ,.BLK_CONT1

	BIT 7,D
	JR Z,.BLK_PAGE3_X

	IN A,(SLOT1)
	LD E,A
	LD D,high (SYS_PAGE.RAMD_FAT - #4000 - #4000)
	LD A,SYS_PAGE
	OUT (SLOT1),A
	LD A,(DE)
	OUT (SLOT1),A
	LD DE,#4000
	JP .BLK_CONT1

.BLK_PAGE3_X:
	IN A,(SLOT3)
	LD E,A
	LD D,high SYS_PAGE.RAMD_FAT
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD A,(DE)
	OUT (SLOT3),A
	LD DE,#C000

	BIT 7,H
	JP Z,.BLK_CONT1

	LD E,A
	LD A,C
	OUT (SLOT3),A
	IN A,(SLOT1)
	LD C,A
	LD A,E
	OUT (SLOT1),A
	LD DE,#4000
	JP .BLK_CONT1

.BLK_EXIT_1:
	LD A,D
        DEC A
	RLCA
	LD A,C
	JR  C,.BLK_EXIT_2
	OUT (SLOT1),A
	RET
.BLK_EXIT_2:
	OUT (SLOT3),A
	AND A
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
        ;****************************************
        ;!!!!! READ_ROM_PAGE_X чтение последних
        ; 256 байтов ПЗУ в служебную страницу зачем-то
        ; READ_ROM_PAGE_X:
        ; 	LD DE,0
        ; 	LD BC,#100						; один сектор
        ; 	PUSH DE
        ; 	PUSH BC
        ; 	LD HL,#3F00
        ; 	LD DE,#FF00
        ; 	LD A,#1F						; last page ROM
        ; 	JR ROM_DISK.loopRead
        ;****************************************

; Чтение с ROM-Disk
; HL - адрес, куда читать
; DE - номер сектора (считать по 256b сектор) 
; B  - число секторов
; A' - размер сектора (1 - 256b, 2 - 512 b)
ROM_DISK:
        ; сохраняем состояние прерываний
        ;LD A,R
	EX AF,AF'
        LD C,0                                                          ; счетчик
	DEC A
	JR Z,.loop
	;JR Z,.start
	DEC A
	SCF
	RET NZ

	EX DE,HL
	ADD HL,HL
	EX DE,HL
	LD A,B
	ADD A,A
	LD B,A
        ;!!!!!
	RET C

        DI
        CALL .loop
;         ; восстанавливаем состояние прерываний
; 	EX AF,AF'
;         JP PO,.noInterrupts
;         EI
; .noInterrupts:
; 	EX AF,AF'
;         ;
	RET C
	AND A
	RR D
	RR E
	XOR A
	RET

; .start:
;         DI
;         CALL .loop
;         ; восстанавливаем состояние прерываний
; 	EX AF,AF'
;         JP PO,.noInterrupts2
;         EI
; .noInterrupts2:
; 	EX AF,AF'
;         ;
; 	RET     


.loop:	PUSH DE                                                         ; номер сектора
	PUSH BC

	LD A,E
	AND #3F								; ADRESS in ROM-Page
	PUSH AF                                                         ; сохранить адрес

	EX DE,HL                                                        ; DE - адрес буфера
	ADD HL,HL
	ADD HL,HL                                                       ; H - номер банки

	LD A,(ROM_DISK.Pages.Number)
	INC H
	CP H
	LD L,H
	LD H, high ROM_DISK.Pages.Number                                ; ROM-Disk pages!
	LD A,(HL)                                                       ; PAGE-ROM

	POP HL                                                          ; восстановить адрес в ROM-Page
	LD L,0                                                          ; если далеко захотели - выход с ошибкой
	JR C,.errorExit                                                 ; ROM-Disk-end
; DE - буфер
; HL - адрес в ROM
; B - число секторов
; A - ROM-Page
.loopRead:
	PUSH HL								; откуда
	PUSH DE								; куда

	LD HL,-.stackDepth - .readProcedure.size			; memory stack use!
	ADD HL,SP							; stack

	PUSH HL								; адрес программы .readProcedure

	LD DE,.readProcedure						; перенести программу на стек
	EX DE,HL
	LD BC,.readProcedure.size
	LDIR								; программа на стеке
	LD BC,#100							; длина сектора
	RET								; исполнить программу .readProcedure, на стеке адреса буфера и ROM
; DE - next address
; HL - ROM address
.readNext:
        POP BC								; число секторов

        INC C								; счетчик считанных секторов
        DEC B								; сектора кончились?

        JR Z,.normExit
        BIT 6,H								; чтение не закончено

        PUSH BC								; сохранить счетчики
        JR Z,.loopRead							; читать дальше
        POP BC

        POP HL								; номер сектора

        LD A,B
        LD B,0
        ADD HL,BC
        LD B,A								; вычислить след.сектор

        EX DE,HL							; теперь HL - адрес, DE сектор, B - сколько еще читать

        JP .loop							; начать все снова!
; чтение закончено
.normExit:
	POP HL								; сектор, откуда велось чтение
	ADD HL,BC							; по возврату: HL - след.адрес
	EX DE,HL							;              DE - след.сектор
	AND A
	RET
; ошибка
.errorExit:                                                             ; !TODO сделать, чтоб на выходе показывалось количество прочитанных секторов
	POP BC
	POP DE
	SCF
	RET
; процедура, переносимая на стек для чтения из ROM-Disk
; осторожнее с PUSH, если надо много, то увеличивай .stackDepth
.readProcedure:
	POP DE								; куда
	POP HL								; откуда
	OUT (ROM.SLOT0),A						; ROM_PAGE
	LDIR								; здесь читается из ROM-Disk
	LD B,A
	XOR A
	OUT (ROM.SLOT0),A
	OUT (SYS_PORT.ROM),A
	LD A,B
	JP .readNext
.stackDepth		EQU 8						; расстояние от конца процедуры до вершины стека. 
.readProcedure.size	EQU $-.readProcedure
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;               вход:  DE - ram_disk trk_sec, A - RAM-Disk
;               выход: HL - адрес, A - page
RAMD_CALC_PAGE:
	CP 16
	CCF
	RET C	; НЕТ ТАКОГО RAM-Disk

	PUSH AF
	LD H,D
	LD L,E
	ADD HL,HL
	ADD HL,HL
	LD B,H
	LD A,E
	OR #C0
	LD C,A		; C - часть адреса, B - страница
	POP AF

	CALL EMM.GetMemPageRMD	; ПОЛУЧИТЬ СТРАНИЦУ
	LD L,0
	LD H,C
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;       Вход:
;        A - RAM Disk ID
;       Выход:
;         A - Number (0..15)
GET_RAMD_NUM:
        EX      AF,AF'
        IN      A,(SLOT1)
        EX      AF,AF'
        LD      BC,SYS_PAGE * 256 + SLOT1
        OUT     (C),B

        LD      HL,SYS_PAGE.RAMD_KEYS - #4000 - #4000
        LD      BC,SYS_PAGE.RAMD_KEYS.NUM
        CPIR

        EX      AF,AF'
        OUT     (SLOT1),A
        EX      AF,AF'

        SCF
        RET     PE

        DEC     L
        LD      A,L
        SUB     low SYS_PAGE.RAMD_KEYS
        RET      
;----------------------------------------------------------------------;
;


;
;----------------------------------------------------------------------;
; [x] 04/11/2023
;       Вход:
;        B = 0:	  swap to Sp
;	 B = #FF: swap to ZX
;	 B = #FE: no swap, only get info
;       Выход:
;         A - current RAM Drives set
SWAP_RAM_DRIVES:
	IN	A,(SLOT3)
	EX	AF,AF'
	PUSH	AF		;на всякий случай
	LD	A,SYS_PAGE
	OUT	(SLOT3),A
	;
	LD	A,(SYS_PAGE.CURRENT_RAM_DRV)
	LD	C,A
	CP	B
	JR	Z,.exit		; уже установлен запрашиваемый набор
	;
	LD	A,#FE
	CP	B
	JR	Z,.exit		; ничего не менять, выдать текущий набор
	;
.swap:	LD	HL,SYS_PAGE.RAMD_KEYS
	LD	DE,SYS_PAGE.Sp_RAMD_KEYS
	LD	B,SYS_PAGE.RAMD_KEYS.NUM
.loop:	LD	A,(DE)
	LD	C,A
	LD	A,(HL)
	LD	(DE),A
	LD	A,C
	LD	(HL),A
	INC	HL
	INC	DE
	DJNZ	.loop
	;
	LD	A,(SYS_PAGE.CURRENT_RAM_DRV)
	XOR	#FF
	LD	(SYS_PAGE.CURRENT_RAM_DRV),A
	LD	C,A
	;
.exit:	EX	AF,AF'
	OUT	(SLOT3),A
	POP	AF
	EX	AF,AF'	
	LD	A,C
	RET
;----------------------------------------------------------------------;
;


;
;----------------------------------------------------------------------;
;       на выходе при А = 0 должен быть установлен флаг Z
; не убивает DE и BC
GET_RAMD_ST:
	CP SYS_PAGE.RAMD_KEYS.NUM
	CCF
	RET C

	PUSH BC

	LD HL,SYS_PAGE.RAMD_KEYS - #4000 - #4000
	ADD A,L
	LD L,A

	IN A,(SLOT1)
	LD B,A
	LD A,SYS_PAGE
	OUT (SLOT1),A
	LD C,(HL)
	LD A,B
	OUT (SLOT1),A
	LD A,C
	POP BC
	AND A
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
;               RAM-Disk A, BLK - B
BLK_TO_RAMD:
	CP SYS_PAGE.RAMD_KEYS.NUM
	CCF
	RET C

	PUSH HL
	LD L,A

	IN A,(SLOT3)
	LD C,A
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD A,L
	LD HL,SYS_PAGE.RAMD_KEYS; - #4000 - #4000
	ADD A,L
	LD L,A
	LD A,(HL)	; ключ блока
	AND A
	JR NZ,BLK_BUSY	; RAM-Disk занят - ошибка
	LD (HL),B

	LD A,C
	OUT (SLOT3),A

	LD A,B
	AND A
	POP HL
	RET
	;
BLK_BUSY:
	LD A,C
	OUT (SLOT3),A
	SCF
	POP HL
	LD A,L
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
; RAM-Disk A
RAMD_CLEAR:
	CP SYS_PAGE.RAMD_KEYS.NUM
	CCF
	RET C

	PUSH HL
	LD L,A

	IN A,(SLOT3)
	LD C,A
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD A,L
	LD HL,SYS_PAGE.RAMD_KEYS; - #4000 - #4000	; RAM-Disk свободен
	ADD A,L
	LD L,A
	LD B,A		; запомнить удаляемый рамдиск
	LD A,(HL)
	AND A
	JR Z,BLK_BUSY	; возврат с ошибкой
	LD (HL),0
	LD A,C
	OUT (SLOT3),A

	AND A
	POP HL
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
; разделить блок памяти на два блока
; A - блок, B - длина первого блока после разделения
; выход: A - блок 1, B - блок 2
EMM.DivMemBlocks:
	INC B
	DEC B
	SCF
	RET Z
	DEC B
	LD E,A
	CALL EMM.GetMemPage	; получить номер страницы блока
	RET C
	LD D,A

	IN A,(SLOT3)
	EX AF,AF'
	LD A,SYS_PAGE
	OUT (SLOT3),A

	LD H,high (SYS_PAGE.RAMD_FAT); - #4000 - #4000)
	LD L,D
	LD A,(HL)
	LD (HL),#FF
	LD B,A

	EX AF,AF'
	OUT (SLOT3),A

	LD A,E
	AND A
	RET
;----------------------------------------------------------------------;
;



;
;----------------------------------------------------------------------;
; слить два блока памяти в один
; А - блок 1, B - блок 2
; выход: А - блок
EMM.MergeMemBlocks:
	LD E,A
	IN A,(SLOT3)
	EX AF,AF'
	LD A,SYS_PAGE
	OUT (SLOT3),A
	LD H,high (SYS_PAGE.RAMD_FAT); - #4000 - #4000)
	LD L,E
	LD C,B
	LD B,0
.EMM_ADD_L:
	LD A,(HL)
	AND A
	JR Z,.EMM_ADD_ERR
	CP #FF
	JR Z,.EMM_ADD_NEXT
	LD L,A
	DJNZ .EMM_ADD_L

.EMM_ADD_ERR:
	EX AF,AF'
	OUT (SLOT3),A
	SCF
	RET

.EMM_ADD_NEXT:
	LD A,C
	AND A
	JR Z,.EMM_ADD_ERR
	LD (HL),A
	EX AF,AF'
	OUT (SLOT3),A
	AND A
	LD A,E
	RET
;----------------------------------------------------------------------;
;