Login

Subversion Repositories NedoOS

Rev

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

        DEVICE ZXSPECTRUM128
        include "../../_sdk/sys_h.asm"

scrbuf=0xe000 ;делится на 0x800
tilemap=0xdd00 ;0x300
collisionmap=0xda00 ;0x300 (перед ней ~20 байт затирается)
validmap=0xfc00 ;0x300 (перед ней ~20 байт затирается)
VALID0=0xfb ;валидная, не надо обновлять
VALID1=0x80 ;невалидная, надо обновлять, там можно более длинные процедуры
VALID00=VALID0+256*VALID0
VALID01=VALID0+256*VALID1
VALID10=VALID1+256*VALID0
VALID11=VALID1+256*VALID1
validmaplinesize=32
validmapwid=validmaplinesize-2 ;в конце строки лежит validmapnext

emptyattr=7

fieldwid=10
fieldhgt=8
fieldx=0
fieldy=0

coordsfactor=4

leftwallx=0
topwally=0
rightwallx=fieldwid*24*coordsfactor
bottomwally=fieldhgt*24*coordsfactor

dir_r=0x09
dir_l=0x08
dir_u=0x0b
dir_d=0x0a

collisionmaplinesize=32
collisionmapwid=fieldwid*3
collisionmaphgt=fieldhgt*3
collisionmapsize=collisionmaplinesize*collisionmaphgt
tilemaplinesize=collisionmaplinesize
tilemapwid=collisionmapwid
tilemaphgt=collisionmaphgt
tilemapsize=collisionmapsize

maxemptytile=9

maxobjects=20
maxbullets=100
TERMINATOR=0x80

tanksize=16
tankdamagesize=11 ;грязный хак
tankaimsize=8
tankspeed=4 ;2^n!
bulletspeed=6
bulletenergy=20

startlives=5
maxlives=10

;timer=23672
       
        include "macro.asm"
       
        org PROGSTART
begin
        OS_HIDEFROMPARENT
        ld e,3 ;6912
        OS_SETGFX ;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+SET FOCUS ;e=-1: disable gfx (out: e=old gfxmode)

        ;OS_GETSCREENPAGES
;de=страницы 0-го экрана (d=старшая), hl=страницы 1-го экрана (h=старшая)
        ld a,(user_scr0_high) ;ok
        SETPG16K
       
        ld hl,valid00
        ld de,VALID00
        ld bc,valid00_size
        ldir
        ld hl,valid01
        ld de,VALID01
        ld c,valid01_size
        ldir
        ld hl,valid10
        ld de,VALID10
        ld c,valid10_size
        ldir
        ld hl,valid11
        ld de,VALID11
        ld c,valid11_size
        ldir

        ld a,1
        ld (nlevel),a

newlevel
        call cls
        call clscrbuf
       
        ld a,startlives
        ld (lives),a
        call prlives

        call initlevel

        call clearvalid
        call restoreobjects_clear
        call restorebullets_clear

        call prmap
        call fillcollisionmap
       
        OS_GETTIMER ;dehl=timer
        ;ld hl,(timer)
        ld (oldtimer),hl
       
loop
        call restoreobjects
        call restorebullets
        ;ld a,2
        ;out (0xfe),a
        call probjlist
        ;ld a,4
        ;out (0xfe),a
        call prbulletlist
        ;ld a,0
        ;out (0xfe),a
       
loopdelay
        OS_GETTIMER ;dehl=timer
        ;ld hl,(timer)
oldtimer=$+1
        ld bc,0
        ld (oldtimer),hl
        ld a,l
        sub c
        jr z,loopdelay
        ld b,a
        ;ld a,5
        ;out (0xfe),a
logicloop0
        push bc
        call control
        call animate
        call logic
        call bulletlogic
        ;ld a,1
        ;out (0xfe),a
        call fillcollisionmap
        ;ld a,5
        ;out (0xfe),a
        call bulletcollision
        pop bc
        djnz logicloop0
        ;ld a,6
        ;out (0xfe),a
        call prvalid
        ;call displaycollisionmap
;TODO сделать что-нибудь, когда врагов не осталось
        ld a,(nenemies)
        or a
        jp nz,loop
        ld hl,nlevel
        inc (hl)
        jp newlevel

