device zxspectrum1024
 
 
 
        include "settings.ast"
 
MEM128=ATM;1 ;TODO автоопределение 48/128?
 
 
 
       if ATM
 
        include "../../_sdk/sys_h.asm"
 
       endif
 
 
 
STICKMOUSEXTOGRID=!ATM;1
 
 
 
FASTMAPPER=0 ;выброшено
 
CEILING=0 ;с потолком 8K лишних, только при FASTMAPPER=0
 
 
 
Nobjects=16+4 ;16 worms + 4 mines
 
 
 
       if ATM
 
STACK=0x4000
 
UVSCROLL_USETILES=0
 
UVSCROLL_USEBMP=0
 
       else
 
STACK=0x6000
 
       endif
 
 
 
FD      EQU 0x7ffd
 
COLOUR  EQU 7
 
TITLCOL EQU 71
 
 
 
PGMASK_  EQU #17
 
       if MEM128
 
MASK=0xf000 ;(MAPWID/2)*((256-8)/2+1[временно для mkmap]) = 46*125 = 5750
 
       else
 
MASK=0xb000 ;(MAPWID/2)*(TERRAINHGT/2+1[временно для mkmap]) = 46*79 = 3634 ;TODO в 128K тут будет потолок карты (80*93=7440)
 
       endif
 
       if !ATM
 
PGMAP=0x10
 
       endif
 
PGHICODE=0x14
 
PGLMN=0x16
 
;LMNS    EQU #C000 ;for mkmap
 
NLMN=15 ;число всех элементов фона в LMNS
 
NLMNONMAP=5 ;число элементов, которые ставим на карту
 
 
 
;USELMNBUF=0
 
;       if USELMNBUF
 
;LMNBUF=0x4000 ;во время построения карты
 
;LMNSZ=0x0800
 
;       else
 
       if !ATM
 
LMNGFX=0x4000 ;здесь будут лежать только те элементы, которые точно хотим ставить (тогда можем перестроить карту и в 48K)
 
LMNGFXSZ=0x0800 ;не более стольких байт, иначе число элементов будет урезано (а по умолчанию MLMNONMAP штук)
 
       endif
 
;       endif
 
 
 
MAPWID   EQU 93 ;нечётная! т.к. маска без 4 пикс слева и 4 пикс справа - там червей нельзя ставить ;TODO а если червь влетит в стену на левой границе карты? надо полную маску или при любой порче ландшафта крайний левый пикс маски формировать из 5 левых пикс, справа аналогично?
 
MASKWID  EQU MAPWID/2 ;округление вниз (x в маске считается для центра червя, x=0 соответствует x=4 в карте)
 
XWID=MAPWID*2 ;максимальное значение координаты xhigh
 
XWIDCHRBITS=1
 
XWIDCHR=1<<XWIDCHRBITS;2 ;одно знакоместо смещает xhigh вот на столько
 
INVISIBLEX=220 ;xhigh между 186 и 255, чтобы даже бомба не задела стоящих там трупов
 
 
 
MAPHGT  EQU 22*8 ;высота карты в пикселях
 
TERRAINHGT = MAPHGT-20 ;высота генерируемой карты в пикселях ;чтобы уместить червей и надписи сверху ;защита от вставания на идеально высокого червя - отсутствие маски для строк выше
 
MASKHGT EQU MAPHGT/2 ;высота маски в пикселях
 
BIGMAPHGT EQU 256 ;с небом
 
SKYHGT=BIGMAPHGT-MAPHGT ;высота неба
 
SKYMASKHGT=SKYHGT/2
 
 
 
       if ATM
 
RAMKAX=5
 
       else
 
RAMKAX=1
 
       endif
 
RAMKAHGT=16
 
RAMKAWID=14
 
SCRTOP=#4061 ;левый верхний угол активной зоны экрана
 
SCRHGT=17*8 ;высота активной зоны экрана в пикселях
 
       if ATM
 
SCRWID=40 ;ширина активной зоны экрана в знакоместах
 
TITLEY=200-32-8
 
       else
 
SCRWID=30 ;ширина активной зоны экрана в знакоместах
 
TITLEY=128
 
       endif
 
;SHADWD=SCRWID+2
 
;SHADHGT=SCRHGT;+14?
 
WATERHGT=32 ;высота воды в пикселях дополнительно к высоте карты с небом (BIGMAPHGT)
 
;для мыши:
 
waterYwin=BIGMAPHGT-SCRHGT ;waterYwin - это где высота воды 0
 
maxYwin=waterYwin+WATERHGT ;waterYwin+WATERHGT - это где высота воды WATERHGT
 
maxXwin=(MAPWID-SCRWID)*8
 
 
 
;DOPRSZ  EQU 56
 
;UPPRSZ  EQU SCRHGT-DOPRSZ
 
;DOPRSCR EQU -(DOPRSZ*4)+#4981
 
 
 
MAP=0xc000 ;там лежит карта в PGMAP
 
MAPDO   EQU -(MAPWID*SKYHGT)+MAP ;виртуальный адрес начала карты, включая небо
 
MASKDO  EQU -(MASKWID*(SKYMASKHGT-4))+MASK ;виртуальный адрес начала маски, включая небо ;маска - под ногами червя (высота червя=8, в маске =4)
 
 
 
MASKSZ  EQU MAPHGT/2*MASKWID
 
 
 
       if ATM
 
INTSTACK=0x3f80
 
       else
 
INTSTACK=0x5c00
 
       endif
 
;SPOILSTACK=INTSTACK+2 ;2 bytes for drawmap
 
 
 
       if ATM
 
uvscroll_scrbase=0x4000+(24*40)
 
uvscroll_pushbase=0x8000
 
uvscroll_callbase=0xc000
 
 
 
UVSCROLL_WID=1024
 
UVSCROLL_HGT=256;512;256
 
SKIPPGS=0;16 ;0 for UVSCROLL_HGT=256
 
