
        .Z80
        ASEG
	.RADIX 10
	ORG 100H

	DB 'EX'
	DB 45H		; RESERV
	DB 0		; MY VERSION
	DW 200H,0       ; START CODE IN FILE
	DW 0		; LEN START LOAD DATA
	DW 0,0,0	; RESERV
	DW 8100H	; ADRESS IN MEM
	DW 8100H	; START ADRESS
	DW 0BFFEH	; STACK ADRESS
	DS 490

	.PHASE 8100h

	INCLUDE SPRINT00.ASZ

START:

	DI

	LD A,CNF_0
	OUT (SYS_PORT_OFF),A

	LD C,0A6h		; установка палитры
	LD A,1
	LD B,1
	RST 8h

	LD C,0A6h
	LD A,0
	LD B,1
	RST 8h

	LD C,0A6h
	LD A,2
	LD B,1
	RST 8h

	LD C,0A6h
	LD A,3
	LD B,1
	RST 8h

	LD A,CNF_3
	OUT (SYS_PORT_OFF),A

	LD A,3		; установка внутр.портов Z84C15 для перезагрузки
	OUT (0EEh),A
	LD A,3
	OUT (0EFh),A	; CASH & ROM

;	LD A,(IX+2)	; флаг (NOT USE!)
;	LD (FLAG),A

	IN A,(PAGE1)
	LD (PG5+1),A

	CALL READ_FROM_FILE	; читать прошивку из файла
				; память зверски не выделена!
				; чтение прямо в страницы 1C..1F
	LD DE,RELOAD_RET
	CALL SET_RETURN		; установка данных для возврата

	IN A,(0FBh)		; CASH_on

	CALL SET_ACEX_DATA	; перегрузка данных ACEX в FAST-RAM

	IN A,(07Bh)		; CASH_off

PG5:	LD A,5			; возврат страницы 1
	OUT (PAGE1),A

;************************************************

RESET:

	DI

	IN A,(PAGE1)	; открытие порта сброса
	PUSH AF
	LD A,40h
	OUT (PAGE1),A	; set DCP page
	LD A,2Eh
	LD (04400h),A	; open for WR
	LD (04600h),A	; open for RD
	POP AF
	OUT (PAGE1),A	; Close PAGE1

RESET_LOOP:		; цикл сброса
	LD BC,100h
	OUT (C),C
	LD BC,000h
	OUT (C),C
	JR RESET_LOOP	; полностью зациклить!

	DI		; пылеуловитель
	HALT

;*************************************************
SET_ACEX_DATA:

	DI
	LD BC,1FFDh
	XOR A
	OUT (C),A		; отключить RAM-0

	LD A,4
	OUT (SYS_PORT_ON),A	; DCP-PAGE 0

	LD A,0
	OUT (5Ch),A

	LD A,1Ch
	OUT (PAGE1),A           ; страница с данными файла

	LD HL,04100h            ; перекидывание данных в КЭШ
	LD DE,01000h
	LD BC,03000h
	LDIR

	LD A,1
	OUT (5Ch),A

	LD DE,00000h

	LD BC,0F00h
	LDIR

	IN A,(PAGE1)
	INC A
	OUT (PAGE1),A
	LD HL,4000h

	LD BC,3100h
	LDIR

	LD A,2
	OUT (5Ch),A		; Страница КЭШ = 2

	LD DE,00000h

	LD BC,0F00h
	LDIR

	IN A,(PAGE1)
	INC A
	OUT (PAGE1),A
	LD HL,4000h

	LD BC,3100h
	LDIR

	LD A,3
	OUT (05Ch),A		; Страница КЭШ = 3

	LD DE,00000h

	LD BC,0F00h
	LDIR

	IN A,(PAGE1)
	INC A
	OUT (PAGE1),A
	LD HL,4000h

	LD BC,3100h
	LDIR

	LD HL,STRING		; флаг перезагрузки из КЭШ-а
	LD DE,03EF0h

	LD BC,10h
	LDIR

	LD A,0FFh
	LD (03EE0h),A		; no multiple ! перезагрузка только одна

	LD A,(FLAG)		; если тут M
	CP "M"			; то перегружаться будет до потери пульса
				; НЕ ИСПОЛЬЗОВАТЬ!!!

	RET NZ

	LD (03EE0h),A		; multiple !

	RET

;*******************************

FLAG:	DB 0

STRING:	DB "ACEX_30K_LOADING"	; флаг перезагрузки

;*******************************

READ_FROM_FILE:			; читать файл прошивки =64k

	LD A,1
	LD HL,ROM_FILE
	LD C,11h
	RST 10h
	DI
	JP C,ERROR_FILE1
	LD (FILE_HANDLE),A

	IN A,(PAGE3)
	PUSH AF
	LD A,1Ch
	OUT (PAGE3),A