initlevel
        call genmap

        ld ix,objlist
        call genobj_terminate
        ld ix,bulletlist
        call genbullet_terminate
       
        ld de,0x0010 ;x
        ld hl,0x02b0 ;y
        ld bc,params_tank
        ld a,1 ;a=dir
        call genobj
       
        ld a,(nlevel)
        inc a
        ld b,a
initlevel_addenemies0
        push bc
        ;ld de,0x0010 ;x = 0x0010..0x0370
        call rndxcoord ;out: hl=x
        ex de,hl
        ld hl,0x0010 ;y
        ld bc,params_tanke
        ld a,2 ;a=dir
        call genobj
        ld hl,nenemies
        inc (hl)

        if 1==0
        ld de,0x0370 ;x
        ld hl,0x0010 ;y
        ld bc,params_tanke
        ld a,2 ;a=dir
        call genobj
        ld hl,nenemies
        inc (hl)
        endif
        pop bc
        djnz initlevel_addenemies0
reter        
        ret

attrbox  
;bc=yx
;a=фон
;d=y координата левого верхнего угла
;е=х координата левого верхнего угла
;0x5800+xcoordredbox+(32*ycoordredbox)
        ld l,d  ;y
        ld h,0        
        add hl,hl    
        add hl,hl    
        add hl,hl    
        add hl,hl    
        add hl,hl
        ld d,0x58
        add hl,de ;x
attrbox_lines
        ld e,l
        ld d,h  
        push bc
attrbox_pixels
        ld (de),a
        inc e
        dec c        
        jr nz,attrbox_pixels
        pop bc
        ld de,32
        add hl,de    
        djnz attrbox_lines
        ret

genmap
        ld hl,tilemap
        ld de,tilemap+1
        ld bc,tilemapsize-1
        ld (hl),0
        ldir
       
        ld hl,tilemap+(3*tilemaplinesize)
        ld b,fieldhgt-2
genmaplines
        push bc
        push hl
        ld b,fieldwid
genmapline
        push bc
        push hl
        push hl
        ld a,b ;1..fieldwid
        sub 2 ;n
        cp fieldwid-2 ;nc=левый или правый край
        adc a,nblocks+1 ;n + cy + (nblocks+1)
        sub b ;n + cy + nblocks - (n+2)
        ld c,a ;nblocks или nblocks-1
        call rnd
        ld c,a
        ld b,0
        ld de,9
        call mulbcde
        ld bc,blocks
        add hl,bc
        ex de,hl
        pop hl
        ld bc,tilemaplinesize-2
        dup 3
        ld a,(de)
        ld (hl),a
        inc de
        inc hl
        ld a,(de)
        ld (hl),a
        inc de
        inc hl
        ld a,(de)
        ld (hl),a
        inc de
        add hl,bc
        edup
        pop hl
        inc hl
        inc hl
        inc hl
        pop bc
        djnz genmapline
        pop hl
        ld bc,tilemaplinesize*3
        add hl,bc
        pop bc
        djnz genmaplines
        ret

control
        GET_KEY
        cp key_esc
        jp z,quit
        call getkey ;c=%???lrduf (0=нажато)
        ld a,c
        rra ;f
        jr nc,control_noreleasefire
        ld a,1
        ld (control_firehasbeenreleased),a
control_noreleasefire

;кнопки должны срабатывать, когда мы стоим посредине клетки ((x&(8*coordsfactor-1)) == 4*coordsfactor, (y&(8*coordsfactor-1)) == 4*coordsfactor)
        ld ix,objlist ;первый объект - наш
        call checkevencoords ;nz=не посредине клетки
        ret nz

        ld a,c
        rra ;f
        jr c,control_nofire
        ;проверим, что до этого был момент, когда огонь не нажимали
control_firehasbeenreleased=$+1
        ld a,0
        or a
        jr z,control_nofire ;не было момента, когда огонь не нажимали
        xor a
        ld (control_firehasbeenreleased),a
        ;ld ix,objlist ;первый объект - наш
        push bc
        call shoot
        pop bc
control_nofire

        ld ix,objlist ;первый объект - наш
        ;если не нажата кнопка движения и мы едем, то остановиться
        rr c
        ld a,c
        cpl
        and 0x0f
        jr nz,control_nokeysreleased
        ld a,(ix+obj_anim)
        cp ANIM_GO
        jr nz,control_nokeysreleased
        SETANIM ANIM_STOP