UVSCROLL_SCRWID=SCRWID*8;320 ;8*(TILEMAPWID-2)
 
UVSCROLL_SCRHGT=136;200;192-16 ;(делится на 16!!!) ;8*(TILEMAPHGT-2) ;чтобы выводить всегда 12 метатайлов (3 блока по 8) по высоте
 
UVSCROLL_NPUSHES=UVSCROLL_WID/2/4/2 
 
UVSCROLL_SCRNPUSHES=UVSCROLL_SCRWID/2/4/2 
 
 
 
UVSCROLL_SCRSTART=uvscroll_scrbase+((UVSCROLL_SCRHGT-1)*40)
 
UVSCROLL_LINESTEP=-40
 
 
 
UVSCROLL_NCALLPGS=4
 
       
 
        macro SETPGPUSHBASE
 
        SETPG8000
 
        endm
 
 
 
        macro RECODEBYTE
 
        ld a,(de)
 
        ld ($+4),a
 
        ld a,(trecodebyteright)
 
        ld c,a
 
        dec de
 
        ld a,(de)
 
        dec de
 
        ld ($+4),a
 
        ld a,(trecodebyteleft)
 
        or c
 
        endm        
 
 
 
       endif
 
 
 
 
 
       macro SCRADDR x,y ;x in chr, y in pix
 
       if ATM
 
_=0x4000+((y)*40)+(x)
 
       else
 
_=0x4000+(((y)&7)<<8)+(((y)&0x38)<<2)+(((y)&0xc0)<<5)+(x)
 
       endif
 
       endm
 
 
 
        page 0
 
       if ATM
 
        org PROGSTART
 
       else
 
        ORG 0x6000
 
       endif
 
begin
 
       if ATM
 
        ld sp,STACK
 
       
 
        ld e,0+128 ;+128=keep
 
        OS_SETGFX ;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+SET FOCUS ;e=-1: disable gfx (out: e=old gfxmode)
 
 
 
        ld e,0
 
        OS_SETSCREEN
 
        ld e,0 ;color byte
 
        OS_CLS
 
        ld e,1
 
        OS_SETSCREEN
 
        ld e,0 ;color byte
 
        OS_CLS
 
 
 
        OS_NEWPAGE
 
        ld a,e
 
        ld (pg1),a
 
        OS_NEWPAGE
 
        ld a,e
 
        ld (pg2),a
 
 
 
        OS_GETMAINPAGES
 
;dehl=номера страниц в 0000,4000,8000,c000
 
        ld a,e
 
        LD (pgmain4000),A
 
        ld a,h
 
        LD (pgmain8000),A
 
        ld a,l
 
        ld (pgmask),a
 
        ld de,res_path
 
        OS_CHDIR
 
 
 
        call SetPgTexture8000
 
        ld de,fnpg1
 
        call loadfile8000
 
 
 
        call SetPgLmn8000
 
        ld de,fnpg2
 
        call loadfile8000
 
 
 
        call setpgsmain40008000
 
 
 
        ;call cls
 
        call swapimer
 
 
 
        call uvscroll_prepare
 
        jp GO
 
 
 
loadfile8000
 
        call openstream_file
 
        ld de,0x8000
 
        ld hl,0x4000
 
        call readstream_file
 
        jp closestream_file
 
        
 
;bgxyfilename
 
;        db "bg8-16d.bmp",0
 
 
 
swapimer
 
        di
 
        ld de,0x0038
 
        ld hl,oldimer
 
        ld bc,3
 
swapimer0
 
        ld a,(de)
 
        ldi ;[oldimer] -> [0x0038]
 
        dec hl
 
        ld (hl),a ;[0x0038] -> [oldimer]
 
        inc hl
 
        jp pe,swapimer0
 
        ei
 
        ret
 
oldimer
 
        jp on_int ;заменится на код из 0x0038
 
        jp 0x0038+3
 
 
 
on_int
 
;restore stack with de
 
        EX DE,HL
 
        EX (SP),HL ;de="hl", в стеке "de"
 
        LD (on_int_jp),HL
 
        LD (on_int_sp),SP
 
        LD SP,INTSTACK
 
        push af
 
        push bc
 
        push de ;"hl"
 
        exx
 
        ex af,af' ;'
 
        push af
 
        push bc
 
        push de
 
        push hl
 
        push ix
 
        push iy
 
 
 
curscrnum_int=$+1
 
        ld e,0
 
        OS_SETSCREEN
 
        
 
        call oldimer ;ei ;а что если выйдем поздно (по yield)? надо в конце обработчика убрать ei, но и это не поможет, т.к. yield сейчас с включенными прерываниями!!!
 
        
 
        ;GET_KEY
 
        ;ld a,c ;кнопка без учёта языка
 
        ;or a
 
        ;jr z,$+5
 
        ;ld (curkey),a
 
        
 
        ;OS_GETKEYMATRIX
 
        LD hl,curwater
 
        ld a,(hl)
 
        SUB -16
 
        LD (hl),A
 
        CALL MOUSE
 
        call TIME
 
        ld hl,timer
 
        inc (hl)
 
 
 
        pop iy
 
        pop ix
 
        pop hl
 
        pop de
 
        pop bc
 
        pop af
 
        ex af,af' ;'
 
        exx
 
        pop hl
 
        pop bc
 
        pop af        
 
on_int_sp=$+1
 
        ld sp,0
 
        pop de
 
        ei
 
on_int_jp=$+1
 
        jp 0
 
 
 
        align 256
 
       endif
 
_tables=$
 
        
 
       macro TABLE sz
 
        org _tables
 
_tables=_tables+sz
 
       endm
 
       macro ENDTABLE
 
       endm
 
       
 
        TABLE 0x200
 
FONT
 
        INCBIN "w64fnt.bin"   ;todo PG ;todo 256 байт (по 2 символа в байте)
 
        ENDTABLE
 
        TABLE 0x200
 