LOOP_READ:
	LD A,(FILE_HANDLE)
	LD HL,0C000h
	LD DE,4000h
	LD C,13h
	RST 10h
	DI
	JP C,ERROR_FILE

	AND A
	LD HL,4000h
	SBC HL,DE
	JP NZ,ERROR_FILE

	IN A,(PAGE3)
	INC A
	OUT (PAGE3),A
	CP 20h
	JR NZ,LOOP_READ

	LD A,(FILE_HANDLE)
	LD C,12h
	RST 10h
	DI
	JP C,ERROR_FILE
	POP AF
	OUT (PAGE3),A
	RET

ERROR_FILE:
	POP AF
	OUT (PAGE3),A
ERROR_FILE1:

	LD A,(FILE_HANDLE)	; закрыть, если был открыт
	AND A
	JR Z,NO_CLOSE
	LD C,12h
	RST 10h

NO_CLOSE:

	LD HL,ERROR_MSG
	LD C,5Ch
	RST 10h
	DI

	LD C,41h
	LD B,0
	RST 10h

	RET

	DI
	HALT

FILE_HANDLE:	db 0

ERROR_MSG:	db "File ERROR!",13,10,0

ROM_FILE:	db "GAME_00.ACX",0,0,0,0,0

;*************************************************

SET_RETURN:		; программа для установки
			; возврата после перезагрузки
;	LD DE,RELOAD_RET	; АДРЕС ВОЗВРАТА

	DI

	IN A,(PAGE3)
	LD (APG3+1),A

	LD A,41h
	OUT (PAGE3),A	; открыть спец-страницу

	LD (0FFF4h),DE	; адрес программы перезапуска

	LD A,"Z"
	LD (0FFFEh),A
	LD A,"X"
	LD (0FFFFh),A	; флаг перезапуска


	IN A,(PAGE0)	; сохранять страницы
	LD (0FFF0h),A	; DOS-PAGE
	IN A,(PAGE1)
	LD (0FFF1h),A	;
	IN A,(PAGE2)
	LD (0FFF2h),A	; программы для возврата???
	IN A,(PAGE3)
	LD (0FFF3h),A	;

	LD A,(APG3+1)
	OUT (PAGE3),A

	RET

;**************************************************************

RELOAD_RET:	; место, куда произведен возврат после перезагрузки
		; новой прошивки

	DI
	LD SP,0BFF0h
	LD A,CNF_0	; конфигурация и отключение ПЗУ
	OUT (SYS_PORT_OFF),A

	LD A,(0FFF0h)	; SET PAGE DOS
	OUT (PAGE0),A

APG3:	LD A,41h	; возврат старой страницы PAGE3
	OUT (PAGE3),A

;*****************************************************************
; вызов основной программы для работы с новой прошивкой
; работают все фунции DOS/BIOS, кроме функций экрана

	CALL MAIN_PROGRAMM

;*****************************************************************
; возврат в старую программу (RESET!)

	LD DE,RELOAD_RET2
	CALL SET_RETURN		; установка данных для возврата

	JP RESET

RELOAD_RET2:		; сюда должно бы выходить после возврата прошивки,
			; но пока не выходит

	DI
	LD SP,0BFF0h
	LD A,CNF_0	; конфигурация и отключение ПЗУ
	OUT (SYS_PORT_OFF),A

	LD A,(0FFF0h)	; SET PAGE DOS
	OUT (PAGE0),A

	LD A,(APG3+1)
	OUT (PAGE3),A

	LD C,41h	; RET TO DOS
	LD B,0
	RST 10h

	RET

;*****************************************************************
;
; Формат режима знакоместа
; Адрес тот же
;
;	Байт 0
;		bit 7..6 - номер палитры
;		bit 5 - графика/текст, должно быть 0 (текста нет)
;		bit 4 - режим 640/320 точек в линии
;		bit 3 - резерв - должны быть 0
;		bit 2 - разрешение смещения сетки
;		bit 1..0 - 2 старших бита координаты X
;
;	Байт 1	8 младших бит координаты X
;
;	Байт 2  координата Y
;
;	Байт 3  смещение сетки координат 
;		bit 3..0 - смещение по X
;		bit 7..4 - смещение по Y
;
;	Квадратик графики 8x8 выводится из виртуального экрана 1024x256
;		в соответствии с координатами верхнего левого
;		угла знакоместа, заданного в байтах режима
;
;	Смещение сетки задается третьим байтом режима экрана
;	Действует только, сопровождаемый единицей 
;	в бите 2 нулевого байта режима
;	Если бит 2 не был установлен, то смещение 
;	ОСТАЕТСЯ ТЕМ, ЧТО БЫЛО УСТАНОВЛЕНО РАНЕЕ
;	Действие байта заданного в знакоместе включается на следующем 
;	знакоместе
;	
;
;*****************************************************************