control_nokeysreleased

        ld a,c
        rra ;u
        jr c,control_nou
        call goifpossible
        ld (ix+obj_dir),0
control_nou
        rra ;d
        jr c,control_nod
        call goifpossible
        ld (ix+obj_dir),2
control_nod
        rra ;r
        jr c,control_nor
        call goifpossible
        ld (ix+obj_dir),1
control_nor
        rra ;l
        jr c,control_nol
        call goifpossible
        ld (ix+obj_dir),3
control_nol
       
        ret
       
goifpossible
        ld c,a
        ld a,(ix+obj_anim)
        cp ANIM_APPEAR
        jr nz,$+4
        ld a,ANIM_STOP
        cp ANIM_STOP
        ld a,c
        ret nz ;не стоим, так что не можем поехать
        SETANIM ANIM_GO
        ret
       
checkevencoords
;out: nz=не посредине клетки
        ld a,(ix+obj_x)
        and 8*coordsfactor-1
        cp 4*coordsfactor
        ret nz
        ld a,(ix+obj_y)
        and 8*coordsfactor-1
        cp 4*coordsfactor
        ret

shoot
        SETANIM ANIM_SHOOT
        ld c,(ix+obj_dir)
        ld b,0
        ld hl,tankbulletcoords
        add hl,bc
        add hl,bc
        ld a,(hl) ;dx
        ld c,a ;%sxxxxxxx
        rla    ;%xxxxxxx?, CY=s
        sbc a,a;%ssssssss
        ld b,a ;dx
        inc hl
        ld a,(hl) ;dy
        GETXDE_YHL
        ex de,hl ;hl=x
        add hl,bc ;x+dx
        push hl ;x+dx
        push de ;y
        ld e,a
        rla
        sbc a,a
        ld d,a ;dy
        pop hl ;y
        add hl,de ;hl = y+dy
        pop de ;de = x+dx
        ld a,(ix+obj_dir) ;a=dir
        ld bc,params_bullet
curbulletlistend=$+2
        ld ix,bulletlist
        call genobjorbullet
genbullet_terminate
        ld bc,objterminator
        ld (ix+obj_objaddr),c
        ld (ix+(obj_objaddr+1)),b
        ld (ix+(obj_x+1)),TERMINATOR
        ld (curbulletlistend),ix
        ret

genobjorbullet
;de=x
;hl=y
;bc=params (obj(16),energy(8),speed(8))
;a=dir
        ld (ix+obj_dir),a
        PUTXDE_YHL
        SETANIM ANIM_APPEAR
        ld (ix+obj_delaycounter),1
        ld (ix+obj_gundelaycounter),0
        ld a,(bc)
        ld (ix+obj_objaddr),a
        inc bc
        ld a,(bc)
        ld (ix+(obj_objaddr+1)),a
        inc bc
        ld a,(bc)
        ld (ix+obj_energy),a
        inc bc
        ld a,(bc)
        ld (ix+obj_speed),a
        ld bc,objsize
        add ix,bc
        ret

genobj
;de=x
;hl=y
;bc=params (obj(16),energy(8),speed(8))
;a=dir
curobjlistend=$+2
        ld ix,objlist
        call genobjorbullet
genobj_terminate
        ld bc,objterminator
        ld (ix+obj_objaddr),c
        ld (ix+(obj_objaddr+1)),b
        ld (ix+(obj_x+1)),TERMINATOR
        ld (curobjlistend),ix
        ret

animate
        ld ix,objlist-objsize
animate0_prepareregs
        ld a,TERMINATOR
        ld bc,objsize
animate0
        add ix,bc
animate0_afterdel
        cp (ix+(obj_x+1))
        ret z
        dec (ix+obj_animcounter)
        jp nz,animate0
        ;текущая фаза анимации кончилась, ищем следующую
        ld l,(ix+obj_objaddr)
        ld h,(ix+(obj_objaddr+1)) ;hl=адрес описателя объекта (в начале лежит указатель на список анимаций)
        ld a,(hl)
        inc hl
        ld h,(hl)
        ld l,a ;hl=указатель на список анимаций
        ld e,(ix+obj_anim) ;номер анимации
        ld d,0
        add hl,de
        add hl,de
        ld a,(hl)
        inc hl
        ld h,(hl)
        ld l,a ;hl=указатель на анимацию
        ld e,(ix+obj_animphase) ;номер фазы анимации
        inc e ;следующая фаза анимации
        ld (animate_pointer),hl
        add hl,de
        add hl,de
        add hl,de
        ld a,(hl) ;время фазы
        or a ;если 0, то это конец анимации
        jr nz,animate_noend
        inc hl
        ld a,(hl) ;режим зацикливания (0=переход на нулевую анимацию, 1=зацикливаемся тут, 2=удалить)
        cp 2 ;признак ANIMENDDIE
        jr z,animate_delete
        or a
        jr nz,animate_no0
        ld (ix+obj_anim),a ;0-я анимация
