DEVICE ZXSPECTRUM4096 ; модель с 4 метрами памяти MMU 0 e, 1 ; первая страница в банку 0 и проверка на границы OUTPUT './Build/DOOM2/d2_fram.bin' ; SND_READ_SECTORS EQU 4 /* ;------------[ПЕРЕДЕЛАТЬ!!!]------------ ;--------------------------------------- */ ORG #1000 Module__D2_FRAM__Start EQU $ ; TRACE: IN A,(SLOT1) LD (TRACE_RET_SLOT1),A IN A,(SLOT3) LD (TRACE_RET_SLOT3),A LD A,#50 OUT (SLOT3),A LD BC,#100 OUT (C),C ; МАСШТАБ 1:1 LD DE,(SCREEN_1) LD HL,(ANGLE_M) ADD HL,HL ; ADD HL,HL LD A,H AND #3F OR #40 BIT 6,H LD H,A RES 6,L LD A,(SKY_1) JR Z,NO_SKY_2 LD A,(SKY_2) NO_SKY_2: OUT (SLOT1),A LD A,0 ;????????? не нужно? LD C,80 SKY_LOOP_1: ACC_SetBlockSize LD B,0 ACC_CopyBlock LD B,(HL) ACC_SetBlockSize LD B,#80 ACC_Off XOR A OUT (RGADR),A ACC_CopyScreenBlock LD (DE),A ACC_Off INC DE INC DE OUT (RGADR),A ACC_CopyScreenBlock LD (DE),A ACC_Off DEC DE OUT (RGADR),A ACC_CopyScreenBlock LD (DE),A ACC_Off INC DE INC DE OUT (RGADR),A ACC_CopyScreenBlock LD (DE),A ACC_Off INC DE INC H BIT 7,H JR Z,NO_NEXT_SKY RES 7,H SET 6,H IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF LD A,(SKY_1) LD B,A IN A,(SLOT1) CP B LD A,B JR NZ,NO_SKY_2X LD A,(SKY_2) NO_SKY_2X: OUT (SLOT1),A NO_NEXT_SKY: DEC C JR NZ,SKY_LOOP_1 IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF ; EXX SCREEN_1 EQU $+1 LD DE,#C040 ; начало экрана LD C,0 ;!!!!!!!!!!!!!!!!!!!!!!!!!! EXX ; LD HL,0 ; начальный угол * 32 ANGLE_M EQU $-2 ; LD A,H RLCA RLCA AND 3 ADD A,TABLE_W/256 LD D,A ; текущий квадрант SET 6,H RES 7,H ; HL - на таблице!!! LD B,40 ; число лучей трассировки деленное на 8 TRACE_NEXT_: ; EXX LD HL,(PLACE_L) ; текущее положение в таблице INC HL LD A,(HL) LD (PLACE_L1),A LD (PLACE_L2),A EXX ; PLACE_L EQU $+1 LD A,(TABLE_TRACE+10) ; тонкое положение - положение в квадрате ; OUT (SLOT1),A LD (CONT_PAGE),A ; JR TRACE_LOOP TRACE_LOOP: LD A,#50 OUT (SLOT3),A XOR A OUT (RGADR),A REPT 16 LD E,(HL) ; первый и далее следующий кубик LD A,(DE) ; есть или нет? AND A JR NZ,TRACE_CONT ; если есть, рисовать!! INC L ENDR PURE_LINE: ; EXX ACC_SetBlockSize LD A,#80 ; пустая стенка ACC_Off ; LD (DE),A ; LINE-Z-bufer OUT (RGADR),A LD A,(COLOR_LO) ACC_FillScreenOneByte LD (DE),A ACC_Off LD A,#70 ; Z-bufer LD (DE),A EXX ; JR NEXT_ANGLE ; трассировка закончена, стены нет. TRACE_CONT: ; HL - таблица ; A - номер стенки ; EXX EX AF,AF' ;номер стенки PLACE_L1 EQU $+1 LD A,5 OUT (SLOT1),A ; следующее положение в таблице ; LD C,0 LD B,1 OUT (C),C ; МАСШТАБ 1:1 EXX ; SET 4,L LD A,(HL) ; номер линии ; EXX LD H,A ; LD L,0 LD L,C SET 6,H RES 7,H EX AF,AF' OUT (SLOT1),A ; стенка. стенка раскидана на 16 килобайт ACC_SetBlockSize LD A,#40 ; взять 64 байта ACC_CopyBlock LD A,(HL) ; взять немасштабированно! ACC_Off ; стенка в ОЗУ акселератора! LD A,5 PLACE_L2 EQU $-1 OUT (SLOT1),A ; следующее положение EXX ; RES 4,L LD A,(HL) ; A - высота ; LD A,80H ; EXX LD H,TABLE_X/256 LD L,A ; высота TABLE_X - таблица высот LD B,(HL) ; старшая часть коэфициента ; ld b,0 INC H LD L,(HL) ; младшая часть коэфициента/смещение в стенке ; LD C,0 OUT (C),L ; масштабирование ; OUTI ; B уменьшается сначала! BIT 7,A JR Z,HIGH_1 ; 64 точки, не на весь экран ; <64 точки, на весь экран XOR A OUT (RGADR),A ; с самого начала ACC_SetBlockSize LD (DE),A ; 256 байт И LINE-Z-bufer!!!! ACC_Off LD A,#58 OUT (SLOT3),A ACC_CopyScreenBlock LD (DE),A ; ФИГАКС всю линию!!! ACC_Off XOR A LD (DE),A ; LINE-Z-bufer!!!! EXX ; JR NEXT_ANGLE HIGH_1: ; A - высота, с которой рисуется стенка ACC_SetBlockSize LD (DE),A ; число точек потолка и пола! & LINE-Z-bufer ACC_Off NEG ; получить положение начала пола OUT (RGADR),A LD L,A LD A,#58 OUT (SLOT3),A ; LD A,#06 ; цвет пола ; LD A,#5F ; цвет пола серый ; LD A,#CF ; цвет пола синий LD A,#2F ; цвет пола темнокрасный COLOR_LO EQU $-1 ; ACC_FillScreenOneByte LD (DE),A ; рисовать пол ACC_Off ; LD A,11 ; цвет потолка ;COLOR_HI EQU $-1 ; ACC_FillScreenOneByte ; LD (DE),A ; рисовать потолок ; ACC_Off LD A,L NEG OUT (RGADR),A LD A,L ; IN A,(RGADR) ADD A,A ; NEG ; выводимый размер стенки ; стенка в акселераторе! ACC_SetBlockSize LD (DE),A ACC_CopyScreenBlock LD (DE),A ; положить стенку! ACC_Off EXX ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NEXT_ANGLE: EXX INC DE LD A,E AND 7 EXX JR NZ,NO_TEST DEC B JR Z,TRACE_END NO_TEST: ; LD A,0 CONT_PAGE EQU $-1 ; OUT (SLOT1),A LD A,L AND #E0 ADD A,32 LD L,A JP NZ,TRACE_LOOP ; CALL SOUND ; играть музыку на ковоксбластере!!! IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF INC H BIT 7,H JP Z,TRACE_LOOP PUSH HL PUSH BC ; LD A,#0F CORNER_1 EQU $-1 ; AND #0F RRCA RRCA LD C,A RRCA RRCA RRCA RRCA OR C AND #0F ; XOR 03H XOR KWADR_CONST LD C,A LD B,0 LD HL,TABLE_TRACE ADD HL,BC ADD HL,BC LD (PLACE_L),HL ; НОВОЕ тонкое положение POP BC POP HL INC D RES 2,D LD HL,#4000 JP TRACE_NEXT_ TRACE_END: ; LD A,0 TRACE_RET_SLOT3 EQU $-1 ; OUT (SLOT3),A ; LD A,5 TRACE_RET_SLOT1 EQU $-1 ; OUT (SLOT1),A LD A,0 OUT (RGADR),A RET ; ;*************************************** ; PRECALC_PLACE: LD HL,(ANGLE_A) LD A,L AND 0E0H LD L,A LD (ANGLE_M),HL LD A,(Y_COORD+1) AND 3 ; XOR 3 ; XOR C LD C,A LD A,(X_COORD+1) RLCA RLCA AND 0CH ; XOR 0CH XOR C XOR 0FH LD C,A BIT 7,H JR Z,NO_NEG XOR 0FH LD C,A NO_NEG: BIT 6,H JR Z,NO_CORN1 RRCA RRCA LD C,A RRCA RRCA RRCA RRCA OR C AND #0F KWADR_CONST EQU #03 ; #03/#0C XOR KWADR_CONST LD C,A NO_CORN1: LD (CORNER_1),A LD B,0 LD HL,TABLE_TRACE ADD HL,BC ADD HL,BC LD (PLACE_L),HL ; тонкое положение RET ; ;*************************************** ; SET_PICTURE: ; A - относительный номер страницы LD C,SLOT1 IN B,(C) PUSH BC LD C,SLOT3 IN B,(C) PUSH BC PUSH AF LD A,#50 OUT (C),A IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF ; ld bc,#0100 ; масштабирование - 1 OUT (C),B LD DE,(SCREEN_1) LD B,5 ; 5 СТРАНИЦ ACC_SetBlockSize LD A,0 ; по 256 байт ACC_Off OUT (RGADR),A POP AF PIC_LOOP: PUSH BC PUSH AF LD HL,TABLE_MAIN ADD A,L LD L,A LD A,(HL) OUT (SLOT1),A LD HL,#4000 LD B,64 LOOP_PG: ACC_CopyBlock LD A,(HL) ACC_CopyScreenBlock LD (DE),A ACC_Off INC DE INC H DJNZ LOOP_PG POP AF INC A POP BC IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF DJNZ PIC_LOOP POP BC OUT (C),B POP BC OUT (C),B RET NN_X: DB 0 ; ;*************************************** ; CALC_NEW_PLACE: LD HL,(ANGLE_A) LD BC,(A_SPEED) ADD HL,BC LD BC,(LF_) LD A,B LD B,C LD C,A INC BC LD C,0 ADD HL,BC ADD HL,BC ADD HL,BC ADD HL,BC LD (ANGLE_A),HL LD A,H ADD A,20+8 RRCA RRCA RRCA AND 1EH LD C,A LD B,0 LD HL,TAB_ANGLE2 ;TAB_SPEED EQU $-2 ADD HL,BC LD E,(HL) ; step to Y INC L LD D,(HL) ; step to X LD HL,(Y_COORD) PUSH HL LD BC,(Y_SPEED) ADD HL,BC LD BC,(UP_) INC BC LD C,0 LD A,B AND A JR Z,ZERO1 LD B,E DEC A ; BIT 7,E ; проверка на отрицательность шага JR Z,ZERO1 LD A,B NEG LD B,A ZERO1: ADD HL,BC LD (Y_COORD),HL ADD HL,BC LD BC,(Y_SPEED) ADD HL,BC PUSH DE CALL MAP_PLACE POP DE POP HL JR NC,CONT_MOVE1 LD (Y_COORD),HL LD HL,(Y_SPEED) LD A,H CPL LD H,A LD A,L CPL LD L,A INC HL LD (Y_SPEED),HL CONT_MOVE1: LD HL,(X_COORD) PUSH HL LD BC,(X_SPEED) ADD HL,BC LD BC,(UP_) INC BC LD C,0 LD A,B AND A JR Z,ZERO2 LD B,D DEC A ; BIT 7,D JR Z,ZERO2 LD A,B NEG LD B,A ZERO2: ADD HL,BC LD (X_COORD),HL ADD HL,BC LD BC,(X_SPEED) ADD HL,BC CALL MAP_PLACE POP HL JR NC,CONT_MOVE2 LD (X_COORD),HL LD HL,(X_SPEED) LD A,H CPL LD H,A LD A,L CPL LD L,A INC HL LD (X_SPEED),HL CONT_MOVE2: RET ; ;*************************************** ; WEAPON_OUT: IN A,(SLOT1) PUSH AF IN A,(SLOT3) PUSH AF ;-------------[нужно ли???]- ld bc,#0100 OUT (C),C ; МАСШТАБ 1:1 ;--------------------------- LD A,(PAGE_WEAPON) OUT (SLOT1),A LD A,#58 OUT (SLOT3),A WEAPON_SWITCH EQU $+1 LD HL,#4500 ; положение спрайта оружия в странице ; LD DE,(SCREEN_1) LD A,E ADD A,100 ; смешение спрайта оружия по горизонтали LD E,A ACC_SetBlockSize LD C,119 ; длина спрайта оружия ACC_Off ;-------------[нужно ли???]- LD A,#FF ; нижняя линия ;--------------------------- LD BC,#100 W_OUT_L: LD A,#44 SUB H OUT (RGADR),A ; ;------[оптимизировать?]---------------- OUT (C),C ; МАСШТАБ 1:1, начинать с 0 ACC_CopyBlock LD A,(HL) ACC_Off OUT (C),C ; МАСШТАБ 1:1, начинать с 0 ACC_CopyBlock LD (DE),A ACC_Off ;--------------------------------------- ; INC H BIT 7,H JR Z,W_OUT_L LD A,(WEAPON_SWITCH) XOR #80 LD (WEAPON_SWITCH),A POP AF OUT (SLOT3),A POP AF OUT (SLOT1),A RET ; ;*************************************** ; MAP_OUT: CALL MAP_PLACE IN A,(SLOT1) PUSH AF IN A,(SLOT3) PUSH AF LD A,(TABLE_WALL) OUT (SLOT1),A RES 4,H ; SET 5,H PUSH HL LD A,(HL) PUSH AF LD (HL),#F7 LD HL,#4000 LD DE,(SCREEN_1) LD A,E ADD A,8 LD E,A MAP_LOOP_2: LD A,#58 OUT (SLOT3),A LD BC,#0100 OUT (C),C ; МАСШТАБ 1:1 ; IF NORM_ACC LD B,16 LD A,184 MAP_LOOP_1: ACC_SetBlockSize LD C,0 ACC_CopyBlock LD C,(HL) ACC_SetBlockSize LD C,#40 ACC_Off INC H REPT 4 OUT (RGADR),A ACC_CopyBlock LD (DE),A ACC_Off INC A ENDR DJNZ MAP_LOOP_1 ; ELSE ; LD B,16 ; LD A,184 ; MAP_LOOP_1: ; ACC_SetBlockSize ; LD C,#40 ; ACC_CopyBlock ; LD C,(HL) ; ACC_Off ; OUT (RGADR),A ; ACC_CopyBlock ; LD (DE),A ; ACC_Off ; INC A ; LD L,64 ; ACC_CopyBlock ; LD C,(HL) ; ACC_Off ; OUT (RGADR),A ; ACC_CopyBlock ; LD (DE),A ; ACC_Off ; INC A ; LD L,64*2 ; ACC_CopyBlock ; LD C,(HL) ; ACC_Off ; OUT (RGADR),A ; ACC_CopyBlock ; LD (DE),A ; ACC_Off ; INC A ; LD L,64*3 ; ACC_CopyBlock ; LD C,(HL) ; ACC_Off ; OUT (RGADR),A ; ACC_CopyBlock ; LD (DE),A ; ACC_Off ; INC A ; INC H ; LD L,0 ; DJNZ MAP_LOOP_1 ; ENDIF LD BC,240 EX DE,HL ADD HL,BC EX DE,HL LD A,H LD H,#60 CP #50 JR Z,MAP_LOOP_2 LD A,0 OUT (RGADR),A POP AF POP HL LD (HL),A POP AF OUT (SLOT3),A POP AF OUT (SLOT1),A RET ;*************************************** ; WALL: ; IX+0 - страница стенки ; IX+1,2 - адрес стенки в странице ; IX+3 - положение по вертикали - задает масштаб ; IX+4,5 - положение по горизонтали ; IX+6,7 - reserved ; IX+8,9 - X-add-parameter (коэфициент масштабирования по Y) ; IX+10 - реальная ширина стенки ??? ; IX+11 - реальная высота стенки ??? IN A,(SLOT3) LD (SLOT3_RET1),A IN A,(SLOT1) LD (SLOT1_RET1),A IN A,(RGADR) LD (RGADR_RET1),A LD A,#58 OUT (SLOT3),A LD A,(IX+0) ; страница стенки OUT (SLOT1),A EXX LD C,0 ; порт масштаба LD H,TABLE_X/256 ; таблица высот и коэфициентов масштабирования LD L,(IX+3) ; положение по Y / определяет высоту LD A,(HL) ; масштаб - LOW AND 3 LD (X_ADD),A INC H LD A,(HL) ; масштаб - HIGH LD (X_ADD2),A DEC H LD A,L ADD A,A NEG ; ширина по горизонтали BIT 0,(IX+M_VAR3) JR Z,NO_DEL2 RRA AND #7F NO_DEL2: BIT 1,(IX+M_VAR3) JR Z,NO_DEL4 AND A RRA RRA AND #3F NO_DEL4: EXX LD B,A ; реальная ширина стенки??? ; LD B,(IX+10) ; ширина стенки LD C,0 ; X-start-LOW ; LD HL,(SCREEN_1) LD E,(IX+4) ; - адрес по горизонтали LD D,(IX+5) ; ADD HL,DE ; LD A,E ; AND A ; BIT 7,D ; JR Z,WALL_NO_SCF ; SCF ; EX AF,AF' ; спрятать в AF - параметр счетчика и флаг ; ; CF - стенка не дошла до края ; ; в A сколько линий до начала экрана ;WALL_NO_SCF: ; ; LD HL,140h ; AND A ; SBC HL,DE ; LD A,L ; в A - сколько линий осталось до конца экрана?? LD HL,(SCREEN_1) ADD HL,DE ; LD A,(IX+3) LD A,B RRA AND #7F ; разделили на 2 LD E,A ; SUB 128 ; LD E,A LD D,0 SBC HL,DE EX DE,HL LD H,(IX+2) ; старший адрес стенки LD L,(IX+1) LD A,#58 OUT (SLOT3),A WOLL_LOOP: XOR A OUT (RGADR),A LD A,D CP #C3 JR NC,NO_WRITE_ALL ; не выводить за экран и закончить CP #C0 JR C,NO_WRITE_LINE ; не выводить за экран LD A,(DE) ; Z-bufer!!! EXX CP L EXX JR C,NO_WRITE_LINE EXX LD B,1 OUT (C),C ; масштаб - 1 ACC_SetBlockSize LD B,#40 ; задать длину линии ACC_Off EXX ACC_CopyBlock LD A,(HL) ; взять линию стенки ACC_Off EXX ; L - высота -128..0..127 !!! LD B,(HL) INC H LD A,(HL) ; масштаб - HIGH OUT (C),A INC H LD A,L ADD A,A JR NC,NO_Z_A1 XOR A NO_Z_A1: NEG ACC_SetBlockSize LD (HL),A ; задать длину линии ACC_Off DEC H DEC H LD A,L EXX BIT 7,A JR Z,NO_Z_A XOR A NO_Z_A: OUT (RGADR),A ; задать порт Y ACC_CopyScreenBlock LD (DE),A ; вывести линию ACC_Off LD A,E AND #0F IF YesSound CALL Z,SOUND ; ELSE ; CALL Z,YesSoundZero ENDIF NO_WRITE_LINE: INC DE ; новое значение X LD A,C X_ADD2 equ $+1 ADD A,0 ; X-add-parameter 2 LD C,A X_ADD equ $+1 LD A,0 ; X-add-parameter ADC A,H LD H,A ; следующая линия WOLL DJNZ WOLL_LOOP NO_WRITE_ALL: ; RGADR_RET1 EQU $+1 LD A,0 OUT (RGADR),A SLOT3_RET1 EQU $+1 LD A,0 OUT (SLOT3),A SLOT1_RET1 EQU $+1 LD A,5 OUT (SLOT3),A RET ; ; ;*************************************** MAKE_MAP: ; HL - положение в текущей карте. ; делать все 4 квадранта PUSH HL LD DE,(LAST_HL) AND A SBC HL,DE LD A,H OR L JR NZ,CONT_MAKE POP HL LD (LAST_HL),HL RET LAST_HL: DW 0000 CONT_MAKE: POP HL LD (LAST_HL),HL IN A,(SLOT1) PUSH AF LD A,(TABLE_WALL) ; карта OUT (SLOT1),A LD DE,TABLE_W ; текущие карты PUSH HL LD C,16 MAP_L1: LD B,16 MAP_L2: LD A,(HL) LD (DE),A INC HL INC E DJNZ MAP_L2 LD A,#30 ADD A,L LD L,A LD A,H ADC A,0 LD H,A DEC C JR NZ,MAP_L1 INC D POP HL PUSH HL CALL SOUND LD C,16 MAP_L3: LD B,16 PUSH HL MAP_L4: LD A,(HL) LD (DE),A LD A,L ADD A,#40 LD L,A LD A,H ADC A,0 LD H,A INC E DJNZ MAP_L4 POP HL DEC HL DEC C JR NZ,MAP_L3 INC D POP HL PUSH HL IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF LD C,16 MAP_L5: LD B,16 MAP_L6: LD A,(HL) LD (DE),A DEC HL INC E DJNZ MAP_L6 LD A,L SUB 30H LD L,A LD A,H SBC A,0 LD H,A DEC C JR NZ,MAP_L5 INC D POP HL PUSH HL IF YesSound CALL SOUND ENDIF LD C,16 MAP_L7: LD B,16 PUSH HL MAP_L8: LD A,(HL) LD (DE),A LD A,L SUB 40H LD L,A LD A,H SBC A,0 LD H,A INC E DJNZ MAP_L8 POP HL INC HL DEC C JR NZ,MAP_L7 POP HL POP AF OUT (SLOT1),A RET MAP_PLACE: ; вычисление положения и проверка на ; наличие препятствий PUSH DE LD A,(X_COORD+1) LD E,A LD A,(Y_COORD+1) LD D,A CALL MAP_PLACE_X RES 5,H ; переключить карту на таблицу стенок POP DE RET MAP_PLACE_X: ; DE - Y:X -> HL карта, E - препятствие LD A,E RRCA RRCA AND #3F LD L,A LD A,D RRCA RRCA AND #3F RRCA RRCA LD H,A AND #C0 OR L LD L,A LD A,H AND #0F ; OR 50H OR #70 ; карта с препятствиями LD H,A ; HL - КАРТА IN A,(SLOT1) PUSH AF LD A,(TABLE_WALL) OUT (SLOT1),A LD A,(HL) LD E,A ; RES 5,H ; переключить карту на таблицу стенок AND A JR Z,CONT_MOVE POP AF OUT (SLOT1),A SCF RET CONT_MOVE: POP AF OUT (SLOT1),A AND A RET ;*************************************** ;SOUND_PG: DB #FF ;COV_ADR: DB 0 ;SND_P: DB #FF SND_A: DW #C000 IF YesSound SND_STOP: ; остановить музыку PUSH AF PUSH BC LD BC,CBL.COVOX_OUT LD A,#80 SND_OUT_S: OUT (C),A ; забить ковокс-бластер одним значением DJNZ SND_OUT_S LD A,#C9 ; забить возврат в программу играния музыки LD (MemPatch_SoundOnOff),A POP BC POP AF RET SND_CONTINUE: ; продолжить музыку PUSH AF PUSH BC LD A,0 ; забить NOP в программу играния музыки LD (MemPatch_SoundOnOff),A POP BC POP AF RET INIT_SOUND: ; инициализировать музыку SND_INIT: PUSH AF PUSH HL PUSH DE PUSH BC LD HL,0 LD (SND_C1),HL LD (SND_C2),HL ; LD A,0 ; LD (SND_P),A LD A,0 LD (MemPatch_SoundOnOff),A LD B,0 IN A,(SLOT3) LD E,A JR SND_INIT1 ENDIF SOUND: IF !YesSound ; PUSH AF ; CALL KBD_INT ; POP AF RET ENDIF ; IF YesSound MemPatch_SoundOnOff EQU $ NOP ; сюда вставляется команда RET для отключения звука и NOP для включения PUSH AF PUSH HL SND_MORE: CALL KBD_INT IN A,(#FE) ; XOR 0 ; covox адрес COV_ADR EQU $-1 ; AND #80 JP NZ,NO_LD_SND PUSH DE PUSH BC LD A,(COV_ADR) CPL LD B,A LD HL,(SND_A) LD C,CBL.COVOX_OUT LD D,16 IN A,(SLOT3) LD E,A MemPatch_D2_FRAM_SndPage EQU $+1 LD A,0 OUT (SLOT3),A L_DDX: OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI DEC D JR NZ,L_DDX LD (SND_A),HL LD A,H AND A JP NZ,NO_SNDP SND_INIT1: PUSH IX PUSH AF EX AF,AF' PUSH AF PUSH HL PUSH DE PUSH BC EXX PUSH HL PUSH DE PUSH BC AND A LD HL,(SND_C1) LD BC,SND_READ_SECTORS SBC HL,BC LD (SND_C1),HL LD HL,(SND_C2) LD C,B SBC HL,BC LD (SND_C2),HL JR NC,NO_NEW_COUNT ; CALL SWITCH_SND CALL CLEAR_COVOX LD HL,SND_SEC1 LD DE,SND_S1 LD BC,8 LDIR AND A LD HL,(SND_C1) LD BC,SND_READ_SECTORS SBC HL,BC LD (SND_C1),HL LD HL,(SND_C2) LD BC,0 SBC HL,BC LD (SND_C2),HL ;_------[Чтение секторов с диска]------- NO_NEW_COUNT: LD HL,-SND_READ_SECTORS*512 ; буфер для данных LD A,0 ; страница буфера, если адрес в окне #C000 LD DE,(SND_S1) ; абсолютный номер сектора Младшая часть LD IX,(SND_S2) ; абсолютный номер сектора Старшая часть LD B,SND_READ_SECTORS ; число читаемых секторов LD C,BIOS.HDD_READ ; функция чтения CALL HDD_FN ;--------------------------------------- LD HL,(SND_S1) LD BC,SND_READ_SECTORS ADD HL,BC LD (SND_S1),HL LD HL,(SND_S2) LD C,B ADC HL,BC LD (SND_S2),HL LD HL,-SND_READ_SECTORS*512 CALL EFFECTS POP BC POP DE POP HL EXX POP BC POP DE POP HL POP AF EX AF,AF' POP AF POP IX LD HL,-SND_READ_SECTORS*512 LD (SND_A),HL NO_SNDP: LD A,B CPL LD (COV_ADR),A LD A,E OUT (SLOT3),A ; CALL INTERUPT POP BC POP DE JP SND_MORE NO_LD_SND: POP HL POP AF RET ENDIF ; IF !YesSound YesSoundZero: PUSH AF PUSH HL CALL KBD_INT POP HL POP AF RET ENDIF EFFECTS: IF !YesSound RET ENDIF LD DE,(EFF_) LD A,D CP #C0 RET NC IN A,(SLOT2) EX AF,AF' LD A,(EFF_PAGE) OUT (SLOT2),A LD BC,SND_READ_SECTORS*512 EFF_LOOP: LD A,(DE) ADD A,(HL) RRA LD (HL),A INC HL INC DE DEC C JR NZ,EFF_LOOP DJNZ EFF_LOOP LD (EFF_),DE EX AF,AF' OUT (SLOT2),A RET ;*************************************** CLEAR_Z_BUFER: IN A,(SLOT3) PUSH AF LD A,#50 OUT (SLOT3),A LD A,0 OUT (RGADR),A LD DE,(SCREEN_1) ACC_SetBlockSize LD A,0 ACC_FillOneByte LD (DE),A INC D ACC_SetBlockSize LD B,#40 ACC_FillOneByte LD (DE),A ACC_Off POP AF OUT (SLOT3),A RET ;*************************************** FIRE_S: LD A,(FIRE_B) AND A JR NZ,FIRE_X LD A,1 LD (FIRE_CT),A RET ; FIRE_CT: DB 1 FIRE_B: DB 0 EFF_: DW #C000 ; FIRE_X: LD A, #80 LD (EFF_+1),A ; включить эффект CALL MONSTR_BFG_INS ; вставить монстра огня! LD A,4 LD (FIRE_CT),A XOR A LD (FIRE_B),A RET ;*************************************** KBD_INT: IN A,(Z84.SIO.Ch_A.Ctrl) BIT 0,A RET Z IN A,(Z84.SIO.Ch_A.Data) CP #E0 JR Z,KBD_INT CP #E1 JR Z,KBD_INT CP #F0 JR Z,.KBD_OFF CP 3 CALL Z,SAVE_PIC_PR PUSH AF LD A,(OFF_BYTE) AND A JR Z,.NO_LAST_KEY POP AF LD (LAST_KEY),A PUSH AF .NO_LAST_KEY: POP AF CP 20 ; CTRL JR Z,.EFF_ON CP 117 ; KEY_UP JR Z,.DIR_UP CP 114 ; KEY_DN JR Z,.DIR_DN CP 107 ; KEY_LF JR Z,.DIR_LF CP 116 ; KEY_RT JR Z,.DIR_RT JR .KBD_INT2 .KBD_OFF: XOR A LD (OFF_BYTE),A ; 0, если появилось отжимание JR KBD_INT .KBD_INT1: PUSH HL LD HL,0 LD (A_SPEED),HL LD (X_SPEED),HL LD (Y_SPEED),HL POP HL .KBD_INT2: LD A,#FF LD (OFF_BYTE),A JR KBD_INT .EFF_ON: LD A,(OFF_BYTE) LD (FIRE_B),A CALL FIRE_S JR .KBD_INT2 .DIR_UP: LD A,(OFF_BYTE) LD (UP_),A JR .KBD_INT1 .DIR_DN: LD A,(OFF_BYTE) LD (DN_),A JR .KBD_INT1 .DIR_LF: LD A,(OFF_BYTE) LD (LF_),A JR .KBD_INT1 .DIR_RT: LD A,(OFF_BYTE) LD (RT_),A JR .KBD_INT1 UP_: DB #00 DN_: DB #00 LF_: DB #00 RT_: DB #00 OFF_BYTE: DB #FF ; ;INCLUDE INTMOUSE.ASZ ; TAB_ANGLE: DB 0,1 ; 0 DB 1,1 ; 45 DB 1,1 ; 45 DB 1,0 ; 90 DB 1,0 ; 90 DB 1,-1 ; 135 DB 1,-1 ; 135 DB 0,-1 ; 180 DB 0,-1 ; 180 DB -1,-1 DB -1,-1 DB -1,0 DB -1,0 DB -1,1 DB -1,1 DB 0,1 ; 0 TAB_ANGLE2: DB 0,2 ; 0 DB 1,2 ; 22 DB 2,2 ; 45 DB 2,1 ; 67 DB 2,0 ; 90 DB 2,-1 ; 112 DB 2,-2 ; 135 DB 1,-2 ; 157 DB 0,-2 ; 180 DB -1,-2 DB -2,-2 DB -2,-1 DB -2,0 DB -2,1 DB -2,2 DB -1,2 ; 0 TAB_ANGLE3: DB 4,2 ; 67 DB 4,1 ; 67 DB 4,0 ; 90 DB 4,-1 ; 112 DB 4,-2 ; 135 DB 4,-3 ; 135 DB 4,-4 ; 135 DB 3,-4 ; 157 DB 2,-4 ; 157 DB 1,-4 ; 157 DB 0,-4 ; 180 DB -1,-4 DB -2,-4 DB -3,-4 DB -4,-4 DB -4,-3 DB -4,-2 DB -4,-1 DB -4,0 DB -4,1 DB -4,2 DB -4,3 DB -4,4 ; 0 DB -3,4 ; 0 DB -2,4 ; 0 DB -1,4 ; 0 DB 0,4 ; 0 DB 1,4 ; 0 DB 2,4 ; 22 DB 3,4 ; 45 DB 4,4 ; 45 DB 4,3 ; 45 MONSTR_ALL: LD HL,(ANGLE_M) RL L RL H RLA RL L RL H RLA RL L RL H RLA LD L,H AND 7 LD H,A LD (ANGLE_R),HL LD IX,MONSTR_TABLE MONSTR_LOOP: LD A,(IX+M_PAGE) AND A RET Z ; JP MONSTR_ALL1 LD A,(X_COORD+1) ; положение игрока SUB (IX+M_X+1) ; положение монстра ADD A,64 JR Z,NO_M_OUT BIT 7,A ; проверка на дальность JR NZ,NO_M_OUT ; не выводить SUB 64 NEG LD L,A LD A,(Y_COORD+1) ; положение игрока SUB (IX+M_Y+1) ; положение монстра ADD A,64 JR Z,NO_M_OUT BIT 7,A JR NZ,NO_M_OUT ; проверка на дальность SUB 64 NEG LD H,A ; H - Y, L - X OR L JR Z,NO_M_OUT ; проверка на 0 LD B,0 BIT 7,H JR Z,A_NO_ADD4 LD A,H ; поворот на 180 -X->X; -Y->Y NEG LD H,A LD A,L NEG LD L,A LD B,4 A_NO_ADD4: BIT 7,L JR Z,A_NO_ADD2 LD A,L ; поворот на 90 Y->X; -X->Y NEG LD L,H LD H,A INC B INC B A_NO_ADD2: ; B - информация о квадранте 0,2,4,6 ; L - X-координата ; H - Y-координата MONSTR_ALL1: LD A,L ADD A,A ADD A,A LD L,A ; HL - указатель на таблицу (4096 по 4b) ; HL - PAGE:(HL) данные ; для вывода на экран -> угол -> x-координата, ; высота/ширина SET 6,H IN A,(SLOT1) PUSH AF LD A,(PAGE_M_PLACE) OUT (SLOT1),A LD E,(HL) ; угол младший INC L LD D,(HL) ; угол старший INC L LD C,(HL) ; высота POP AF OUT (SLOT1),A LD A,D ADD A,B LD D,A ; добавить квадрант DEC C BIT 7,C JR Z,MONST_H1 LD C,0 ; монстр рядом MONST_H1: INC C LD (IX+M_HIGH),C ; положение по вертикали LD HL,(ANGLE_R) AND A EX DE,HL SBC HL,DE ; ADD HL,DE ; LD DE,512+160-512 ; LD D,2 ; LD E,160 ; ADD HL,DE LD A,H AND 7 LD H,A LD (IX+M_HOR),L ; угол LD (IX+M_HOR+1),H LD DE,128 ADD HL,DE LD DE,256+320 AND A SBC HL,DE ; проверка попадания монстра в угол зрения CALL C,WALL IF YesSound CALL SOUND ; ELSE ; CALL YesSoundZero ENDIF NO_M_OUT: call MONSTR_NEXT_P LD DE,MONSTR_D_LEN ADD IX,DE JP MONSTR_LOOP MONSTR_NEXT_P: BIT 7,(IX+M_VAR3) ; не меняюийся монстр (убитый) RET NZ LD A,(IX+M_VAR2) ; счетчик цикла AND 0Fh RLCA RLCA RLCA RLCA ADD A,(IX+M_VAR2) ; добавить младший байт к старшему LD (IX+M_VAR2),A AND 0F0h RET NZ ; вернуться, если не 0 ; JR NC,NO_ADD_MX BIT 6,(IX+M_VAR3) ; бит единичного показа цикла JP Z,SW_MONS_X CALL SW_MONS_X RET Z SET 7,(IX+M_VAR3) ; остановить переключение RET SW_MONS_X: LD A,(IX+M_X) ADD A,(IX+M_VX) LD (IX+M_X),A LD A,(IX+M_X+1) ADC A,(IX+M_VX+1) LD (IX+M_X+1),A LD A,(IX+M_Y) ADD A,(IX+M_VY) LD (IX+M_Y),A LD A,(IX+M_Y+1) ADC A,(IX+M_VY+1) LD (IX+M_Y+1),A LD A,(IX+M_X+1) LD E,A LD A,(IX+M_Y+1) LD D,A CALL MAP_PLACE_X ; проверить, нет ли препятствия ; если С - препятствие есть JR NC,CONT_MONS ; при встрече с препятствием BIT 3,(IX+M_VAR3) JR Z,CONT_MONS ; если 0, ничего не делать ; иначе - исчезновение монстра с ; выкидыванием из таблицы CALL MONSTR_DELET ; удалить монстра LD DE,-MONSTR_D_LEN ADD IX,DE ; переключиться на предыдущего XOR A ; и вернуться RET CONT_MONS: BIT 2,(IX+M_VAR3) ; переключение по старшему адресу JR Z,SW_MONS LD A,(IX+M_ADR+1) ; переключатель адреса ADD A,(IX+M_VAR4) ; сколько добавлять AND 3Fh OR 40h LD (IX+M_ADR+1),A CP 40h ; признак завершения цикла RET SW_MONS: LD A,(IX+M_ADR) ; переключатель адреса ADD A,40H LD (IX+M_ADR),A AND A ; признак завершения цикла ;NO_ADD_MX: RET SAVE_PIC_PR: PUSH AF PUSH IX PUSH HL PUSH DE PUSH BC LD A,(FLAG) AND A JR NZ,NO_SAVE LD A,#FF LD (FLAG),A CALL SAVE_PIC LD A,0 LD (FLAG),A NO_SAVE: POP BC POP DE POP HL POP IX POP AF RET SAVE_HL: DW 0 SAVE_P1: DW 0 SAVE_P2: DW 0 SAVE_RGA2: DB 0 SAVE_PIC: IN A,(RGMOD) AND 1 LD HL,0C040H JR NZ,SET_1X LD HL,0C180H SET_1X: LD IX,TABLE_PIC LD A,(IX) AND A RET Z LD DE,08436h SAVE_PIC_X: LD (SAVE_HL),HL ; Pic line IN A,(RGADR) LD (SAVE_RGA2),A LD C,SLOT2 IN B,(C) LD (SAVE_P1),BC LD C,SLOT3 IN B,(C) LD (SAVE_P2),BC LD A,#50 OUT (C),A ; Screen LD A,#FF OUT (RGADR),A ; Line 1 LD A,(IX) OUT (SLOT2),A NEXT_SV_LN: LD HL,(SAVE_HL) ; вспомнить линию LD B,160 LOOP_SV_PIC: LD A,(HL) LD (DE),A INC HL INC DE LD A,(HL) LD (DE),A INC HL INC DE bit 6,d JR Z,NO_NEXT_PAGE LD A,B LD BC,(SAVE_P1) OUT (C),B LD B,A INC IX LD A,(IX) OUT (SLOT2),A ; next page LD DE,8000h NO_NEXT_PAGE: DJNZ LOOP_SV_PIC ; CALL SOUND IN A,(RGADR) DEC A OUT (RGADR),A CP 0FFh JR NZ,NEXT_SV_LN LD BC,(SAVE_P2) OUT (C),B LD BC,(SAVE_P1) OUT (C),B LD A,(SAVE_RGA2) OUT (RGADR),A RET ;WALL_SET: ;*************************************** ; монстровая структура ; IX+0 - страница стенки ; IX+1,2 - адрес стенки в странице ; IX+3 - положение по вертикали - задает масштаб ; IX+4,5 - положение по горизонтали ; IX+6,7 - reserved ; IX+8,9 - X-add-parameter (коэфициент масштабирования по Y) ; IX+10 - реальная ширина стенки ??? ; IX+11 - реальная высота стенки ??? ; IX+12 - координата X ; IX+14 - координата Y ; IX+16 - скорость X ; IX+18 - скорость Y ; IX+20 - тип монстра ; IX+22 - переменные монстра /* SSS2: ENT ;.DEPHASE ;*************************************** ; DS 86F0H-$ ; DS 7F0H-$ ; db 'flc C',0,80h,0,80H,80H,2,1 DS #A000-$ incbin "table.bin" */ ; ENT ASSERT $ < #1FFF, Relocate table "TABLE_W"!!! D2_fram_END EQU $ ; OUTEND ; DISPLAY "d2_fram.bin starts - ",/H,TRACE DISPLAY "d2_fram.bin ends - ",/H,D2_fram_END DISPLAY "Dd2_fram.bin size - ",/H,D2_fram_END-TRACE ;