DEVICE ZXSPECTRUM1024 include "../../_sdk/sys_h.asm" OLDDRAWSPR=0;1 DEBUGPRINT=0 scrbase=0x4000 sprmaxwid=32 sprmaxhgt=32 scrwid=160 ;double pixels scrhgt=192-16;200 clswid=40 ;*8 clshgt=200 STACK=0x3ff0 ;место для вылетания за экран tempsp=0x3f06 ;6 bytes for prspr INTSTACK=0x3f00;0x3b80 ;чтобы не запороть стек загрузки bmp в bgpush (теперь он в 0x4000+) XSUBPIX8=8 YSUBPIX8=8 MAXSPEED=4*XSUBPIX8 CAMERATRACKINGSPEED_X=16 ;double pixels CAMERATRACKINGSPEED_Y=16 CAMERASHIFTSPEED_X=4 ;double pixels CAMERASHIFTSPEED_Y=4 FIRSTSOLIDTILE=32 FIRSTBETONTILE=64 FIRSTOBJTILE=111 uvscroll_scrbase=0x4000 uvscroll_pushbase=0x8000 uvscroll_callbase=0xc000 UVSCROLL_USETILES=1 UVSCROLL_USEBMP=1 SCRHGT=scrhgt UVSCROLL_WID=1024 UVSCROLL_HGT=256;512 TILEMAPWID=42 ;целые метатайлы TILEMAPHGT=24 ;целые метатайлы UVSCROLL_SCRWID=320 ;8*(TILEMAPWID-2) UVSCROLL_SCRHGT=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 UVSCROLL_TEMPSP=tempsp METATILEMAPWID=256;64 METATILEMAPHGT=64 TILEGFX=0xc000 DELETEDYHIGH=0x7f pushbase=0x8000;c000 macro SETPGPUSHBASE ;ld (curpgc000),a ;SETPGC000 ;ld (curpg8000),a 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 org PROGSTART begin jp GO ;/prsprqwid (спрайты в файле подготовлены так, что выходят сюда) mainloop_uv0 ld a,(curscrnum) or a ld hl,(allscroll) ld a,(allscroll_lsb) jr z,mainloop_uv_getcurscroll0 allscroll_scr1=$+1 ld de,-1 ld (allscroll_scr1),hl allscroll_lsb_scr1=$+1 ld c,-1 ld (allscroll_lsb_scr1),a jr mainloop_uv_getcurscrollok mainloop_uv_getcurscroll0 allscroll_scr0=$+1 ld de,-1 ld (allscroll_scr0),hl allscroll_lsb_scr0=$+1 ld c,-1 ld (allscroll_lsb_scr0),a mainloop_uv_getcurscrollok skipfastredraws=$+1 ld b,1 dec b jr nz,mainloop_uv_dodrawbg cp c jr nz,mainloop_uv_dodrawbg or a sbc hl,de ;jr nz,mainloop_uv_dodrawbg jr z,mainloop_uv_nodrawbg mainloop_uv_dodrawbg ld a,b ld (skipfastredraws),a call uvscroll_draw ;367574/391621 jr mainloop_uv_drawbgq mainloop_uv_nodrawbg ;copy scr behind sprites ;ld hl,spritesA+5;/B/C ld a,(curspritesN) inc a cp 3 jr nz,$+3 xor a ;берём спрайты на 2 отрисовки раньше (т.е. буфер следующий из 3) call getspritesN_a_tode ex de,hl ld l,0 ld l,(hl) inc l dec l jr z,undrawsprites0q undrawsprites0 ld a,(hl) dec hl SETPGC000 ld a,(hl) ;sub 0x80 ld hy,a dec hl ld a,(hl) ld ly,a dec hl ld c,(hl) ;y dec hl ld e,(hl) ;x ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть) push hl ;jr $ call copyboxscrtoscr pop hl dec l jp nz,undrawsprites0 undrawsprites0q call setpgsmain40008000 mainloop_uv_drawbgq if OLDDRAWSPR==1 ld ix,objects call drawsprites ld ix,bullets call drawsprites else curspritesN=$+1 ld a,0 call getspritesN_a_tode ld ix,objects call preparedrawsprites ;1720 ld ix,bullets call preparedrawsprites ;1110 dec de ld (drawsprites_data),de ld a,e ld e,0 ld (de),a call drawsprites ;24040 (только герой) ld a,(curspritesN) inc a cp 3 jr nz,$+3 xor a ld (curspritesN),a endif call usetrackcamera ;d=camera dy ;e=camera dx ;l=mousekey ld a,l ;hl=(sysmousebuttons) rra ;jr nc,mainloop_uvq ;LMB call uvscroll_scroll call uvscroll_scrolltiles ;23099(21121 ldir)/46220 ld a,(timer) push af call changescrpg ;с этого момента (точнее, с прерывания) можем видеть, что нарисовали mainloop_uvwaittimer0 ld a,(timer) uvoldtimer=$+1 ld b,0 ld (uvoldtimer),a sub b ld b,a jr z,mainloop_uvwaittimer0 mainloop_uvlogic0 push bc call logic pop bc djnz mainloop_uvlogic0 ;можем начать новую отрисовку, только если с момента changescrpg прошло хотя бы одно прерывание (возможно, внутри logic) pop bc ;b=timer на момент changescrpg waitchangescr0 ld a,(timer) cp b jr z,waitchangescr0 ld a,(curkey) cp key_esc jp nz,mainloop_uv0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mainloop_uvq if 1==1 ;vertical scroll ld de,bgfilename call bgpush_prepare call cls ld de,pal;SUMMERPAL OS_SETPAL mainloop ld bc,-1 call bgpush_inccurscroll call bgpush_draw ;359975t ld de,spritesA+1 call preparedrawsprites dec de ld (drawsprites_data),de call drawsprites ld a,(timer) push af call changescrpg ;с этого момента (точнее, с прерывания) можем видеть, что нарисовали mainloopwaittimer0 ld a,(timer) oldtimer=$+1 ld b,0 ld (oldtimer),a sub b ld b,a jr z,mainloopwaittimer0 mainlooplogic0 push bc call logic pop bc djnz mainlooplogic0 ;можем начать новую отрисовку, только если с момента changescrpg прошло хотя бы одно прерывание (возможно, внутри logic) pop bc ;b=timer на момент changescrpg waitchangescr1 ld a,(timer) cp b jr z,waitchangescr1 ;waitkey ;halt ;в играх не юзаем YIELD, иначе может сработать чужой обработчик прерываний ld a,(curkey) cp key_esc jp nz,mainloop;waitkey endif call swapimer pgmusic=$+1 ld a,0 SETPG4000 halt ld hl,0x4000;0x4008+3 ;stop OS_SETMUSIC QUIT curkey db 0 getspritesN_a_tode or a ld de,spritesA+1 ret z dec a ld de,spritesB+1 ret z ld de,spritesC+1 ret if OLDDRAWSPR==1 drawsprites pg1=$+1 ld a,0 call setpgc000 drawsprites0 bit 7,(ix+obj.y16+1) ;yhigh jp nz,setpgsmain40008000 ld l,(ix+obj.animaddr16+0) ld h,(ix+obj.animaddr16+1) ld e,(hl) inc hl ld d,(hl) ;de = phase ;ld l,(ix+obj.spraddr16+0) ;ld h,(ix+obj.spraddr16+1) ex de,hl ;ld a,2 ;add a,0 ;ld ($-1),a ;and 2*3 ;add a,l ;ld l,a ld (drawsprites0_sprdescr),hl call setpgsscr40008000 ;предыдущий спрайт мог выключить, если был левее экрана и вообще не попал на экран? ;TODO если спрайт в границах экрана drawsprites0_sprdescr=$+2 ld iy,(0xc000);testspr ;храним x*XSUBPIX8 (in double pixels),y*YSUBPIX8 ld a,(ix+obj.x16+0) ld d,(ix+obj.x16+1) srl d rra srl d rra srl d rra ld e,a cameraxm=$+1 ld hl,0;+160;-2048+160 add hl,de ;jr $ ld a,h or a jr nz,drawspr_skip ld a,l cp 159+sprmaxwid jr nc,drawspr_skip ;sub sprmaxwid-1 ld e,a ld a,(ix+obj.y16+0) ld b,(ix+obj.y16+1) srl b rra srl b rra srl b rra ld c,a cameraym=$+1 ld hl,0;+160;-1024+160 add hl,bc ld a,h or a jr nz,drawspr_skip ld a,l cp 199+sprmaxhgt jr nc,drawspr_skip sub sprmaxhgt-1 ld c,a ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть) push ix ;call prsprega ;(с включением экранных страниц и проверкой попадания спрайта в экран) один спрайт 16x16 = 6875t call prspr ;(без включения экранных страниц и без проверки попадания спрайта в экран) один спрайт 16x16 = 6408t (из них 4224t само мясо) pop ix drawspr_skip ld bc,OBJSIZE add ix,bc jp drawsprites0 ;817000(prsprega)/793000(prspr)t на всё endif if OLDDRAWSPR==0 preparedrawsprites ;pg1=$+1 ld a,(pg1) ;страница описателей спрайтов call setpgc000 preparedrawsprites0 bit 7,(ix+obj.y16+1) ;yhigh ret nz ;jp nz,preparedrawspritesq ;setpgsmain40008000 ;храним x*XSUBPIX8 (in double pixels),y*YSUBPIX8 ld a,(ix+obj.x16+0) ld b,(ix+obj.x16+1) srl b rra srl b rra srl b rra ld c,a cameraxm=$+1 ld hl,0;+160;-2048+160 add hl,bc ld a,h or a jr nz,preparedrawspr_skip ld a,l cp 159+sprmaxwid jr nc,preparedrawspr_skip ;ld e,a ld (de),a ;x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ld a,(ix+obj.y16+0) ld b,(ix+obj.y16+1) srl b rra srl b rra srl b rra ld c,a cameraym=$+1 ld hl,0;+160;-1024+160 add hl,bc ld a,h or a jr nz,preparedrawspr_skip ld a,l cp 199+sprmaxhgt jr nc,preparedrawspr_skip sub sprmaxhgt-1 ;ld c,a inc de ld (de),a ;y = -(sprmaxhgt-1)..199 (кодируется как есть) inc de ld l,(ix+obj.animaddr16+0) ld h,(ix+obj.animaddr16+1) ld a,(hl) ;phase LSB inc hl ld h,(hl) ;phase HSB ld l,a ldi ldi ld a,(ix+obj.animaddr16+0) ;TODO pg1=$+1 ld a,0 ld (de),a ;pg inc de preparedrawspr_skip ld bc,OBJSIZE add ix,bc jp preparedrawsprites0 ;817000(prsprega)/793000(prspr)t на всё ;preparedrawspritesq ; dec de ; ld (drawsprites_data),de ; ret ;jp setpgsmain40008000 ;ld iy,(0xc000);testspr ;ld e,110+(sprmaxwid-1) ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ;ld c,120 ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть) ;call prsprega align 256 spritesA ds 1+5*51 align 256 spritesB ds 1+5*51 align 256 spritesC ds 1+5*51 drawsprites ;y,x,addr,pg - читаем с конца drawsprites_data=$+1 ld hl,0;sprlistA/B/C + ... ;jr $ inc l dec l ret z ;no sprites drawsprites0 call setpgsscr40008000 ;предыдущий спрайт мог выключить, если был левее экрана и вообще не попал на экран? ;TODO если спрайт в границах экрана ld a,(hl) dec hl call setpgc000 ld a,(hl) ld hy,a dec hl ld a,(hl) ld ly,a dec hl ld c,(hl) ;y dec hl ld e,(hl) ;x push hl ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть) call prspr ;(без включения экранных страниц и без проверки попадания спрайта в экран) один спрайт 16x16 = 6408t (из них 4224t само мясо) pop hl dec l jp nz,drawsprites0 jp setpgsmain40008000 endif getmousedelta GET_KEY ;OS_GETKEYNOLANG ld a,c ;keynolang ;ld (key),a jr nz,control_nofocus control_imer_oldmousecoords=$+1 ld bc,0 ld (control_imer_oldmousecoords),de ld a,d;b sub b;d ld d,a ld a,c;e sub e;c ld e,a control_nofocus ;ld (control_imer_mousecoordsdelta),de ret loadpage ;заказывает страничку и грузит туда файл (имя файла в hl) ;out: hl=после имени файла, a=pg push hl OS_NEWPAGE pop hl ld a,e push af ;pg call setpgc000;SETPG32KHIGH push hl ex de,hl OS_OPENHANDLE push bc ld de,0xc000 ;addr ld hl,0x4000 ;size OS_READHANDLE pop bc OS_CLOSEHANDLE pop hl ld b,1 xor a cpir ;after 0 pop af ;pg ret include "pal.ast" ;SUMMERPAL ;DDp palette: %grbG11RB(low),%grbG11RB(high), инверсные ;dw 0xffff,0xfefe,0x1d1d,0x3c3c,0xcdcd,0x4c4c,0x2c2c,0xecec ;dw 0xfdfd,0x2d2d,0xeeee,0x3f3f,0xafaf,0x5d5d,0x4e4e,0x0c0c ;RSTPAL ; STANDARDPAL primgega ;b=hgt,c=wid (/2) ;de=gfx ;hl=scr push bc call setpgsscr40008000 pop bc primgega0 push bc ld hx,b push hl ld bc,40 primgegacolumn0 ld a,(de) inc de ld (hl),a add hl,bc dec hx jr nz,primgegacolumn0 pop hl ld a,0x9f;0xa0 cp h ld bc,0x4000 adc hl,bc jp pe,primgegacolumn0q ;в половине случаев ;8000->с000 (надо 6000) или a000->e001 (надо 4001) inc a xor h ld h,a primgegacolumn0q pop bc dec c jr nz,primgega0 jp setpgsmain40008000 prsprega ;iy=spr (+4) ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1)) ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть) push bc call setpgsscr40008000 pop bc ld a,e cp scrwid+(sprmaxwid-1) jr nc,noprspr ld a,c add a,sprmaxhgt-1 cp scrhgt+(sprmaxhgt-1) call c,prspr noprspr jp setpgsmain40008000 sfxplay push af pgsfx=$+1 ld a,0 SETPG8000 pop af jp 0x8000 ;SFXPLAY include "int.asm" include "cls.asm" include "prspr.asm" include "bgpush.asm" include "bgpushxy.asm" include "mem.asm" include "../../_sdk/bmp.asm" include "logic.asm" include "camera.asm" include "sprdata.asm" include "../../_sdk/file.asm" if DEBUGPRINT prcoords call setpgsscr40008000 ld hl,(cameraxshift) ld de,0x4000 + (192*40) call prnum ld hl,(objects+obj.xspeed16) ld de,0x4008 + (192*40) call prnum ret prnum ld bc,10000 call prdig ld bc,1000 call prdig ld bc,100 call prdig ld bc,10 call prdig ld bc,1 prdig ld a,'0'-1 prdig0 inc a or a sbc hl,bc jr nc,prdig0 add hl,bc ;push hl ;call prchar ;pop hl ;ret prchar ;a=code ;de=screen push de push hl call prcharin pop hl pop de inc e ret calcscraddr ;bc=yx ;можно портить bc ex de,hl ld a,c ;x ld l,b ;y ld h,0 ld b,h ld c,l add hl,hl add hl,hl add hl,bc ;*5 add hl,hl add hl,hl add hl,hl ;*40 add hl,hl add hl,hl add hl,hl add a,l ld l,a ld a,h adc a,0x40 ld h,a ex de,hl ret prcharxy ;a=code ;bc=yx push de push hl push bc push af call calcscraddr pop af call prcharin pop bc pop hl pop de ret prcharin sub 32 ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ;ld bc,font-(32*32) ;add hl,bc ld a,h add a,font/256 ld h,a prcharin_go ex de,hl ld bc,40 push hl push hl dup 8 ld a,(de) ;font ld (hl),a ;scr inc de add hl,bc edup pop hl ;set 6,h ld a,h add a,0x40 ld h,a ;ld d,font/256 dup 8 ld a,(de) ;font ld (hl),a ;scr inc de add hl,bc edup pop hl set 5,h push hl ;ld d,font/256 dup 8 ld a,(de) ;font ld (hl),a ;scr inc de add hl,bc edup pop hl ;set 6,h ld a,h add a,0x40 ld h,a ;ld d,font/256 dup 8 ld a,(de) ;font ld (hl),a ;scr inc de add hl,bc edup ret endif 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 if DEBUGPRINT align 256 font incbin "fontgfx" endif RestoreMemMap3 ret res_path db "sprexamp",0 ;в этом относительном пути будут лежать все загружаемые данные игры bgfilename db "bg6-16c.bmp",0 bgxyfilename db "bg8-16d.bmp",0 tilefilename db "tiles.bin",0 tilebmpfilename db "tiles1.bmp",0 tilemapfilename db "map1.map",0 enemymapfilename db "map1.enm",0 TILEMAP ds TILEMAPWID*TILEMAPHGT ;снизу вверх, справа налево 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=0x4000 ;ds 1024;320 ;заголовок bmp или одна строка bgpush_loadbmplinestack=bgpush_bmpbuf+1024 ;ds pushhgt*2+32 include "init.asm" end display "begin=",begin display "end=",end display "Size ",/d,end-begin," bytes" savebin "sprexamp.com",begin,end-begin LABELSLIST "../../../us/user.l",1