animate_no0
        ld e,0
animate_pointer=$+1
        ld hl,0
        add hl,de
        add hl,de
        add hl,de
        ld a,(hl) ;время фазы
animate_noend
        ld (ix+obj_animcounter),a
        ld (ix+obj_animphase),e ;следующая фаза анимации
        jp animate0_prepareregs
       
animate_delete
        push ix
        pop hl
        ld de,objlist
        or a
        sbc hl,de
        jr z,animate_delete_player
        ld hl,curobjlistend
        call delobj ;копируем из ix+objsize в ix

        ld hl,nenemies
        dec (hl)
       
        ld a,TERMINATOR
        ld bc,objsize
        jp animate0_afterdel
animate_delete_player
        call decreaselives
        call rndbottomcoords ;bc=x, de=y
        SETANIM ANIM_APPEAR
        ld (ix+obj_dir),1 ;a=dir
        jp animate0_prepareregs
       
bulletlogic
        ld ix,bulletlist-objsize
        jr logic0
logic
        ld ix,objlist-objsize
logic0
        ld bc,objsize
        add ix,bc
logic0_afterdel
        ld l,(ix+obj_objaddr)
        ld h,(ix+(obj_objaddr+1)) ;hl=адрес описателя объекта (в начале лежит указатель на список анимаций)
        inc hl
        inc hl
        jp (hl) ;hl=адрес обработчика объекта
       
rndbottomcoords
;out: bc=x, de=y
rndbottomcoords_retry
        call rndxcoord
        ex de,hl
        ld hl,0x02b0 ;y
        PUTXDE_YHL
        call checkobstacles_tank ;nc=препятствие
        jr nc,rndbottomcoords_retry
        ret

rndxcoord
;out: hl=x
        ld c,fieldwid
        call rnd
        ld c,a
        ld b,0
        ld de,8*coordsfactor*3
        call mulbcde
        ld bc,4*coordsfactor
        add hl,bc ;x
        ret

delobj
;hl=адрес указателя на конец списка (на терминатор)
;копируем из ix+objsize в ix
        ld (delobj_curlistend1),hl
        ld (delobj_curlistend2),hl
        ld c,(hl)
        inc hl
        ld b,(hl) ;указатель на конец списка (на терминатор)
        ld hl,objsize
        add hl,bc
        ld b,h
        ld c,l ;указатель на конец списка (после объекта-терминатора)
        ld d,hx
        ld e,lx ;de=ix
        ld a,e
        add a,objsize
        ld l,a
        adc a,d
        sub l
        ld h,a ;hl=ix+objsize
        ld a,c
        sub l
        ld c,a
        ld a,b
        sbc a,h
        ld b,a ;bc=objlistend-hl
        ld a,b
        or c
        ret z ;почему удаляем терминатор после встречи двух пуль??? TODO
        ldir ;копируем все следующие объекты, включая терминатор
delobj_curlistend1=$+1
        ld hl,(curobjlistend)
        ld bc,-objsize
        add hl,bc
delobj_curlistend2=$+1
        ld (curobjlistend),hl
        push ix
        call fillcollisionmap
        pop ix
        ret
       
movetank
        ld a,(ix+obj_anim)
        cp ANIM_GO
        ret nz
moveobj
        GETXDE_YHL
        ld b,(ix+obj_speed)
        ld c,(ix+obj_dir)
        inc c
        dec c
        call z,moveobj_u
        dec c
        call z,moveobj_r
        dec c
        call z,moveobj_d
        dec c
        call z,moveobj_l
        PUTXDE_YHL
        ret
moveobj_u
        dec hl
        djnz $-1
        ret
moveobj_r
        inc de
        djnz $-1
        ret
moveobj_d
        inc hl
        djnz $-1
        ret
moveobj_l
        dec de
        djnz $-1
        ret