FONT88
 
        INCBIN "w88_fnt.bin" ;(пока адрес делится на 512) можно уменьшить (за счёт ненужных символов и высоты), но не сильно
 
        ENDTABLE
 
        TABLE 0x100
 
WATER
 
        INCBIN "water.bin"    ;todo PG
 
        ENDTABLE
 
        TABLE 0x100
 
DTNTAB ;32 байта по круглому адресу во время построения контура карты
 
MKMASKBUF EQU DTNTAB ;(MASKWID) ;во время построения карты
 
TPLACES EQU DTNTAB ;table of y's (per column) usable for worms ;во время построения карты
 
TXY     EQU TPLACES+256-(2*Nobjects) ;x,y всех червей (генерируется в mkmap) временно, потом используем WORMXY
 
;TABSIN  EQU DTNTAB ;пока топорный квадратичный (для перемещения курсора вокруг червя) во время хода игрока (но не логики)
 
;MAXWXY EQU 98 
 
;SPRITE,COORDS,SPEED
 
WORMXY  EQU DTNTAB ;во время игры
 
;TEAM,WORM,ENERGY,WEAPON,AIM,0
 
CUWORMS EQU DTNTAB+0x80
 
;TODO ещё буфер координат партиклов - или их сюда же? тогда не более 22 партиклов при 512 байт на два этих списка
 
        ENDTABLE
 
        TABLE 0x100
 
TITBUF ;todo очередь в PG
 
        ENDTABLE
 
        TABLE 0x400
 
Tshift ;,#400 ;во время игры (скролл 3,5)
 
grassbuf=Tshift ;for mkmap
 
grassbufsz=0x400 ;0x200 часто выдаёт "nowhere to worm"
 
LMNused=grassbuf ;(NLMN) ;for mkmap ;там помечается, какие номера элементов уже использовались
 
LMNlist=LMNused+256-NLMNONMAP ;список используемых
 
        ENDTABLE
 
        TABLE 0x100
 
TABROLL ;для логики (быстрая работа с маской)
 
        ENDTABLE
 
        TABLE 0x200
 
TMASKLN ;512 ;адреса строк маски = MASK+l*MASKWID ;почему-то не используется при построении карты
 
        ENDTABLE
 
       if !ATM
 
        TABLE 0x200
 
TMAPLN ;512 ;адреса строк карты = MAP+l*MAPWID ;во время построения карты и для drawinmap (и для FASTMAPPER)
 
        ENDTABLE
 
        TABLE 0x200
 
skysprlist=$+256-(42*6)+(4*6) ;80 строк по 6 байт (480 байт) с запасом сверху на 4 (не хватило на высоту червя) (внутри каждых 6 байт адресация inc l!)
 
        ENDTABLE
 
       endif
 
endtables=_tables
 
        ds endtables-$
 
GO
 
        ld sp,STACK
 
       if !ATM
 
        xor a
 
       out (0xfe),a
 
        ld hl,0x6000
 
        ld (hl),a
 
        inc l
 
        ld (hl),a
 
        inc l
 
        ld (hl),a ;was jp GO
 
       endif
 
        LD A,R
 
        ld l,a
 
       ;ld hl,0xcdc5;0x4dd5;0xf1b3
 
        ld (rndseed1),hl
 
        ld hl,(0x5c78)
 
       ;ld hl,0x765e;0x2734;0x6c1b
 
        ld (rndseed2),hl
 
     
 
      if !ATM
 
     ld a,PGLMN
 
     call OUTME
 
     ld a,(LMNS)
 
     ld (LMNSfirstbyte),a
 
      endif
 
 
 
       if ATM
 
;шрифт должен содержать по 2 копии каждой буквы
 
        ld hl,FONT
 
        ld bc,512 +255 ;+255 для цикла dec bc:inc b:djnz
 
mkdoublefont0
 
        ld a,(hl)
 
        rlca
 
        rlca
 
        rlca
 
        rlca
 
        or (hl)
 
        ld (hl),a
 
        inc hl
 
        dec bc
 
        inc b
 
        djnz mkdoublefont0
 
       endif
 
 
 
        LD HL,TITBUF
 
        LD (HL),0
 
;NACHALO
 
       if !ATM
 
        LD DE,MAPDO
 
        LD BC,MAPWID
 
        LD L,B;0
 
MKTBROW0 LD H,TMAPLN/256
 
        LD (HL),E
 
        INC H
 
        LD (HL),D
 
       ;BIT 6,D
 
       ;JR NZ,$+6
 
       ;LD (HL),#C0
 
       ;DEC H
 
       ;LD (HL),B
 
        EX DE,HL
 
        ADD HL,BC
 
        EX DE,HL
 
        INC L
 
        JR NZ,MKTBROW0
 
       endif
 
 
 
        LD L,0
 
        LD DE,MASKDO
 
        LD C,MASKWID
 
MKTBMSK LD H,TMASKLN/256
 
        LD (HL),E
 
        INC H
 
        LD (HL),D
 
        LD A,L ;l=y не в маске, а в карте, причём для головы, а не для ног!
 
       add a,8 ;координата для ног
 
       cp SKYHGT
 
       jr nc,MKTBMSKnoblank
 
       ; CP -8
 
       ; JR NC,$+6
 
       ;BIT 5,D
 
       ;JR NZ,$+7
 
         LD (HL),BLANK/256
 
         DEC H
 
         LD (HL),BLANK&0xff
 
MKTBMSKnoblank
 
        RRA 
 
        JR NC,$+5
 
         EX DE,HL
 
         ADD HL,BC ;двигаемся каждый второй раз (1 строка маски = 2 строки карты)
 
         EX DE,HL
 
        INC L
 
        JR NZ,MKTBMSK
 
 
 
        CALL INIMOUS ;портит ba00
 
        
 
       if ATM
 
        call SetPgMuzC000
 
        call muz
 
        ld hl,muz+5
 
        ld a,(pg1)
 
        OS_SETMUSIC
 
       else
 
        ld a,PGMAP
 
        call OUTME
 
        xor a
 
        ld (muz),a
 
        ld a,PGLMN
 
        call OUTME
 
        ld a,(muz)
 
        sub 0x21
 
        ld (muzpatch),a
 
        call z,muz
 
         CALL MAKINT
 
       endif
 