MAIN_PROGRAMM:

	IN A,(PAGE3)	; сохранить порты
	PUSH AF
	IN A,(PORT_Y)
	PUSH AF

	LD A,50h
	OUT (PAGE3),A	; экран в PAGE3

	LD A,0		; координата Y
	LD DE,6180h	; координата X плюс режим

	CALL CLEAR_SH	; очистка 4-го байта режима экрана

	CALL MAIN_SCROLL; задание нового граф.режима

	CALL PIC_SET	; прорисовка картинки (сетка)

	LD A,0		; координата Y
	LD DE,6180h	; координата X плюс режим
	LD BC,100	; число фреймов до выхода C*256
LOOP_SCR:
	PUSH AF
	PUSH DE
	PUSH BC

	CALL MAIN_SCROLL2	; новый скроллинг

	POP BC
	POP DE

	LD A,1		; меняем координату X
ADD_PAR2 EQU $-1
	ADD A,E
	LD E,A

	CP 0FFh
	JR NZ,NO_X1
	LD A,-1
	LD (ADD_PAR2),A
NO_X1:
	CP 0
	JR NZ,NO_X2
	LD A,1
	LD (ADD_PAR2),A
NO_X2:


	POP AF
	ADD A,1		; меняем координату Y
ADD_PAR1 EQU $-1

	PUSH AF

	CP 0F0h
	JR NZ,NO_X3
	LD A,-1
	LD (ADD_PAR1),A
NO_X3:
	CP 0
	JR NZ,NO_X4
	LD A,1
	LD (ADD_PAR1),A
NO_X4:

	LD A,7
	OUT (0FEh),A	; бордерная указка

	EI
	HALT

	LD A,0
	OUT (0FEh),A

	POP AF

	DJNZ LOOP_SCR
	DEC C
	JR NZ,LOOP_SCR

	POP AF		; восстановить порты
	OUT (PORT_Y),A
	POP AF
	OUT (PAGE3),A

	RET

;******************************************

MAIN_SCROLL2:
	DI

	IN A,(PORT_Y)
	PUSH AF


	LD HL,0C310h	; начиная с 4-й строки сверху
LOOP_SC1:
	LD A,5		; начинаем с N-го знакоместа режима
			; LD A,N*2-1
			; смещение в нулевом знакоместе
			; задано как ноль и может быть 
			; смещено как 56-е знакоместо, 
			; установкой смещения в 55-м
			; 

	OUT (PORT_Y),A

	LD A,(HL)
	OR 04h
	LD (HL),A	; установка бита 2 для включения смещения

	INC L
	INC L
	INC L
	LD A,(COUNT1)	                    
	LD (HL),A	; установка смещения

	INC L

	LD A,L
	CP 70h		; заканчиваем на 28-й строке
	JR NZ,LOOP_SC1


	LD HL,0C310h	; начиная с 4-й строки
LOOP_SC2:

	LD A,75		; на 38-м знакоместе
	OUT (PORT_Y),A

	LD A,(HL)
	OR 04h
	LD (HL),A	; устанавливаем новое смещение

	INC L
	INC L
	INC L
	LD (HL),88h	; со значением 8 пикселей по гор-ли
			; и 8 по вертикали
			; на постоянно
	INC L

	LD A,L
	CP 78h		; заканчиваем на 30-й строке
			; (две лишних строки, что бы 
			; сработали байты в смещенном по 
			; вертикали знакоместе)
	JR NZ,LOOP_SC2

	POP AF
	OUT (PORT_Y),A


	LD A,(COUNT2)	; "плавное" изменение счетчика для демонстрации
	ADD A,40h	; смещения
	LD (COUNT2),A
	JR NC,no_add1
	LD A,(COUNT1)
	ADD A,11h
	AND 77h
	LD (COUNT1),A
no_add1:

	RET

COUNT1:	db 0
COUNT2:	db 0

;******************************************************

CLEAR_SH:		; забиваются нулями все 3-и байты режима
	IN A,(PORT_Y)   ; на всем экране (в том числе бордере и бланке!)
	PUSH AF         ; акселератором

	XOR A
	OUT (PORT_Y),A
	LD HL,0C303h	                                        


CLEAR_LOOP:
	DI
	LD D,D
	LD A,0
	LD E,E
	LD (HL),A
	LD B,B
	EI

	INC L
	INC L
	INC L
	INC L

	LD A,L
	CP 0B3h
	JR NZ,CLEAR_LOOP

	POP AF
	OUT (PORT_Y),A
	RET