objtank
        dw anims_tank
objtank_move
        GETXDE_YHL
        push de
        push hl
        call movetank
        call checkobstacles_tank ;nc=коллизия
        jr nc,objtank_collided
        ld c,tanksize ;размер
        call checkwalls ;nc=стена
        ;TODO как-то воткнуть checkwalls в moveobj, но не в ущерб пулям
objtank_collided
        pop hl
        pop de
        jp c,logic0 ;не стена
        PUTXDE_YHL ;стена - восстановим старые координаты
        jp logic0

objtanke
        dw anims_tanke
        dec (ix+obj_gundelaycounter)
        jr nz,objtanke_nogundelaystop
        inc (ix+obj_gundelaycounter)
        ld a,(ix+obj_anim)
        cp ANIM_PREPARESHOOT
        jr nz,objtanke_noshoot
        push ix
        call shoot
        pop ix
        ld (ix+obj_gundelaycounter),50
        jr objtanke_stop
objtanke_noshoot
objtanke_nogundelaystop
        ld a,(ix+obj_anim)
        cp ANIM_DIE
        jp z,objtanke_nologic
;логика должна срабатывать, когда мы стоим посредине клетки ((x&(8*coordsfactor-1)) == 4*coordsfactor, (y&(8*coordsfactor-1)) == 4*coordsfactor)
        call checkevencoords ;nz=не посредине клетки
        jp nz,objtanke_nologic
;едем энное растояние, потом случайно меняем направление или встаём
        dec (ix+obj_delaycounter)
        jr nz,objtanke_nonewmove
        ld (ix+obj_delaycounter),20
        ld c,5
        call rnd
        cp 4
        jr z,objtanke_stop
        ld (ix+obj_dir),a
        SETANIM ANIM_GO
        jr objtanke_nonewmove
objtanke_stop
        SETANIM ANIM_STOP
objtanke_nonewmove
;если одна из координат близка к нашей (x-(tanksize/2*coordsfactor) > xe >= x+(tanksize/2*coordsfactor)), то встать, задержать и стрелять
        GETXDE_YHL
        push hl ;y
        ld hl,(objlist+obj_x) ;наша координата
        ld bc,-(tankaimsize/2*coordsfactor)
        add hl,bc
        or a
        sbc hl,de ;надо -tanksize*coordsfactor..-1
        ld bc,tankaimsize*coordsfactor
        add hl,bc ;cy=координата близка к нашей
        pop hl ;y
        ex de,hl ;de=y, hl=x
        jr z,$+4
        jr nc,objtanke_noprepareshootx
        ld hl,(objlist+obj_y) ;наша координата
        or a
        sbc hl,de ;y >= ye? тогда d, иначе u
        ld a,2 ;d
        jr nc,$+4 ;y >= xe
        ld a,0 ;u
        ld (ix+obj_dir),a
        jr objtanke_prepareshoot
objtanke_noprepareshootx
        push hl ;x
        ld hl,(objlist+obj_y) ;наша координата
        ld bc,-(tankaimsize/2*coordsfactor)
        add hl,bc
        or a
        sbc hl,de ;надо -tanksize*coordsfactor..-1
        ld bc,tankaimsize*coordsfactor
        add hl,bc ;cy=координата близка к нашей
        pop de ;x
        jr z,$+4
        jr nc,objtanke_noprepareshoot
        ld hl,(objlist+obj_x) ;наша координата
        or a
        sbc hl,de ;x >= xe? тогда r, иначе l
        ld a,1 ;r
        jr nc,$+4 ;x >= xe
        ld a,3 ;l
        ld (ix+obj_dir),a
objtanke_prepareshoot
        SETANIM ANIM_PREPARESHOOT
        ;ld (ix+obj_delaycounter),1
objtanke_noprepareshoot
objtanke_nologic
        jp objtank_move

objbullet
        dw 0
        call moveobj
        ld c,0 ;размер
        call checkwalls ;nc=стена
        jp c,logic0 ;не стена
        ld hl,curbulletlistend
        call delobj ;копируем из ix+objsize в ix
        ld bc,-objsize
        add ix,bc
        jp logic0
       
bulletcollision
        ld ix,bulletlist-objsize
        ld ly,-(128-1)
bulletcollision0
        dec ly
        ld bc,objsize
        add ix,bc