NACHALO
 
        LD HL,TLAND
 
        jr newmapgo
 
nowhere ;return here if "nowhere to worm"
 
        LD HL,MESWHE ;"nowhere to worm"
 
newmapgo
 
       ld sp,STACK
 
        CALL MTITLE
 
        call cls
 
        
 
       if ATM
 
        ;ld de,bgxyfilename
 
        ;call uvscroll_preparebmp;uvscroll_prepare
 
        ld de,pal;SUMMERPAL
 
        OS_SETPAL
 
        YIELD
 
        ld hl,panel16
 
        call DrawPanel
 
       else
 
        ld hl,panel
 
        call DrawPanel
 
       endif
 
        
 
        LD HL,(curdrawingtitle)
 
        CALL DrawTitle ;печать игрового сообщения
 
 
 
        CALL MKMAP
 
 
 
       if !ATM
 
        ld hl,Tshift
 
        ld de,0x0705
 
        call fixshift
 
        ld h,Tshift/256+2
 
        ld de,0x1f03
 
        call fixshift
 
       endif
 
 
 
;TODO сделать нормальный синус
 
;он тут кладётся, т.к. TABSIN затёрта во время генерации карты
 
        ;LD HL,TABSIN
 
        ;XOR A
 
        ;LD B,22
 
        ;LD (HL),A
 
        ;INC HL
 
        ;ADD A,B
 
        ;DJNZ $-3
 
 
 
        LD HL,MESHOM
 
        CALL MTITLE
 
        CALL DrawAttrField
 
        CALL ResetTime
 
        CALL DrawEnergyPanel ;печать панельки для энергии и ветра
 
 
 
        LD HL,TABROLL
 
        LD C,1
 
MKTRL   LD A,L
 
        AND 31
 
        JR NZ,$+4
 
         RRC C
 
        LD (HL),C
 
        INC L
 
        JR NZ,MKTRL 
 
 
 
       call ForcedDrawWormsInMap
 
gamemove
 
       call DrawWormsDataInMap
 
       ld a,STATE_MOVE
 
       ld (gamestate),a
 
genwind0
 
        call RND
 
        and 127
 
        cp 46+1+46
 
        jr nc,genwind0
 
        sub 46
 
        ld (wind),a
 
        
 
       if 1 ;TODO remove
 
genpowr0
 
        call RND
 
        and 127
 
        cp 119
 
        jr nc,genwind0
 
        ld (powr),a
 
       endif
 
 
 
       CALL DrawEnergy ;печать полосок энергии и ветра
 
gameloop
 
        LD HL,(MOUSEx)
 
        LD (MOUSEX),HL
 
        LD A,(MOUSEy)
 
        LD (MOUSEY),A
 
      ;HALT
 
    ;CALL MAPPER ;печать верха карты при one frame выводилке
 
       if !ATM
 
        LD A,PGMAP;16
 
        CALL OUTME
 
       endif
 
    call DrawWormsInMap ;TODO рисовать только сместившихся ;даже если напечатали ниже 0xc000, то всё равно сотрём сразу после отрисовки
 
       ld a,(gamestate)
 
       cp STATE_MOVE
 
       call z,DrawCrossInMap
 
     CALL DrawMap ;TODO не перерисовывать, если не сменился XY и не сместились объекты (прорисовать только строки под стрелкой для air strike)
 
     CALL DrawTime
 
       if !ATM
 
        LD A,PGMAP;16
 
        CALL OUTME
 
       endif
 
       ld a,(gamestate)
 
       cp STATE_MOVE
 
       call z,UnDrawCrossInMap
 
    call UnDrawWormsInMap ;TODO стирать только сместившихся
 
    call AnimMines
 
       ;LD A,-64
 
       ;LD HY,'TY4TOP
 
       ;CALL WORMS
 
       ;CALL CURSOR
 
oldtitletimer=$+1
 
        ld e,0
 
        ld a,(timer)
 
        ld (oldtitletimer),a
 
        sub e
 
        ld e,a
 
STCNTa=$+1
 
        LD A,1
 
        sub e;DEC A
 
        JR nc,STNOTIT
 
        xor a
 
curdrawingtitle=$+1
 
        LD HL,TITBUF
 
        CP (HL)
 
        CALL NZ,DrawTitle ;печать игрового сообщения
 
        JR $+5
 
STNOTIT LD (STCNTa),A
 
;DOPR    CALL 0 ;печать низа карты при one frame выводилке
 
;DOPRA   LD HL,0
 
;       LD (HL),#FD
 
;       INC HL
 
;       INC HL
 
;       LD (HL),#E1
 
;       CALL DrawWater
 
;      LD BC,999
 
;      LD D,B
 
;NOLDIR LDIR ;wait for turbo mode (недостаточно при 14 МГц)
 
       ;XOR A
 
       ;LD HY,'TY4LOW
 
       ;CALL CURSOR ;TODO для AIRSTRIKE (надо печатать на карте с запоминанием - прямо перед выводом карты, а потом восстанавливать)
 
 
 
       if ATM
 
        call changescrpg ;с этого момента (точнее, с прерывания) можем видеть, что нарисовали
 
        halt
 
        ;ld a,(curscrnum_int)
 
        ;ld e,a
 
        ;OS_SETSCREEN
 
       endif
 
 
 
;logic:
 
;delta timing
 
oldtimer=$+1
 
        ld e,0
 
waithalt
 
        ld a,(timer)
 
        ld (oldtimer),a
 
        sub e
 
         cp 1;2
 
       if ATM
 
        jp c,waithalt ;это не гарантия переключения экрана!!!
 
       else
 
        jp c,timeraction0q;waithalt ;чтобы линия обновления экрана была в рандомном месте
 
       endif
 