;*********************************************

PIC_SET:			; рисуется сетка
				; и квадратики
	IN A,(PORT_Y)
	PUSH AF

	DI

	LD D,D
	LD A,8
	LD B,B

	LD HL,0C000h
	LD C,0
LOOP_SC7:
	LD A,0
LOOP_SC6:
	LD B,8
LOOP_SC5:
	OUT (PORT_Y),A

	LD C,C
	LD (HL),C
	LD B,B

	INC A
	DJNZ LOOP_SC5

	INC C
	AND A
	JR NZ,LOOP_SC6

	LD A,L
	ADD A,8
	LD L,A
	LD A,H
	ADC A,0
	LD H,A
	CP 0C3h
	JR NZ,LOOP_SC7

	LD HL,0C000h
	LD C,0FFh
	LD D,D
	LD A,0
	LD B,B
LOOP_SC3:
	LD E,E
	LD (HL),C	; vertical lines
	LD B,B

	INC L
	INC L
	INC L
	INC L
	INC L
	INC L
	INC L

	LD E,E
	LD (HL),C	; vertical lines
	LD B,B

	INC HL

	LD A,H
	CP 0C3h
	JR NZ,LOOP_SC3

	LD A,0
	OUT (PORT_Y),A
	LD HL,0C000h

LOOP_SC4:
	OUT (PORT_Y),A

	LD C,C
	LD (HL),C	; horizontal line
	INC H
	LD (HL),C
	INC H
	LD (HL),C
	LD B,B

	ADD A,7
	OUT (PORT_Y),A

	LD C,C
	LD (HL),C	; horizontal line
	DEC H
	LD (HL),C
	DEC H
	LD (HL),C
	LD B,B

	INC A
	JR NZ,LOOP_SC4


	POP AF
	OUT (PORT_Y),A

	RET

;*********************************************
; установка режима экрана

MAIN_SCROLL:		; A - координата Y
	PUSH DE
	CALL Y_SET	; установить данные Y координаты для столбца
	POP DE
	CALL X_SET

	LD HL,0C302h	; адрес режима

	LD BC,Y_DATA	; адрес положений Y
	LD DE,X_DATA	; адрес режимов и координат X в строках

M_LOOP:
	PUSH HL

	LD A,1
	OUT (PORT_Y),A

	DI		; акселераторное заполнение режима экрана
			; для одной линии знакомест
	LD D,D
	LD A,79		; 40 знакомест (но через 1!!!)
	LD B,B

	LD A,(BC)	; взять заполнитель для Y координаты

	LD E,E          ; заполнять константой, вертикально
	LD (HL),A
	LD B,B
	IN A,(PORT_Y) 	; восстановление порта
	OUT (PORT_Y),A

	DEC L
	LD L,L
	LD A,(DE)	; взять линию режимов
	LD A,A
	LD (HL),A	; установить режим, вертикально
	LD B,B
	INC DE

	IN A,(PORT_Y) 	; восстановление порта
	OUT (PORT_Y),A

	DEC L
	LD L,L
	LD A,(DE)	; взять вторую линию режимов
	LD A,A
	LD (HL),A	; установить режим
	LD B,B
	DEC DE

	IN A,(PORT_Y) 	; восстановление порта
	OUT (PORT_Y),A

	POP HL
	INC L
	INC L
	INC L
	INC L		; следующая строка
	INC BC		; следующий Y
	LD A,L
	CP 82h
	JR NZ,M_LOOP	; повторять заполнение режима

	EI
	RET

;******************************************

Y_SET:			; A - Y_coord
	LD HL,Y_DATA	; адрес данных
	LD B,32
M_LP1:
	LD (HL),A	; Y координаты для всех квадратиков одной строки
	INC HL
	ADD A,8		; увеличить на 8 для следующей строки
	DJNZ M_LP1
	RET

;******************************************

X_SET:			; DE - X_coord + MODE
	LD HL,X_DATA	; адрес данных
	LD B,40
M_LPX1:
	LD (HL),E	; запомнить координату для квадратика
	INC HL
	LD (HL),D
	INC HL
	LD A,E
	ADD A,8		; увеличить на 8 для следующего
	LD E,A
	LD A,D
	ADC A,0
	LD D,A
	DJNZ M_LPX1	; повторять 40  раз

	RET

;******************************************

X_DATA:	DS 80 		; набор режимов одной строки
Y_DATA: DS 32		; данные Y (расчетные)


;*****************************************************************

	DSS 8700h,255

        .DEPHASE
        END


