;	DISPLAY "Service"
; !FIXIT тут можно, походу, дохрена убрать

; ; страницы с конфой для Sp97, для совместимости с древними прогами
; PG_SP1	equ #EC
; PG_SP2	equ #EE
; PG_AY	equ #EA
; ;

; ;!TODO замутить заливку конфы, рестарт, перехват ресета силами BIOS
; PG_Sp2000		EQU #FE
; PG_Sp2000_REINIT	EQU #FD
;

RST_CONF:
;--[] ZX Spectrum
.AY8910:	CALL	.ACC_OFF
		LD	DE,ACEX.Config_ID.Sp97_AY
		JR	.INT_PLD
		;LD	A,CNF_PORT.CNF_1
		;OUT	(SYS_PORT.ON),A
		;RET
;--[]

;--[] Sprinter ZX
.SP97_1:	CALL	.ACC_OFF
		LD	DE,ACEX.Config_ID.Sp97_1
		JR	.INT_PLD
;--[]

;--[]
.SP97_2:	CALL	.ACC_ON
		LD	DE,ACEX.Config_ID.Sp97_2
		JR	.INT_PLD
;--[]


;--[]
;[x]
.SP2000:	CALL	.ACC_ON
		LD	DE,ACEX.Config_ID.Sp2000
		JR	.INT_PLD
;--[]


;--[]
.CUSTOM:	LD	C,A
		; устанавливаем нулевую карту портов
		LD	A,CNF_PORT.CNF_0
		OUT	(SYS_PORT.ON),A
		LD	A,C
		;
		CP	#80 ; тут теперь может любое число быть у старых прог
		JR	NC,.CHOOSE_CNF
		; only for old FLEX10K soft compatible