logicframesremained=$+1
 
       add a,0 ;0..LOGICSPEED-1
 
timeraction0
 
        ld (logicframesremained),a
 
        sub 1;2
 
        jr c,timeraction0q
 
        push af
 
 
 
       CALL WRMOVE
 
       ld a,(gamestate)
 
       cp STATE_MOVE
 
       call z,ControlCurWorm
 
       call WormsVsMines
 
       call StayingWormsVsMovingWorms ;столкновение летящего со стоящим
 
       
 
        pop af
 
        jr timeraction0
 
timeraction0q
 
       
 
       ld a,(gamestate)
 
       cp STATE_FLYCURWORM
 
       jr nz,noflycurworm ;не режим прыжка
 
       call CheckFlyingWorms
 
       jr nz,noflycurworm ;есть летящие
 
       call DrawCurWormData
 
       ld a,STATE_MOVE
 
       ld (gamestate),a
 
noflycurworm
 
       ld a,(gamestate)
 
       cp STATE_FLY
 
       jr nz,flyingok ;не режим взрыва
 
       call CheckFlyingWorms
 
       jr nz,flyingok ;есть летящие
 
;летящих червей больше нет, печатаем названия всех живых червей и переходим в режим смертей (а из него потом или в режим взрыва, или в режим перехода хода)
 
       ld a,STATE_DIE
 
       ld (gamestate),a
 
;TODO...
 
;TODO асинхронно от цикла графики  
 
        jp gamemove
 
flyingok
 
;
 
      
 
       ;CALL CLRTOP
 
       ;CALL UPPRU
 
       ;CALL 8020
 
       ;RET NC
 
       LD A,-3
 
       IN A,(-2)
 
       BIT 1,A
 
       CALL Z,unsetwms;SETWMS ;"S" - заново расставить червей
 
       LD A,#FB
 
       IN A,(-2)
 
       BIT 3,A
 
       JP Z,NACHALO ;"R" - заново сгенерировать карту
 
        JP gameloop
 
 
 
timer
 
        db 0 ;for logic
 
wind
 
        db 0 ;-46..46
 
powr
 
        db 0 ;0..118
 
gamestate
 
        db 0 ;STATE_MOVE=управление червём (в т.ч. ИИ), STATE_SHOT=анимация выстрела, STATE_BULLET=полёт снаряда, STATE_FLY=взрыв, STATE_DIE=смерти, STATE_NEXTMOVE=переход хода
 
STATE_MOVE=0
 
STATE_SHOT=1
 
STATE_BULLET=2
 
STATE_FLY=3 ;сняты надписи со всех червей
 
STATE_DIE=4
 
STATE_NEXTMOVE=5
 
STATE_FLYCURWORM=6 ;прыжок/падение во время хода, снята надпись только с текущего червя
 
 
 
       if !ATM
 
fixshift
 
fixshift0
 
        ld b,e
 
        ld a,l
 
        RRCA 
 
        DJNZ $-1
 
        ld (hl),a
 
        and d
 
        inc h
 
        ld (hl),a
 
        dec h
 
        xor (hl)
 
        ld (hl),a
 
        inc l
 
        jr nz,fixshift0
 
        ret
 
       endif
 
 
 
       if !ATM
 
MAKINT
 
        LD A,IMTAB/256
 
        LD I,A
 
        IM 2
 
        EI 
 
        RET 
 
       endif
 
 
 
      if !ATM
 
;PRGA    LD A,0
 
curpg
 
        db 0x10
 
OUTME
 
        ;LD (PRGA+1),A
 
        ld (curpg),a
 
;OUTNO
 
        PUSH BC
 
        LD BC,FD
 
        OUT (C),A
 
        POP BC
 
        RET 
 
      endif
 
 
 
SetPgMask
 
       if ATM
 
pgmask=$+1
 
        ld a,0
 
        push bc
 
        SETPGC000
 
        pop bc
 
        ret
 
       else
 
       LD A,PGMASK_
 
       jp OUTME
 
       endif
 
 
 
       if ATM
 
SetPgMask8000
 
        ld a,(pgmask)
 
        push bc
 
        SETPG8000
 
        pop bc
 
       ret
 
SetPgTexture8000
 
pg1=$+1
 
        ld a,0
 
        push bc
 
        SETPG8000
 
        pop bc
 
       ret
 
SetPgTextureC000
 
        ld a,(pg1)
 
        push bc
 
        SETPGC000
 
        pop bc
 
       ret
 
SetPgLmn8000
 
pg2=$+1
 
        ld a,0
 
        push bc
 
        SETPG8000
 
        pop bc
 
       ret
 
SetPgMuzC000
 
        ld a,(pg2) ;TODO отдельная страница
 
        push bc
 
        SETPGC000
 
        pop bc
 
       ret
 
       endif
 
 
 
RND
 
        PUSH de
 
        PUSH HL
 
;Patrik Rak
 
rndseed1=$+1
 
        ld  hl,0xA280   ; xz -> yw
 
rndseed2=$+1
 
        ld  de,0xC0DE   ; yw -> zt
 
        ld  (rndseed1),de  ; x = y, z = w
 
        ld  a,e         ; w = w ^ ( w << 3 )
 
        add a,a
 
        add a,a
 
        add a,a
 
        xor e
 
        ld  e,a
 
        ld  a,h         ; t = x ^ (x << 1)
 
        add a,a
 
        xor h
 
        ld  d,a
 
        rra             ; t = t ^ (t >> 1) ^ w
 
        xor d
 
        xor e
 
        ld  h,l         ; y = z
 
        ld  l,a         ; w = t
 
        ld  (rndseed2),hl
 
        POP HL
 
        POP de
 
        RET 
 
 
 
RNDA
 
        PUSH BC
 
        LD C,A
 
        CALL RND
 
        SUB C
 
        JR NC,$-1
 
        ADD A,C
 
        POP BC
 
        RET 
 
 
 
