.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