Login

Subversion Repositories NedoOS

Rev

Rev 1626 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

        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
        OS_HIDEFROMPARENT
       
        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