unsetwms
 
       ld a,(gamestate)
 
       cp STATE_FLY
 
       ret z
 
       call ForcedUnDrawWormsInMap
 
       call UnDrawWormsDataInMap
 
       ld a,STATE_FLY
 
       ld (gamestate),a
 
 
 
        ld a,80
 
        call RND
 
       add a,80
 
        ld e,a ;y0
 
        call RND
 
        ld c,a ;x0low
 
        xor a
 
        sla c
 
        rla
 
        sla c
 
        rla
 
        ld b,a ;bc=x0
 
        ld a,40
 
        call RNDA
 
        add a,10
 
        ld d,a ;d=R
 
         ;ld bc,200
 
         ;ld e,100
 
        call UnDrawCircleInMap
 
 
 
        LD HL,WORMXY
 
unsetwms0
 
        ;POP BC ;SPRITE (lsb=xlow*32)
 
        ;POP HL ;COORDS
 
        ;POP DE ;SPEED
 
        ld c,(hl)
 
        inc l
 
        ld b,(hl) ;spritehsb
 
        inc l
 
        dec b
 
        ret z
 
        inc b
 
        ld a,(hl) ;x
 
        inc l
 
        inc l
 
        inc l
 
       cp XWID
 
       jr nc,unsetwms_skip
 
        call RND
 
        and 7
 
        sub 4
 
        ld c,a
 
        call RND
 
        and 7
 
        sub 7;4
 
        ld b,a ;dy
 
        dec l
 
        ld (hl),c
 
        inc l
 
        ld (hl),b
 
unsetwms_skip
 
        inc l
 
        jr unsetwms0
 
 
 
SETWMS
 
;чтобы считывать XY в случайном порядке, будем переставлять случайно несколько раз с первым
 
        ld b,100
 
SETWMS_SHUFFLE0
 
        ld hl,TXY
 
        xor a
 
        sub l
 
        srl a ;число объектов
 
        call RNDA
 
        add a,a
 
        cpl
 
        ld e,a
 
        dec e
 
        ld d,h
 
        ld c,(hl)
 
        ld a,(de)
 
        ld (hl),a
 
        ld a,c
 
        ld (de),a
 
        inc l
 
        inc e
 
        ld c,(hl)
 
        ld a,(de)
 
        ld (hl),a
 
        ld a,c
 
        ld (de),a
 
        djnz SETWMS_SHUFFLE0
 
 
 
        LD HL,WORMXY
 
        LD DE,TXY
 
        LD B,0
 
SWMS0   LD A,(DE) ;x from TXY (до 186?)
 
       ;ld a,l
 
        INC E
 
        LD C,A
 
;SWMSAp1=$+1
 
        LD A,#80
 
        ;SRL C
 
        ;RRA 
 
        LD (HL),A ;xlow*64;32 (was for sprite)
 
        INC HL
 
        LD (HL),sprworm_0/256;BOMBWMS/256+1 ;sprite
 
       ld a,e
 
       cp -2*4 ;4 mines (last in the list)
 
       jr c,$+4
 
       LD (HL),sprmine_0/256;BOMBWMS/256+1 ;sprite
 
        INC HL
 
        LD (HL),C ;xhigh
 
        INC HL
 
        LD A,(DE) ;y from TXY
 
       ;ld a,l
 
        LD (HL),A ;y
 
        INC HL
 
        LD (HL),B;0 ;dx
 
        INC HL
 
        LD (HL),SPRLIST_STAYING ;dy
 
        INC HL
 
        INC E
 
        JR NZ,SWMS0
 
        INC HL
 
        LD (HL),1 ;end of list (impossible xlow)
 
       inc hl
 
       inc hl
 
       inc hl
 
       inc hl
 
       ld (hl),SPRLIST_END ;end of list (impossible dy)
 
        ;LD HL,SWMSAp1
 
        ;LD A,(HL)
 
        ;SUB -2
 
        ;OR #80
 
        ;LD (HL),A ;"рандомная" младшая часть x
 
        LD HL,CUWORMS
 
MKCUW0  XOR A
 
MKCUW1  LD (HL),B ;team 0..3
 
        INC HL
 
        LD (HL),A ;worm 0..3 in team
 
        INC HL
 
        LD (HL),150 ;health
 
        INC HL
 
        LD (HL),0 ;???
 
        INC HL
 
        LD (HL),10 ;???
 
        INC HL
 
        INC HL
 
        INC A ;next worm in team
 
        CP 4
 
        JR C,MKCUW1
 
        INC B
 
       ld a,b
 
       cp 4 ;костыль ;FIXME for 2 or 3 teams
 
        ;CP B ;4 teams ;FIXME for 2 or 3 teams
 
        JR NZ,MKCUW0
 
        RET 
 
 
 
;offint:
 
MOUSEX  DW 0
 
MOUSEY  DB 0
 
 
 
NUMFONTCHARSZ=16;8
 
 
 
ResetTime
 
        LD HL,6*NUMFONTCHARSZ*256+(0*NUMFONTCHARSZ) ;"60"
 
        LD (curtime),HL
 
        LD A,50
 
        LD (curtimeframe),A
 
        jp Hud_ResetTime
 
 
 
TIME
 
curtime=$+1
 
        LD BC,6*NUMFONTCHARSZ*256+(0*NUMFONTCHARSZ) ;"60"
 
        LD A,C
 
        INC A
 
        ret z ;JR Z,PTIMOUT
 
curtimeframe=$+1
 
        LD A,50
 
        DEC A
 
        JR NZ,$+4
 
        LD A,50
 
        LD (curtimeframe),A
 
        ret nz ;JR NZ,TIMPR
 
        LD A,C
 
        SUB NUMFONTCHARSZ;8
 
        LD C,A
 
        JR NC,TIMEok
 
        LD C,9*NUMFONTCHARSZ;8
 
        LD A,B
 
        SUB NUMFONTCHARSZ;8
 
        LD B,A
 
        JR NC,TIMEok
 
        LD HL,MESTIM
 
        CALL MTITLE
 
        LD A,-1
 
        LD (curtime),A
 
        jp Hud_UnDrawTime
 