.crutch:	LD	C,SLOT3
		IN	B,(C)
		OUT	(C),A						; PAGE с прошивкой
		LD	DE,(#C090)					; PLD-ID
		OUT	(C),B						; RET page
;--[]		;JR INT_PLD
.INT_PLD:       ; only for old FLEX10K soft compatible
		LD	C,SLOT3
		IN	B,(C)
		 LD	A,SYS_PAGE
		 OUT	(C),A
		 LD	(SYS_PAGE.CONFIG_BYTE),DE
		OUT	(C),B
		;
		LD	A,E		; config-byte
		CP	#FF
		LD	A,#80
		JR	Z,.YES_CBL
		XOR	A
.YES_CBL:	LD	BC,CBL.SYS_PORT
		OUT	(C),A
		;
		LD	A,E		; config-byte
		OR	#FE						;!HARDCODE 
		LD	BC,Port_All_Mode				; SYSTEM Spectrum/Sprinter
		OUT	(C),A
		;
		LD	A,#3C
		OUT	(FDC_93.DrvCTRL),A
		; восстанавливаем карту портов - походу, не нужно
		;LD	C,SLOT3
		;IN	B,(C)
		; LD	A,SYS_PAGE
		; OUT	(C),A
		; LD	A,(SYS_PAGE.CONFIG_DE.CNF_PORT)
		;OUT	(C),B
		;OUT	(SYS_PORT.ON),A		
		XOR	A
		RET
		;
	;[x]
.CHOOSE_CNF:	; [x] bug with "free zx pages"
		 LD	A,high ZX_MEM_PORT.Scorpion
		 IN	A,(ZX_MEM_PORT)
		 RRCA
		 LD	A,C
		 JR	C,.not_vRAM_page
		 ;
		 IN	A,(SLOT3)
		 CP	C
		 LD	A,C
		 JR	Z,.crutch
		; [x]
.not_vRAM_page:	 CP	ACEX.Config_PG.Sp2000_SoftRestartNow
		 JP	Z,.ReturnSoftReset
		 ;
		 CP	ACEX.Config_PG.Sp2000_AcexSetUpNow
		 JR	Z,.INIT_ACEX
		 ;
		 CP	ACEX.Config_PG.Sp2000_SetUp
		 JR	Z,.SP2000
		 ;
		 CP	ACEX.Config_PG.Sp2000_SoftRestartSet
		 JR	Z,.SetUpSoftReset
		 ;
		 CP	ACEX.Config_PG.Sp2000_AcexSetUpSet
		 JR	Z,.SetUpHardReset
		;
		; only for old FLEX10K soft compatible
		CP	ACEX.Config_PG.Sp97_1
		LD	DE,ACEX.Config_ID.Sp97_1
		JR	Z,.INT_PLD
		;
		CP	ACEX.Config_PG.Sp97_2
		LD	DE,ACEX.Config_ID.Sp97_2
		JR	Z,.INT_PLD
		;
		CP	ACEX.Config_PG.Sp97_AY
		LD	DE,ACEX.Config_ID.Sp97_AY
		JR	Z,.INT_PLD
		SCF
		RET
		;
; B - ID рамблока с bitstream		
		;[x]
.INIT_ACEX:	LD	C,B
		LD	B,high BIOS.REINIT.HARD_RESET
		CALL	.PrepareResetSetUp
		LD	B,C
		CALL	.PrepareHardReset
		JR	C,.INIT_ACEX.ERROR
		LD	B,high BIOS.REINIT.HARD_RESET
		JR	.set_ret_addr
		
; 		DI
; 		IN	A,(SLOT3)		; сохраняем номер воткнутой страницы
; 		PUSH	AF
; 		LD	A,Spec_Page
; 		OUT	(SLOT3),A
; 		; проверяем размер блока с конфой и получаем страницы конфы
; 		LD	HL,Spec_Page.bitstream_pages
; 		LD	A,B
; 		AND	A
; 		JR	Z,.INIT_ACEX.ReloadConfFromROM
; 		;
; 		CALL	EMM.GetMemBlkPages
; 		LD	A,B
; 		JR	C,.INIT_ACEX.ERROR
; 		CP	BitStream_SizeInPages+1	; количество страниц в кэш для бистрима плюс одна
; 		JR	NC,.INIT_ACEX.ERROR
; 		LD	A,(Spec_Page.bitstream_pages)
; 		INC	A
; 		JR	Z,.INIT_ACEX.ERROR	
; 		;
; .INIT_ACEX.ReloadConfFromROM:
; 		; закидываем в Spec_Page прогу для заливки конфы
; 		LD	HL,.INIT_ACEX.PROGRAM
; 		LD	DE,Spec_Page.init_acex
; 		LD	BC,.INIT_ACEX.PROGRAM.Size
; 		LDIR
; 		; если ZF=0, то процедура сделает ресет с перезаливкой из BIOS, иначе из КЭШ
; 		CALL	Spec_Page.init_acex
; 		LD	B,high BIOS.REINIT.HARD_RESET
; 		POP	HL
; 		;
; 		;вход:	B - параметр функции BIOS REINIT
; 		;	H - Spec_Page.page_3
; .INIT_ACEX.ifSoftreset:
; 		; сохраняем воткнутые страницы в Spec_Page
; 		IN	A,(SLOT0)
; 		LD	E,A
; 		IN	A,(SLOT1)
; 		LD	D,A
; 		IN	A,(SLOT2)
; 		;POP	HL			; восстанавливаем номер воткнутой страницы
; 		LD	L,A
; 		LD	(Spec_Page.page_0),DE
; 		LD	(Spec_Page.page_2),HL
; 		;
; 		; достаём адрес возврата в вызывающую функцию и сохраняем в Spec_Page
; 		POP	DE
; 		LD	HL,RST_18_1.exit
; 		XOR	A
; 		SBC	HL,DE
; 		JR	NZ,.set_ret		; NZ - если вызов был по RST #18
; 		POP	DE			; если вызов был в ОЗУ по RST 8
; 		INC	A
; .set_ret:	LD	(Spec_Page.RET_addr),DE
; 		; A=0 - SYS_PORT.ON
; 		; A=1 - SYS_PORT.OFF
; 		LD	(Spec_Page.Reload_Version),A
; 		LD	(Spec_Page.Stack_Point),SP
; 		;
; 		LD	A,high BIOS.REINIT.HARD_RESET
; 		CP	B
; 		JR	NZ,.reinit
; 		; Устанавливаем ключи для HARD reset
; 		LD	HL,Spec_Page.flag_R
; 		LD	(HL),"R"
; 		INC	HL
; 		LD	(HL),"S"
; 		INC	HL
; 		LD	(HL),"T"
; 		;
; 		; .. ... ... .. 
; 		;LD	BC,BIOS.REINIT.HARD_RESET
; .reinit:	JP	REINIT
		;
.SetUpHardReset:
		LD	C,B
		LD	B,high BIOS.REINIT.HARD_RESET
		CALL	.PrepareResetSetUp
		LD	(Spec_Page.RET_addr),DE
		LD	A,#FF
		LD	(Spec_Page.Reload_Version),A
		LD	B,C
		CALL	.PrepareHardReset
		JR	.INIT_ACEX.ERROR	; нормальный выход в данном случае
		;
.ReturnSoftReset:
		CALL	.PrepareSoftReset
		CALL	.PrepareResetSetUp
		; достаём адрес возврата в вызывающую функцию и сохраняем в Spec_Page
.set_ret_addr:	POP	DE
		LD	HL,RST_18_1.exit
		XOR	A
		SBC	HL,DE
		JR	NZ,.set_ret		; NZ - если вызов был по RST #18
		POP	DE			; если вызов был в ОЗУ по RST 8
		INC	A
.set_ret:	LD	(Spec_Page.RET_addr),DE
		; A=0 - SYS_PORT.ON
		; A=1 - SYS_PORT.OFF
		LD	(Spec_Page.Reload_Version),A
		LD	(Spec_Page.Stack_Point),SP
		JP	REINIT
		;
.SetUpSoftReset:
		PUSH	DE
		CALL	.PrepareSoftReset
		CALL	.PrepareResetSetUp
		POP	DE
		LD	(Spec_Page.RET_addr),DE
		LD	A,#FF
		LD	(Spec_Page.Reload_Version),A
		LD	A,(Spec_Page.page_3)
		OUT	(SLOT3),A
		RET

		; DI
		; LD	A,ACEX.RET_PORT
		; LD	B,Spec_Page
		; CALL	SET_PORTS
		; ;
		; ; и так понятно что делает
		; IN	A,(SLOT3)					; сохраняем номер воткнутой страницы
		; LD	H,A
		; LD	A,Spec_Page
		; OUT	(SLOT3),A
		; ;
		; LD	B,high BIOS.REINIT.SOFT_RESET
		; JR	.INIT_ACEX.ifSoftreset
		;
		;;;
.INIT_ACEX.ERROR:
		LD	A,(Spec_Page.page_3)
		OUT	(SLOT3),A
		;SCF
		RET
;
;--[]
.ACC_OFF:	LD	BC,Port_All_Mode
		IN	A,(C)
		AND	Port_All_Mode.DEFAULT - Port_All_Mode.SPECTRUM_MODE_OFF
		OUT	(C),A
		RET
		;
.ACC_ON:	LD	BC,Port_All_Mode
		IN	A,(C)
		OR	1								; ACC_ON
		OUT	(C),A
		RET
;--[]
;
.INIT_ACEX.PROGRAM:
	DISP	Spec_Page.init_acex
		;
		SAFE_PORTY
		IN	A,(FastRAM.ON)
		; IN	A,(SLOT1)
		; LD	(.slot1_page),A
		;
		LD	A,#FE						; чтоб проверить, что вызывать после CALL NZ,.INIT_ACEX.PROGRAM.LOAD
		; тут ZF должен быть из вызывающей процедуры
		CALL	NZ,.INIT_ACEX.PROGRAM.LOAD			; если RAM_BLOCK ID не равен 0, то выполняется
		INC	A						; флаг ZF=0 грузим из ROM
		;
.INIT_ACEX.PROGRAM.SET_KEYS:
		LD	A,3
		OUT	(FastRAM.SLOT0),A				; Страница КЭШ = 3
		;
		LD	HL,.INIT_ACEX.Reload_String			; флаг перезагрузки из КЭШ-а
		JR	Z,.skip						; устанавливаем флаг перезагрузки из КЭШ-а
		INC	L						; затираем флаг перезагрузки из КЭШ-а
.skip:		LD	DE,ACEX.LOADER.String_Address-#C000
		LD	BC,#10
		LDIR

		LD	HL,#FFFF					; залить конфу только при первой перезагрузке
		;LD	HL,ACEX.LOADER.Reload_Flag			; заливать конфу при каждой перезагрузке
		LD	(ACEX.LOADER.Reload_Flag_Address-#C000),HL
		;
.INIT_ACEX.PROGRAM.END:
		XOR	A
		OUT	(FastRAM.SLOT0),A
		IN	A,(FastRAM.OFF)
; .slot1_page+1:	LD	A,0
		LD	A,(Spec_Page.page_1)
		OUT	(SLOT1),A
		RET
		;
		;
.INIT_ACEX.PROGRAM.LOAD:
		XOR	A						; страница КЭШ
		LD	HL,Spec_Page.bitstream_pages
		OUT	(FastRAM.SLOT0),A				; Страница КЭШ = 0
		INC	A
.INIT_ACEX.PROGRAM.load_loop:
		EX	AF,AF'
		 LD	A,(HL)
		 INC	HL
		 CP	#FF
		 RET	Z
		 OUT	(SLOT1),A					; страница с данными файла
		EX	AF,AF'
		;
		; перекидывание #3000 байтов в КЭШ(0) = #1000
		EXX
		 LD	HL,#4000					
		 LD	DE,#1000
		 LD	BC,#3000
		 LDIR
		 ; докидывание #1000 байтов в КЭШ(1) = #0000
		 ; HL = #7000
		 OUT	(FastRAM.SLOT0),A				; Страница КЭШ = 1
		 INC	A
		 ;
		 LD	D,C		; LD DE,0
		 LD	B,#10		; LD BC,#1000
		 LDIR
		EXX
		JR	.INIT_ACEX.PROGRAM.load_loop

	
.INIT_ACEX.Reload_String:
		DB	ACEX.RELOAD_STRING
	;
 ENT
.INIT_ACEX.PROGRAM.Size	EQU	$-.INIT_ACEX.PROGRAM
;--[]
.PrepareSoftReset:
		LD	A,ACEX.RET_PORT
		LD	B,Spec_Page
		CALL	SET_PORTS
		LD	B,high BIOS.REINIT.SOFT_RESET
		RET

.PrepareResetSetUp:
		DI
		; сохраняем воткнутые страницы в Spec_Page
		IN	A,(SLOT3)
		LD	H,A
		LD	A,Spec_Page
		OUT	(SLOT3),A	
		;
		IN	A,(SLOT2)
		LD	L,A
		LD	(Spec_Page.page_2),HL
		IN	A,(SLOT0)
		LD	(Spec_Page.page_0),A
		IN	A,(SLOT1)
		LD	(Spec_Page.page_1),A
		;
		LD	A,high BIOS.REINIT.HARD_RESET
		CP	B
		LD	HL,Spec_Page.flag_R
		JR	NZ,.kill_flag
		; Устанавливаем ключи для HARD reset
		LD	(HL),"R"
		INC	HL
.kill_flag:	LD	(HL),"S"
		INC	HL
		LD	(HL),"T"
		RET
		;

; B - ramblock bitstream
.PrepareHardReset:
		; проверяем размер блока с конфой и получаем страницы конфы
		LD	HL,Spec_Page.bitstream_pages
		LD	A,B
		AND	A
		JR	Z,.INIT_ACEX.ReloadConfFromROM
		;
		CALL	EMM.GetMemBlkPages
		RET	C			; ERROR
		LD	A,BitStream_SizeInPages	; количество страниц в кэш для бистрима
		CP	B
		RET	C			; ERROR
		LD	A,(Spec_Page.bitstream_pages)
		INC	A
		SCF
		RET	Z			; ERROR
		;
.INIT_ACEX.ReloadConfFromROM:
		; закидываем в Spec_Page прогу для заливки конфы
		LD	HL,.INIT_ACEX.PROGRAM
		LD	DE,Spec_Page.init_acex
		LD	BC,.INIT_ACEX.PROGRAM.Size
		LDIR
		; если ZF=0, то процедура сделает ресет с перезаливкой из BIOS, иначе из КЭШ
		JP	Spec_Page.init_acex
;--[]
;***************************************


;[x]
;--------------------------[;!TODO потестить]--------------------------;
; B - параметр сброса
; B = 1 - RESTART.
; B = 2 - Soft reset
; B = 3 - Hard reset
; B = 4 - Free memory except ZX pages
REINIT:		DEC	B
		JR	Z,.Restart      ; 1
		DEC	B
		JR	Z,.SoftReset    ; 2
		DEC     B
		JR	Z,.HardReset    ; 3
		DEC	B
		SCF
		RET	NZ
		;			; 4
.FreeNoZxMem:	DI
		LD	C,SLOT3
		IN	B,(C)
		LD	A,SYS_PAGE
		OUT	(C),A
		LD	(SYS_PAGE.SP_SAVE),SP
		LD	SP,SYS_PAGE.SYS_SP
		PUSH	BC
		; чистим буфер
		LD	HL,SYS_PAGE.SHARED_BUFFER_256b
		LD	DE,SYS_PAGE.SHARED_BUFFER_256b + 1
		LD	BC,255
		LD	(HL),0
		LDIR
		;
		LD	IX,SYS_PAGE.Block_IDs
		LD	H,high SYS_PAGE.RAM_TABLE
		LD	D,high SYS_PAGE.SHARED_BUFFER_256b
		LD	BC,2*256 + #FF					; 2 = vRAM и VROM ID's
		CALL	SAVE_CHAINS
		;
		CALL	EMM.InitMem
		;
		LD	HL,SYS_PAGE.SHARED_BUFFER_256b
		LD	DE,SYS_PAGE.RAM_TABLE
		CALL	RESTORE_CHAINS
		; CF=0
		POP	BC
		LD	SP,(SYS_PAGE.SP_SAVE)
		OUT	(C),B
		RET

;[x]
.Restart:	DI
		XOR	A
		LD      BC,#1FFD
		OUT     (C),A
		LD      B,#7F
		OUT     (C),A
		OUT     (RGADR),A
		OUT     (RGMOD),A
		OUT     (SLOT0),A
		; [ ] 16/09/24 free zx pages!
		 ;LD      A,5
		 ;OUT     (SLOT1),A
		 ;LD      A,2
		 ;OUT     (SLOT2),A
		 OUT	(SLOT2),A
		 DEC	A
		 OUT	(SLOT1),A
		;
		LD      A,DCP_PAGE
		OUT     (SLOT3),A
		JP	0						;Restart
;

;
.SoftReset:	DI
		LD A,#10
		LD BC,#1FFD
		OUT (C),A						; 8-я страница !!
		;
		LD A,RESET_PAGE
		OUT (SLOT3),A
		LD A,CNF_PORT.TURBO.OFF
		OUT (SYS_PORT.ROM),A
.loop2:		LD (#C000),A						; Soft RESET !!!
		JR .loop2
;

;[x]
.HardReset:
        DI
	LD	A,SYS_PORT.CNF_0
	OUT	(SYS_PORT.ROM),A
	;
	LD	A,Z84.REG.Misc_Ctrl
	OUT	(Z84.SYS.Control),A
	LD	A,%0000'0011		; CS1/CS0 enabled		
	OUT	(Z84.SYS.Data),A
	;
        LD      A,DCP_PAGE
        OUT     (SLOT1),A                                               ; set DCP page
        LD      A,ACEX.RESET
        LD      (#4400),A                                               ; open for WR
.loop:  LD      BC,#0100                                                ; цикл сброса
        OUT     (C),C
        LD      B,C
        OUT     (C),C
        JR      .loop                                                   ; полностью зациклить!
;
;----------------------------------------------------------------------;
; Вход:	 H - RAM_TABLE
;	 D - Buffer for RAM_TABLE
;	IX - указатель на последовательность из RAM BLOCK ID
;	 B - кол-во RAM BLOCK ID в последовательности
;	 C - #FF (чтоб LDI не ломало DJNZ счётчик)
SAVE_CHAINS:	LD	A,(IX)
		INC	IX
		OR	A
		LD	L,A
		CALL	NZ,COPY_CHAIN
		DJNZ	SAVE_CHAINS
		RET
; Вход:	 H - RAM_TABLE
;	 L - RAM BLOCK ID
;	 D - Buffer for RAM_TABLE
COPY_CHAIN:	LD	E,L
		LDI 
		DEC	L
		LD	L,(HL)
		INC	L
		RET	Z
		DEC	L
		JR	COPY_CHAIN
;--------------;
; Вход:	 HL - копия RAM_TABLE откуда копировать
;	 DE - RAM_TABLE
RESTORE_CHAINS:	XOR	A
.loop:		CP	(HL)
		JR	Z,.NoCopy
		LD	E,L
		LDI 
		DEC	L
.NoCopy:	INC	L
		JR	NZ,.loop
		RET
;----------------------------------------------------------------------;


;----------------------------------------------------------------------;
; старый вариант освобождения страниц спектрума через RAM BLK ID 1
;----------------------------------------------------------------------;
; 	JR      Z,.HardReset    ;3
; 	DEC     B
; .ReinitZXpages:                 ;4
;  	LD DE,RESERVED_PAGES	; таблица занятых системных страниц
; 	LD HL,SYS_PAGE.RAM_TABLE	; Адрес FAT ОЗУ.

;         LD C,SLOT3
;         IN B,(C)
;         LD A,SYS_PAGE
;         OUT (SLOT3),A
       
; 	LD A,(DE)
; .zxloop:
; 	CP #FF
; 	JR Z,.endzxloop
; 	INC DE
; 	LD L,A

;         LD A,(HL)
;         AND A
;         JR NZ,.errorzxloop

;         LD A,(DE)
; 	LD (HL),A
; 	JR .zxloop

; .errorzxloop:
;         DEC DE
;         LD HL,-RESERVED_PAGES-1
;         ADD HL,DE
;         JR NC,.errorzxloop_noChanges

;         DEC DE
;         LD H,high SYS_PAGE.RAM_TABLE
;         LD A,(DE)
; 	LD L,A
;         LD A,#FF
; 	LD (HL),A
; .errorzxloop_noChanges:
;         SCF
; .endzxloop:
;         OUT (C),B
;         RET

;----------------------------------------------------------------------;
;