bulletcollision0_afterdel
        ld a,(ix+(obj_x+1))
        cp TERMINATOR
        ret z
        GETXDE_YHL
        call calctilemapaddr_de_hl
        ld a,(hl)
        cp maxemptytile+1
        jr nc,bulletcollision_collided
        call calccollisionmapaddr
        ld a,(hl)
        add a,ly ;номер текущей пули ;CY=1 при совпадении
        call nz,checkbulletcollision
        jp c,bulletcollision0 ;не коллизия
bulletcollision_delete
        ld hl,curbulletlistend
        call delobj ;копируем из ix+objsize в ix
        jp bulletcollision0_afterdel
bulletcollision_collided
        ;ld c,l
        GETXDE_YHL
        push hl
        ex de,hl
        ld a,(ix+obj_dir)
        rra ;nc=vertical direction
        ccf
        call divmul3 ;hl=x клетки карты
        ex (sp),hl ;сохранили x клетки карты ;hl=y
        ld a,(ix+obj_dir)
        rra ;nc=vertical direction
        call divmul3 ;hl=y клетки карты
        pop bc ;x клетки карты
        ld b,l ;y клетки карты
        ld a,c
        call calctilemapaddr_a_l
        ld a,(ix+obj_dir)
        dec a
        jr z,objbullet_collided_ver ;r
        dec a
        jr z,objbullet_collided_hor ;d
        dec a
        jr z,objbullet_collided_ver ;l
                                    ;u
objbullet_collided_hor
        call degradetile
        inc c
        inc hl
        call degradetile
        inc c
        inc hl
        call degradetile
        jp bulletcollision_delete
objbullet_collided_ver
        ld de,tilemaplinesize
        call degradetile
        inc b
        add hl,de
        call degradetile
        inc b
        add hl,de
        call degradetile
        jp bulletcollision_delete
       
divmul3
;если CY=1, то делим до знакомест и округляем до 3
;иначе просто делим до знакомест
        ld de,8*coordsfactor
        jp nc,divhlde ;hl=x(y) клетки карты (без округления)
        ld de,8*coordsfactor*3
        call divhlde ;hl=x(y) клетки поля
        ld c,l
        ld b,h
        add hl,hl
        add hl,bc
        ret ;hl=x(y) клетки карты

degradetile
;bc=yx клетки карты
;hl=tilemap+
        ;push bc
        push de
        ;push hl
        call degradetile_changetile
        call calcscrbufaddr ;de=scrbuf+
        call restoretile
        ;pop hl
        pop de
        ;pop bc
        ret
degradetile_changetile
        ld a,(hl)
        cp tilem
        ret z
        cp tileb
        ld (hl),tile0
        ret z
        cp tilec
        ld (hl),tileb
        ret z
        ld (hl),tile0
        ret
       
objterminator
        dw 0
        ret

decreaselives
lives=$+1
        ld a,0
        dec a
        ld (lives),a
        push af
        call prlives
        pop af
        ret nz
       
gameover    
fieldEx=32
fieldEy=24
centr=(fieldEx/2)-(10/2)+(256*fieldEy/2)
;bc=yx
;a=фон
;d=y координата левого верхнего угла
;е=х координата левого верхнего угла
;0x5800+xcoordredbox+(32*ycoordredbox)
        ld c,12
        ld b,3
        ld de,centr-0x0101
        ld a,0x57        
        ld (curattr),a
        call attrbox
        ld hl,endtext
        ld bc,centr
        call prtext
gameoverloop
        YIELD
        GET_KEY
        cp key_esc
        jr nz,gameoverloop
quit
        QUIT

endtext
        db "Game over!",0

font
        incbin "zx.fnt"
       
        include "collisio.asm"
        include "tankgfx.asm"
        include "tankdata.asm"
        include "math.asm"
        include "input.asm"

nlevel
        db 0 ;1..
nenemies
        db 0
end

reobjlist
        ds 2*(maxobjects+1)
rebulletlist
        ds 2*(maxbullets+1)

objlist
        ds objsize*(maxobjects+1)
objlistend
       
bulletlist
        ds objsize*(maxbullets+1)
bulletlistend


        ;display "End=",end
        ;display "Free after end=",/d,0xc000-end
        ;display "Size ",/d,end-begin," bytes"
       
        savebin "tank.com",begin,end-begin
       
        ;LABELSLIST "..\us\user.l"