TIMEok  LD (curtime),BC
 
        ret
 
 
 
 
 
 
 
       if FASTMAPPER
 
MAKELDI
 
        PUSH BC
 
        LD (HL),225
 
        INC HL
 
        LD B,15
 
MLDI1   LD (HL),225
 
        INC HL
 
        LD (HL),34
 
        INC HL
 
        LD (HL),E
 
        INC HL
 
        LD (HL),D
 
        INC HL
 
        INC E
 
        INC E
 
        DJNZ MLDI1
 
        CALL DDE
 
        POP BC
 
        DJNZ MAKELDI
 
        DEC HL
 
        DEC HL
 
        CALL READER
 
        LD SP,IX
 
        RET 
 
        NOP 
 
        RET 
 
       endif
 
 
 
       if FASTMAPPER
 
READER
 
;генерация в HL куска кода, заданного после CALL (0 = конец куска)
 
        EX DE,HL
 
        EX (SP),HL
 
        DEC DE
 
READ0   INC DE
 
        LD A,(HL)
 
        LD (DE),A
 
        INC HL
 
        OR A
 
        JR NZ,READ0
 
        EX (SP),HL
 
        EX DE,HL
 
        RET 
 
       endif
 
 
 
cursorkeys
 
        db 0 ;11LRDUef cursor
 
 
 
TLAND   DB 18,"CREATING LANDSCAPE"
 
MESHOM  DB 17,"2X HOMING MISSILE"
 
MESWHE  DB 16,"NOWHERE TO WORM!"
 
MESTIM  DB 11,"TIME IS OUT"
 
        db 0
 
MESDIE  DB "123456789012 IS AN EX-WORM"
 
MESTEAM
 
        DB "1234567890123456 TEAM IS NO MORE"
 
TEAMLEN=16
 
CUTEAMS ;каждая надпись по TEAMLEN символов
 
        DB "ALONE CODER     "
 
        DB "DAVE            "
 
        DB "WORMS           "
 
        DB "THE FARM        "
 
 
 
NAMES   DB "ALCO        "
 
        DB "ALCO2       "
 
        DB "ALCO3       "
 
        DB "ALCO4       "
 
        DB "DAVE        "
 
        DB "D2          "
 
        DB "D3          "
 
        DB "D4          "
 
        DB "FLAT        "
 
        DB "EARTH       "
 
        DB "TAPE        "
 
        DB "WOOD        "
 
        DB "MOO         "
 
        DB "HORSE       "
 
        DB "PIGGY       "
 
        DB "CHICKEN     "
 
       ;db "BOMBA       "
 
       ;db "BOMBA       "
 
       ;db "BOMBA       "
 
       ;db "BOMBA       "
 
 
 
numfont
 
        include "numfont.ast"
 
       
 
       if !ATM
 
        include "panel.ast" ;в 48K версии можно несъёмную панель (без панелей оружия)
 
       endif
 
 
 
        include "input.asm"
 
        include "mkmap.asm"
 
       if ATM
 
        include "mkmapatm.asm"
 
       else
 
        include "mkmap6912.asm"
 
       endif
 
        include "hud.asm"
 
       if ATM
 
        include "hudatm.asm"
 
       else
 
        include "hud6912.asm"
 
       endif
 
       display "fast procedures: ",$,">=0x8000"
 
        include "logic.asm"
 
        include "drawmap.asm"
 
       if ATM
 
        include "drawmapatm.asm"
 
        include "bgpushxy.asm"
 
        include "../../_sdk/file.asm"
 
        ;include "../../_sdk/bmp.asm"
 
;bmpwid
 
        ;dw 0
 
        include "mem.asm"
 
       else
 
        include "drawmap6912.asm"
 
       endif
 
        include "drawinmap.asm"
 
       if ATM
 
        include "drawinmapatm.asm"
 
       else
 
        include "drawinmap6912.asm"
 
       endif
 
 
 
       if ATM
 
BLANK   DS MASKWID ;BLANK - пустая строка маски (небо) шириной MASKWID
 
       else
 
        align 256
 
IMTAB   DS 257,$/256+1
 
BLANK   DS $/256-1 ;BLANK - пустая строка маски (небо) шириной MASKWID
 
IMER
 
;restore stack from de
 
;if sp=screen, fill with 0
 
;if critical section, unwind de/bc and restore from de/bc
 
        ld (imerhl),hl
 
        pop hl
 
        ld (imerjp),hl
 
        ld (imersp),sp
 
        ld sp,INTSTACK
 
       push BC
 
       push DE
 
       push HL
 
       PUSH AF
 
      if !ATM
 
        ld a,l
 
        sub x6line_startcritical&0xff
 
        ld a,h
 
        sbc a,x6line_startcritical/256
 
        jr c,IMERnocritical
 
        ld a,l
 
        sub x6line_endcritical&0xff
 
        ld a,h
 
        sbc a,x6line_endcritical/256
 
        jr nc,IMERnocritical
 
        ld a,(x6line_restorede_startcritical+x6line_startcritical)&0xff
 
        sub l
 
        ld l,a
 
        ld a,((x6line_restorede_startcritical+x6line_startcritical)/256)&0xff
 
        sbc a,h
 
        ld h,a
 
       pop af
 
       push af
 
       ld (IMERcriticaljp),hl
 
       ld hl,IMERcritical_restorede ;jp (hl)=restore de, ret=restore bc
 
IMERcriticaljp=$+1
 
       call 0 ;unwind de ;addr=x6line_restorede_startcritical-(imerjp-x6line_startcritical)
 
        ld hl,(imersp)
 
        dec hl
 
        ld (hl),b
 
        dec hl
 
        ld (hl),c
 
       jp IMERcriticalq
 
IMERcritical_restorede
 
;after jp (hl)
 
       pop af ;skip return addr
 
