ORG 6D00h ; +========================+ MUSadr EQU 5CB0h ; | Kод игры "Tiny Tetri$" | FGad EQU 5B00h ; | (C) 1995 Oleg N. Cher | FGrjad EQU 5B02h ; +========================+ ; Список программных переменных: ; (MUSadr) .. нач. адрес первой из шести мелодий; ; (NXTfig+1) .. тип фигуры, которая будет следующей; ; (NXTcol+1) .. цвет фигуры, которая будет следующей; ; (FIGtyp+1) .. тип текущей фигуры; ; (FIGarj+1) .. архив типа текущей фигуры; ; (FIGcol+1) .. цвет текущей фигуры; ; (FGad) .. экр.адр,по кот.будет выведена фигура; ; (FGrjad) .. архив экр.адреса для вывода фигуры; ; (tSPEED+1) .. кол-во циклов опроса клавиш в игре; ; (rotDir+1) .. направление вращения падающей фигуры; ; (FGdown+1) .. булево значение - упала уже фигура?; TTinit LD A,(23730) ; Запретить SUB 5 ; прерывание программы LD (23613),A ; по нажатию Ctrl+Break. LD HL,4000h ; Перенести LD DE,TTinit ; коды и картинку LD BC,1000h ; с экранной LDIR ; в рабочую память. FONT LD HL,3D00h ; Эта часть кода формирует LD DE,7D00h ; по адресу 7D00h LD B,62h ; новый шрифт - "курсив", curFNT PUSH BC ; которым собственно LD B,4 ; и будет выводиться fs4byt LD A,(HL) ; большинство текстов SRA A ; в игре. OR (HL) ; Шрифт генерируется LD (DE),A ; из стандартного INC HL ; по алгоритму: INC DE ; каждый байт DJNZ fs4byt ; нового шрифта LD B,4 ; получается из ls4byt LD A,(HL) ; соответствующего SLA A ; байта стандартного OR (HL) ; путём исполнения LD (DE),A ; команд INC HL ; ld a,old; sra a; or old INC DE ; (для первых 4-х байтов) DJNZ ls4byt ; и POP BC ; ld a,old; sla a; or old DJNZ curFNT ; (для остав. 4-х байтов). NXTfig LD A,4 ; Следующая фигура стаёт LD (FIGtyp+1),A ; текущей... -> (FIGtyp+1) LD (FIGarj+1),A ; -> (FIGarj+1). LD A,R ; Задумать следующую фигуру AND 7 ; (число от 1 до 7). JR NZ,fig ; В двух случаях из восьми LD A,4 ; это будет палочка. fig LD (NXTfig+1),A ; Присвоить -> (NXTfig+1). NXTcol LD A,111 ; Цвет следующей фигуры LD (FIGcol+1),A ; стаёт цветом текущей. LD A,(23672) ; Значение системного mod6 SUB 6 ; таймера JR NC,mod6 ; взять ADD A,6 ; по модулю 6. ADD A,A ; Цвет следующей ADD A,A ; фигуры ADD A,A ; будет вычислен ADD A,79 ; по формуле LD (NXTcol+1),A ; NXTcol=(timer mod 6)*8+79. LD HL,22586 ; Экранный адрес, где будет LD (FGrjad),HL ; выведена текущая фигура, LD (FGad),HL ; -> (FGrjad) -> (FGad). CALL FGplac ; Не завалился ли ещё игрок? JR Z,cont ; Если нет, продолжать. LD BC,5A87h ; Угрюмый рык; вернуть true. SOUND LD A,C ; Процедура SOUND производит LD (snd+1),A ; различного рода звуки. LD HL,0 ; Требует задания sou PUSH BC ; следующих параметров: LD DE,1 ; B - длительность звучания, PUSH HL ; C - измен.формы огибающей. CALL 03B5h ; Freq := 0; POP HL ; sou: Len := 1; snd LD BC,0Ah ; BEEP (Freq, Len); ADD HL,BC ; Freq := Freq + C; POP BC ; B--; DJNZ sou ; IF B THEN GOTO sou RET ; RETURN. cont CALL putFIG ; Вывести текущую фигуру. LD HL,22638 ; Очистить от остатков LD B,4 ; старой фигуры clrhi LD (HL),40h ; четыре позиции INC HL ; верхней строки DJNZ clrhi ; индикатора NEXT. LD HL,22670 ; Очистить от остатков LD B,4 ; старой фигуры clrlo LD (HL),40h ; четыре позиции INC HL ; нижней строки DJNZ clrlo ; индикатора NEXT. PUSH BC ; Положить на стек false. LD C,4 ; Показать nxt LD HL,(NXTfig+1); на индикаторе NEXT CALL AEL ; следующую фигуру, LD DE,22640 ; то есть вычислить ADD HL,DE ; экранные адреса LD A,(NXTcol+1) ; каждого её звена LD (HL),A ; и записать по ним DEC C ; цвет фигуры - значение JR NZ,nxt ; переменной (NXTcol+1). POP BC ; Снять со стека false RET ; и вернуть его программе. MELODY LD HL,(MUSadr) ; Процедура MELODY играет с ply LD A,(HL) ; помощью процедуры в ПЗУ INC HL ; одноголосую мелодию, LD (MUSadr),HL ; нач. адрес которой задан OR A ; в переменной MUSadr. RET Z ; MUSadr увеличивается PUSH AF ; с игрой каждой ноты CALL PLAY ; и на момент возврата POP AF ; указывает на следующую RRA ; мелодию. Формат музыки: RRA ; DEFB hbF2hbF1B RRA ; DEFB LEN1,FRQ1 RRA ; DEFB LEN2,FRQ2 CALL PLAY ; hbF1 - старший полубайт JR ply ; высоты нечётной ноты; PLAY AND 0Fh ; LEN1 - байт длительности LD E,(HL) ; нечётной ноты; INC HL ; FRQ1 - младший байт LD D,0 ; высоты нечётной ноты; PUSH HL ; hbF2 - старший полубайт LD L,(HL) ; высоты чётной ноты; LD H,A ; LEN2 - байт длительности CALL 03B5h ; чётной ноты; POP HL ; FRQ2 - младший байт INC HL ; высоты чётной ноты; RET ; DEFB 0 - конец музыки. M260W XOR A ; Процедура M260W реализует LD (FGdown+1),A ; опрос клавиш ^, v, <, >, LD (T1+1),A ; fire, обработку паузы. tSPEED LD B,4 ; Обнулить dial PUSH BC ; HALT ; Главный цикл диалога игры. HALT ; Повторить (tSPEED+1) раз. HALT ; Задержка на 3/50 сек. LD A,0DFh ; Если нажата клавиша 'P' IN A,(0FEh) ; (пауза в игре), AND 1 ; предпринять действия, JR NZ,npause ; приостанавливающие игру: LD BC,0AA0Fh ; произвести мягкий, CALL SOUND ; восходящий звук паузы; hitP LD A,0DFh ; на всякий случай IN A,(0FEh) ; дождаться отпускания AND 1 ; клавиши 'P' (вдруг игрок JR Z,hitP ; всё ещё держит её); gamma LD A,0FEh ; будем наигрывать LD HL,96h ; методом 'Wizard Lair' CALL 703Ah ; статичную гамму из ПЗУ XOR A ; до тех пор, пока IN A,(0FEh) ; игрок не прервёт паузу CPL ; нажатием любой клавиши; AND 1Fh ; произвести сочный, JR Z,gamma ; бодрый звук конца паузы. LD BC,0D008h ; Затем продолжить игру, CALL SOUND ; как ни в чём не бывало. npause XOR A ; Выполнить опрос клавиатуры IN A,(0FEh) ; на предмет содержания CPL ; нажатых клавиш: AND 1Fh ; если таковых не имеется, JR NZ,hit ; false -> (FIRE+1), LD (FIRE+1),A ; иначе hit CALL NZ,press ; обработать нажатия. POP BC ; Kонец главного цикла DJNZ dial ; диалога игры. RET ; Всё. press LD B,A ; FIGtyp LD A,1 ; LD (CI+1),A ; LD A,(T1+1) ; OR A ; RET NZ ; BIT 0,B ; Если нажат огонь, изменить JR Z,noFire ; направление вращения. LD A,2 ; Убрать с экрана CALL 1601h ; указатель, показывающий LD DE,ClrNxt ; в какую сторону можно LD BC,12 ; вращать падающую фигуру. CALL 203Ch ; Произвести тяжёлое LD BC,1E46h ; звуковое сопровождение CALL SOUND ; данной акции. EXX ; Положить PUSH HL ; на стек LD A,91 ; калькулятора CALL 2D28h ; X, LD A,144 ; Y, CALL 2D28h ; radius. LD A,7 ; Нарисовать окружность, CALL 2D28h ; снимая параметры CALL 232Dh ; со стека. rotDir LD C,0 ; Изменить направление LD A,2 ; вращения фигуры SUB C ; на противоположное: LD (rotDir+1),A ; 2-(rotDir+1) ->(rotDir+1). RDROP CALL fADp32 ; Если можно опустить CALL FGplac ; фигуру ниже, сделать это JR Z,putFIG ; и вывести её на новом месте, CALL fADm32 ; иначе просто: LD A,1 ; true -> (FGdown+1) LD (FGdown+1),A ; -> (T1+1) LD (T1+1),A ; и вывести на старом месте. putFIG LD C,4 ; Процедура putFIG выводит put CALL AELF1 ; на экран дисплея фигуру LD DE,(FGad) ; в текущем месте (FGad) ADD HL,DE ; цветом (FIGcol+1). FIGcol LD (HL),111 ; Также производится DEC C ; дублирование переменных JR NZ,put ; в архивы: тип фигуры LD A,(FIGtyp+1) ; (FIGtyp+1) -> (FIGarj+1), LD (FIGarj+1),A ; её адрес (FGad) -> (FGrjad). LD HL,(FGad) ; Это нужно для того, чтобы LD (FGrjad),HL ; легко восстановить тип RET ; и адрес, если понадобится. ClrNxt DEFB 22,3,10,' '; Это текстовая строка DEFB 22,4,10,' '; для очистки индикатора NEXT. fADp32 LD HL,(FGad) ; Экранный адрес, LD DE,32 ; по которому будет ADD HL,DE ; выведена фигура LD (FGad),HL ; увеличить на 32 RET ; (фигуру на строку ниже). fADm32 LD HL,(FGad) ; Экранный адрес, LD DE,0-32 ; по которому будет ADD HL,DE ; выведена фигура LD (FGad),HL ; уменьшить на 32 RET ; (фигуру на строку выше).