IMERnocritical
 
      endif
 
        ld hl,(imersp)
 
       dec hl
 
       dec hl
 
        bit 7,h
 
        jr nz,IMERnozerostack
 
        ld de,0
 
      if !ATM
 
       ld a,l
 
       inc a
 
       jr nz,IMERnozerostack
 
       ld a,h
 
       sub 0x50
 
       cp 7
 
       jr nc,IMERnozerostack
 
;при запарывании 0x50ff..0x56ff (ATM=0)
 
;50ff - берём из 51ff
 
;51ff - берём из 50ff
 
;52ff - берём из 51ff
 
;53ff - берём 0f
 
;прочие - берём ff
 
        ;call ReDrawEnergy ;при запарывании 0x50ff..0x56ff
 
        cp 3
 
        ld e,0x0f
 
        jr z,IMERnozerostack
 
        ld e,0xff
 
        jr nc,IMERnozerostack
 
        cpl
 
        and 1
 
        add a,0x50
 
        ld b,a
 
        ld c,l
 
        ld a,(bc)
 
        ld e,a
 
      endif
 
IMERnozerostack
 
        ld (hl),e
 
        inc hl
 
        ld (hl),d
 
IMERcriticalq
 
        LD hl,curwater
 
        ld a,(hl)
 
        SUB -16
 
        LD (hl),A
 
       ex af,af' ;'
 
       PUSH AF
 
        CALL MOUSE
 
        call TIME
 
        ld hl,timer
 
        inc (hl)
 
        ld a,(curpg)
 
        push af
 
        push ix
 
        push iy
 
        ld a,PGLMN
 
        call OUTME
 
muzpatch=$+1
 
        ld a,0
 
        or a
 
        call z,muz+5
 
        pop iy
 
        pop ix
 
        pop af
 
        call OUTME
 
       pop AF
 
       ex af,af' ;'
 
       pop AF
 
       POP HL
 
       pop DE
 
       pop BC
 
imersp=$+1
 
        ld sp,0
 
imerhl=$+1
 
        ld hl,0
 
        EI 
 
imerjp=$+1
 
        jp 0
 
       endif
 
 
 
       if ATM
 
genpush_newpage
 
;заказывает страницу, заносит в tpushpgs, a=pg
 
        push bc
 
        push de
 
        push hl
 
        push ix
 
        OS_NEWPAGE
 
        pop ix
 
        ld a,e
 
        ld (ix),a
 
        ld de,4
 
        add ix,de
 
        pop hl
 
        pop de
 
        pop bc
 
        ret
 
 
 
RestoreMemMap3
 
        ;ld a,CC_PAGE3;0
 
        ;jp setpgc000;SETPG32KHIGH
 
        ret
 
 
 
        include "grass16.ast"
 
;pal
 
;DDp palette: %grbG11RB(low),%grbG11RB(high), инверсные
 
        ;STANDARDPAL
 
        include "pal.ast"
 
res_path
 
;в этом относительном пути будут лежать все загружаемые данные игры
 
        db "worms"
 
        db 0
 
fnpg1
 
        db "hicode.c",0
 
fnpg2
 
        db "hicode2.c",0
 
        
 
        align 256 ;for setpixel
 
tpushpgs
 
        ds 128 ;первая страница 0 слоя, первая страница 1 слоя, первая страница 2 слоя, первая страница 3 слоя, вторая страница 0 слоя...
 
 
 
        align 256
 
trecodebyteleft
 
        dup 256
 
;%00003210 => %.3...210
 
_3=$&8
 
_210=$&7
 
        db (_3*0x08) + (_210*0x01)
 
        edup
 
        
 
trecodebyteright
 
        dup 256
 
;%00003210 => %3.210...
 
_3=$&8
 
_210=$&7
 
        db (_3*0x10) + (_210*0x08)
 
        edup
 
 
 
bgpush_bmpbuf ds 1024;320 ;заголовок bmp или одна строка
 
       endif
 
 
 
        display "endcode=",$
 
 
 
        align 256
 
tsin
 
        incbin "sin"
 
       if !ATM
 
        align 256
 
        include "texture.ast" ;только при генерации карты (0x800 байт) (можно урезать (как на Амиге) или сжать?)
 
       endif
 
        align 256
 
        include "sprites.ast"
 
sprpie
 
        INCBIN "gug.bin" ;только при генерации карты (на 48K можно убрать)
 
        
 
        display "endgfx=",$
 
endall
 
 
 
       if !ATM
 
        ORG 0x6000
 
        jp GO
 
       endif
 
 
 
        page PGHICODE
 
        ORG 0xc000
 
hicode_begin
 
       if !ATM
 
        nop ;TODO в этой странице тоже что-нибудь
 
       else
 
        include "texforrest.ast"
 
        include "panel16.ast"
 
       endif
 
hicode_end
 
 
 
        page PGLMN
 
        ORG 0xc000
 
hicode2_begin
 
LMNS
 
        INCBIN "lmn.bin" ;>7K! в формате SCUT
 
muz
 
        include "../../_sdk/ptsplay.asm"
 
MDLADDR
 
        incbin "music/WORMS8.pt3"        
 
;GUG
 
;        INCBIN "gug.bin" ;только при генерации карты (на 48K можно убрать)
 
hicode2_end
 
 
 
       if !ATM
 
        page 0
 
        savebin "code.c",begin,endall-begin
 
        page PGHICODE;6
 
        savebin "hicode.c",hicode_begin,hicode_end-hicode_begin
 
        page PGLMN;4
 
        savebin "hicode2.c",hicode2_begin,hicode2_end-hicode2_begin
 
       else
 
        page 0
 
        savebin "worms.com",begin,endall-begin
 
        page PGHICODE;6
 
        savebin "worms/hicode.c",hicode_begin,hicode_end-hicode_begin
 
        page PGLMN;4
 
        savebin "worms/hicode2.c",hicode2_begin,hicode2_end-hicode2_begin
 
       endif
 
 
 
        LABELSLIST "../../../us/user.l",1