IF corr_coord CORR_COORD LD A,L OR A jr NZ,$+3 INC L INC A jr NZ,$+3 DEC L LD A,H OR A jr NZ,$+3 INC H INC A RET NZ DEC H RET ENDIF RAYPREPXY ;TODO брать координаты не из прерывания!!! IF optfast LD HL,(IMcurDX) LD A,H OR L LD HL,(IMcurDY) OR H OR L LD A,lowmaxscale jr Z,$+4 LD A,0;-1 LD (foptfast),A ENDIF IMcurXx=$+1 LD HL,#0F80 ;#0580 IF corr_coord CALL CORR_COORD ENDIF LD (curXx),HL IMcurYy=$+1 LD HL,#0180+(map&#FF00) ;#A580 IF corr_coord CALL CORR_COORD ENDIF LD (curYy),HL LD A,(IMavision+1) LD (curangle),A SUB 32 LD L,A LD H,0 ADD HL,HL ADD HL,HL LD A,L LD (avision4L),A LD A,H LD (avision4H),A LD HL,(cury-1) LD A,(curx) LD L,A LD (cur00yx),HL LD (cur01yx),HL ;LD A,L ;основное направление CPL ;1-основное направление LD L,A LD (cur10yx),HL LD (cur11yx),HL CPL ;основное направление LD L,H,H,A LD (cur00xy),HL LD (cur01xy),HL LD A,L ;1-основное направление CPL ;основное направление LD L,A LD (cur10xy),HL LD (cur11xy),HL LD HL,(curX) LD A,(curY) LD H,A ;LD (curYX),HL LD (ray00yx_YX),HL LD (ray01yx_YX),HL LD (ray10yx_YX),HL LD (ray11yx_YX),HL LD (ray00xy_YX),HL LD (ray01xy_YX),HL LD (ray10xy_YX),HL LD (ray11xy_YX),HL SET mapdifbit,L LD (ray00xy_YX2),HL LD (ray01xy_YX2),HL LD (ray10xy_YX2),HL LD (ray11xy_YX2),HL ret SCAN call RAYPREPXY ;TODO чтобы узнать, какая дверь открывается, надо её отметить на самой карте (с обеих сторон) IF interpolate == 0 IF lores LD L,0;2*(32-scrwid) LD HY,SCRWIDPIX;scrwid*4 ELSE LD L,0;4*(32-scrwid) LD HY,SCRWIDPIX;scrwid*8 ENDIF RAY0 LD A,L LD (cura),A CALL RAYCAST LD HL,(cura) LD H,distbuf/256+2 LD (HL),C ;dist (scale#) DEC H LD (HL),B ;texx DEC H RRCA ;CY=0 LD A,(DE) ;ID(YX) ;ld a,0xc0 LD (HL),A ;ID INC L DEC HY JP NZ,RAY0 ELSE ;interpolate main_step=interpolate;16 ;oldscan=RAYCAST(0) XOR A LD L,A LD (cura),A CALL RAYCAST EXX ;main_a=main_step-1 LD L,main_step-1 ;IF lores ; LD HY,scrwid*4/main_step ;ELSE ; LD HY,scrwid*8/main_step ;ENDIF ld hy,SCRWIDPIX/main_step ;repeat { ;L=main_a ;BCDE'=oldscan ;BCDE=newscan RAY0 ;newscan=RAYCAST(main_a) LD A,L LD (cura),A CALL RAYCAST LD HL,(cura) ;INTERPOLATE_SUB(main_a, main_step, oldscan, newscan) LD A,main_step LD H,distbuf/256+2 LD (HL),C ;dist (scale#) DEC H LD (HL),B ;texx DEC H RRCA ;CY=0 CALL INTERPOLATE_SUB LD A,(DE) ;ID(YX) ;ld a,0xc0 LD (HL),A ;ID ;oldscan=newscan LD A,L EXX ;main_a+=main_step ADD A,main_step LD L,A ;} until(main_a>255) DEC HY JP NZ,RAY0 ENDIF ;interpolate RET ;((b+f)/2)^2-b^2/4-f^2/4 ;a=e MACRO MULPOS LD H,tsqr2/256 ADD A,C RRA LD L,A LD A,(HL) INC H LD L,C SUB (HL) LD L,E SUB (HL) ENDM MACRO DIVPOS SRL C DUP 7 ADD A,C jr NC,$+3 SUB C RL B ADD A,A EDUP ADD A,C LD A,B RLA ENDM MACRO DIVNEG SRL C DUP 7 SUB C jr NC,$+3 ADD A,C RL B ADD A,A EDUP SUB C LD A,B RLA ENDM ;Y растёт вверх RAYCAST ;L=(cura)=угол на экране ;портит ABCDEHLIX ld a,(doortimer) ld ly,a LD H,tda/256 LD A,(HL) avision4L=$+1 ADD A,0 LD (rayrealangle),A LD L,A avision4H=$+1 ADC A,0 SUB L ;a1..0 = 0..3 ~ sector 1..4 ;LD H,tctg/256 ;-pi/4..+pi/4 INC H LD C,(HL) ;ystep or xstep LD HX,-1 ;IX=dist*cos RRA jr NC,ray13 RRA JP NC,ray2 JP ray4 ray13 RRA JP NC,ray1 JP ray3 macro INCR num ;0..5 = bcdehl db 0x04+(8*(num)) endm macro DECR num ;0..5 = bcdehl db 0x05+(8*(num)) endm ;RAY 1,1,H,D,y,x MACRO RAY mainplus,secplus,maindirhlreg,maindirdereg,maindir,secdir ;mainplus=\0 ;основное направление положительно ;secplus=\1 ;побочное направление положительно ;\2=основное направление для hl (YX) ;\4=основное направление для de (yx) ;\6=основное направление (0=x, 1=y) ;\7=побочное направление (0=x, 1=y) ;c=побочный шаг LD A,E ;основное направление LD LX,A ;IX=dist*cos MULPOS ;a = a*c IF secplus ;побочное направление положительно ADD A,D ;побочное направление LD B,A ;texx ray0176_YX=$+1 LD HL,0 ;hl = основная стенка IF maindir != 0 ;"\6\6"-"xx" ray0176_YX2=$+1 LD DE,0 ;set mapdifbit ;осн.напр. y, побочное x ELSE LD D,H ;осн.напр. x, побочное y ld E,L ENDIF ;de = побочная стенка jr NC,2f;raynshort\0\1\7\6 ;точно не пересечение по побоч.напр. INCR maindirdereg^1 ;secdirdereg;INC \5 ;e/d LD A,(DE) add a,a cp ID_DOOR*2;128+(22*2) jr z,9f ld a,(de) RLA jp C,1f;raysec\0\1\7\6 ;выход по побочной стене 9 INCR maindirhlreg^1 ;secdirhlreg;INC \3 ;l/h 2;raynshort\0\1\7\6 IF maindir != 1 ;"\6\6"-"yy" SET mapdifbit,L ENDIF ELSE ;побочное направление отрицательно LD L,A LD A,D ;побочное направление SUB L LD B,A ;texx ray0176_YX=$+1 LD HL,0 ;hl = основная стенка IF maindir != 0 ;"\6\6"-"xx" ray0176_YX2=$+1 LD DE,0 ;set mapdifbit ;осн.напр. y, побочное x ELSE LD D,H ;осн.напр. x, побочное y ld E,L ENDIF ;de = побочная стенка jr NC,2f;raynshort\0\1\7\6 ;точно не пересечение по побоч.напр. LD A,(DE) add a,a cp ID_DOOR*2;128+(22*2) jr z,9f ld a,(de) RLA jp C,1f;raysec\0\1\7\6 ;выход по побочной стене 9 ;продолжение по основному направлению DECR maindirhlreg^1 ;secdirhlreg DECR maindirdereg^1 ;secdirdereg 2;raynshort\0\1\7\6 IF maindir != 1 ;"\6\6"-"yy" SET mapdifbit,L ENDIF ENDIF ;первый (короткий) шаг закончен, теперь идём полными шагами в цикле 3;raynsec=$;\0\1\7\6 INC HX IF mainplus ;основное направление положительно INCR maindirhlreg;INC \2 ;h/l ENDIF LD A,(HL) add a,a cp ID_DOOR*2;128+(22*2) jp z,4f;doorhlq ;куб двери ld a,(hl) RLA JP C,rayhlq ;b=texx ;выход по основной стене 13 IF mainplus ;основное направление положительно INCR maindirdereg;INC \4 ;d/e ELSE DECR maindirhlreg DECR maindirdereg ENDIF LD A,B ;texx IF secplus ;побочное направление положительно ADD A,C ;побочный шаг ELSE SUB C ;побочный шаг ENDIF LD B,A ;texx jr NC,3b;raynsec;\0\1\7\6 ;точно не пересечение по побоч.напр. 12 IF secplus ;побочное направление положительно INCR maindirdereg^1 ;secdirdereg;INC \5 ;e/d ENDIF LD A,(DE) add a,a cp ID_DOOR*2;128+(22*2) jr z,5f ld a,(de) RLA jp C,1f;raysec\0\1\7\6 ;выход по побочной стене 9 IF secplus ;побочное направление положительно INCR maindirhlreg^1 ;secdirhlreg;INC \3 ;l/h ELSE ;побочное направление отрицательно DECR maindirhlreg^1 ;secdirhlreg DECR maindirdereg^1 ;secdirdereg ENDIF JP 3b;raynsec;\0\1\7\6 7 ;возврат из куба двери, если дверь открыта (в следующей стене игнорить дверь!!!) LD A,B ;texx IF secplus ;побочное направление положительно ADD A,C ;побочный шаг ELSE SUB C ;побочный шаг ENDIF LD B,A ;texx jr C,12b;raynsec;\0\1\7\6 ;точно не пересечение по побоч.напр. ;3;raynsec=$;\0\1\7\6 INC HX IF mainplus ;основное направление положительно INCR maindirhlreg;INC \2 ;h/l ENDIF jr 13b ;считаем, что стены впереди нет, продолжаем как обычно ;куб двери по побочному шагу 5 ld a,(de) rla jr nc,$+5 ;закрытая дверь ld ly,0 IF secplus ;побочное направление положительно INCR maindirhlreg^1 ;secdirhlreg;INC \3 ;l/h ELSE ;побочное направление отрицательно DECR maindirhlreg^1 ;secdirhlreg DECR maindirdereg^1 ;secdirdereg ENDIF INC HX bit 7,B ;texx IF secplus ;побочное направление положительно jp z,rayhlq ;видим основную стену до двери ELSE jp nz,rayhlq ;видим основную стену до двери ENDIF ;ld b,10 ;сплошной голубой (0=сплошной серый) ;jp z,rayhlq IF secplus ;побочное направление положительно INCR maindirdereg^1 ;secdirdereg;INC \5 ;e/d ENDIF ;jp rayhlq ;дверь открыта, выход по основной стене ;dec hx ld a,b ;texx add a,128 ;ld b,a ;jr 1f ;jr C,8f;raysec\0\1\7\6 ;выход по побочной стене ;LD A,B IF secplus ;побочное направление положительно SUB C else ADD A,C endif ;a=texx как был ex de,hl;EXD ;ex de,hl ;jp rayhlq ;дверь открыта, выход по основной стене push bc IF secplus ;побочное направление положительно DIVPOS ;texx(a)/step(c), портит b,c ELSE DIVNEG ;texx(a)/step(c), портит b,c ENDIF pop bc IF mainplus ;основное направление положительно CPL ;push hl ;ld hl,timer add a,ly;(hl) jr c,6f ;b=texx, выход по осн. стене (полуоткрытая дверь) LD B,A ;b=texx sub ly;(hl) ;pop hl ELSE ;push hl ;ld hl,timer add a,ly;(hl) jr c,6f ;выход по осн. стене (полуоткрытая дверь) LD B,A ;b=texx sub ly;(hl) CPL ;pop hl ENDIF dec hx JP raydeq ;c,de не важны 6 ;выход по осн. стене (полуоткрытая дверь) ;pop hl ex de,hl jp rayhlq ;b=texx ;куб двери по основному шагу 4 bit 7,(HL) jr z,$+5 ;закрытая дверь ld ly,0 ;проверить, что позади дверь, тогда выход в 13b (т.е. впереди пусто) IF mainplus ;основное направление положительно DECR maindirhlreg;INC \4 ;d/e ELSE INCR maindirhlreg ENDIF ld a,(hl) IF mainplus ;основное направление положительно INCR maindirhlreg;INC \4 ;d/e ELSE DECR maindirhlreg ENDIF add a,a cp ID_DOOR*2;128+(22*2) jp z,13b ;позади дверь, значит, впереди пусто ; srl c ;побочный шаг IF mainplus ;основное направление положительно INCR maindirdereg;INC \4 ;d/e ELSE DECR maindirhlreg DECR maindirdereg ENDIF LD A,B ;texx IF secplus ;побочное направление положительно ADD A,C ;побочный шаг LD B,A ;texx SUB C ;побочный шаг ELSE SUB C ;побочный шаг LD B,A ;texx ADD A,C ;побочный шаг ENDIF jr c,2f ex af,af' ;' ld a,ly;(timer) add a,b ld b,a jr nc,11f ;дверь по основному направлению ex af,af' ;' ld b,a ;texx как был sla c ;побочный шаг как был jp 7b ;нет двери 11 jp doorhlq;3b;raynsec;\0\1\7\6 ;точно не пересечение по побоч.напр. 2;куб двери по основному шагу - выход по побочной стене IF secplus ;побочное направление положительно INCR maindirdereg^1 ;secdirdereg;INC \5 ;e/d ENDIF ;побочная стена при шаге половинками sla c ;побочный шаг как был jr 8f ;побочная стена 1;raysec\0\1\7\6 LD A,B IF secplus ;побочное направление положительно SUB C else ADD A,C endif 8 ;a=texx как был ex de,hl;EXD IF secplus ;побочное направление положительно DIVPOS ;texx(a)/step(c) ELSE DIVNEG ;texx(a)/step(c) ENDIF IF mainplus ;основное направление положительно CPL LD B,A ;b=texx ELSE LD B,A ;b=texx CPL ENDIF JP raydeq ENDM ;mainplus=\0 ;основное направление положительно ;secplus=\1 ;побочное направление положительно ;\2=основное направление для hl = 4..5 ;\4=основное направление для de = 2..3 ;\6=основное направление ;\7=побочное направление ;c = ystep or xstep (шаг по побочному направлению) всегда положительный ;HX=-1 ;IX=dist*cos ;сейчас l=angle ray1 BIT 7,L JP NZ,ray1b ;RAY 1,1,L,E,x,y ;1a cur11yx=$+1 LD DE,0 RAY 1,1,5,3,0,1;x,y ;1a ;cur11yx=cur0176 ray11yx_YX=ray0176_YX ;ray11yx_YX2=ray0176_YX2 ray1b ;RAY 1,1,H,D,y,x ;1b cur11xy=$+1 LD DE,0 RAY 1,1,4,2,1,0;y,x ;1b ;cur11xy=cur0176 ray11xy_YX=ray0176_YX ray11xy_YX2=ray0176_YX2 ray2 BIT 7,L JP NZ,ray2b ;RAY 1,0,H,D,y,x ;2a cur10xy=$+1 LD DE,0 RAY 1,0,4,2,1,0;y,x ;2a ;cur10xy=cur0176 ray10xy_YX=ray0176_YX ray10xy_YX2=ray0176_YX2 ray2b ;RAY 0,1,L,E,x,y ;2b cur01yx=$+1 LD DE,0 RAY 0,1,5,3,0,1;x,y ;2b ;cur01yx=cur0176 ray01yx_YX=ray0176_YX ;ray01yx_YX2=ray0176_YX2 ray3 BIT 7,L JP NZ,ray3b ;RAY 0,0,L,E,x,y ;3a cur00yx=$+1 LD DE,0 RAY 0,0,5,3,0,1;x,y ;3a ;cur00yx=cur0176 ray00yx_YX=ray0176_YX ;ray00yx_YX2=ray0176_YX2 ray3b ;RAY 0,0,H,D,y,x ;3b cur00xy=$+1 LD DE,0 RAY 0,0,4,2,1,0;y,x ;3b ;cur00xy=cur0176 ray00xy_YX=ray0176_YX ray00xy_YX2=ray0176_YX2 ray4 BIT 7,L JP NZ,ray4b ;RAY 0,1,H,D,y,x ;4a cur01xy=$+1 LD DE,0 RAY 0,1,4,2,1,0;y,x ;4a ;cur01xy=cur0176 ray01xy_YX=ray0176_YX ray01xy_YX2=ray0176_YX2 ray4b ;RAY 1,0,L,E,x,y ;4b cur10yx=$+1 LD DE,0 RAY 1,0,5,3,0,1;x,y ;4b ;cur10yx=cur0176 ray10yx_YX=ray0176_YX ;ray10yx_YX2=ray0176_YX2 doorhlq ld a,128 jr raydeq rayhlq_texxaxorb xor b ld b,a rayhlq XOR A raydeq ;b=texx ;hl=YX ;dist*cos=ix+a PUSH HL ADD A,LX LD L,A ADC A,HX SUB L LD H,A ;HL=dist*cos=128..#3fff ;приводим к 128..255 LD DE,#000 LD A,L jr Z,TOLOGRLQ DUP 5;6 INC D SRL H RRA jr Z,TOLOGRLE EDUP TOLOGRLQ ; if antizalom;debug cp 64 jr nc,$+4 ld a,64 else OR A JP M,$+5 ;>=128 LD A,128 ;<128 endif TOLOGRLE ; LD L,A ;128..255 ;D=0..5 LD H,tlogd/256 ;2.делим на cos rayrealangle=$+1 LD A,(tlogcos) ;0..63 ADD A,(HL) ;log(dist/2^N) = 128..255 for arg>=128 IF antizalom;debug jr NC,$+3 INC D ENDIF ;3.умножение на corrdist(scrX) - получаем k/масштаб ;(сокращаем расстояние по краям в sqrt(2) раз) ;corrdist(scrX)=1/sqrt(1+scrX^2), где scrX=-1..+1 ;из него номер таблицы масштабирования cura=$+1 LD HL,tcorrlogd ;L=scrX=0..255="-127.5..127.5" SUB (HL) ;64..128 IF antizalom;debug jr NC,DEBBP DEC D JP P,DEBBP INC D XOR A DEBBP ; ENDIF LD L,A LD H,tlogd2sca/256 SRA D RR E ;DE=+0,+#80,..+#300 ADD HL,DE IF 0;debug BIT 7,(HL) jr NZ,$ ENDIF LD C,(HL) ;dist(scale#)=63..1;127..1 ;todo linear scale, recalc in DRAWWALLS SCF RR B ;texx=0x80..0xFF IF scale64 SRL B ;texx=0x40..0x7F ENDIF POP DE RET IF interpolate IF 0 I_SUB_INTERt ; POP HL ; PUSH HL ;de LD A,D SUB H jr NZ,holeny LD A,E SUB L JP Z,I_SUB_INTER ;продолжение стены DEC A CP 3 jr C,nhole JP isubneq holeny ; DEC A CP 3 jr NC,isubneq LD A,E CP L jr NZ,isubneq nhole ; ENDIF I_SUB_INTER ; rightscan=Middlescan LD A,C EXX ADD A,C RRA LD C,A ;dist EXX LD A,B EXX ADD A,B RRA LD B,A ;texx I_SUB_SCANQ ; ;INTERPOLATE_SUB(a-step, step, leftscan, rightscan);r=M PUSH HL ;step,a LD A,L SUB H LD L,A ;a-step LD A,H LD H,distbuf/256+2 LD (HL),C ;dist DEC H LD (HL),B ;texx DEC H RRCA CALL NC,INTERPOLATE_SUB LD A,(DE) ;ID ;ld a,0xc0 LD (HL),A ;ID ;leftscan=rightscan ;=Middlescan EXX POP HL ;step,a ;pop(rightscan) POP DE pop BC ;INTERPOLATE_SUB(a, step, leftscan, rightscan) ;l=M,r=R ;scan[a]=rightscan ;if (step==1) exit LD A,H LD H,distbuf/256+2 LD (HL),C ;dist DEC H LD (HL),B ;texx DEC H RRCA RET C INTERPOLATE_SUB ;L=a ;A=step/2 ;not preserved ;BCDE'=leftscan ;(a-step) ;not preserved ;BCDE=rightscan ;(a) ;CY=0 EXA LD A,(DE) ;ID LD (HL),A ;ID ;texx,dist are written already EXA ;step=step/2 LD H,A ;push(rightscan) PUSH BC push DE ;if(rightscan.yx==leftscan.yx) ;LD A,(DE) EXX ;EXD ;XOR (HL) ;EXD ;JP Z,I_SUB_INTERt POP HL ; PUSH HL ;de ;OR A SBC HL,DE ;CY=0 JP Z,I_SUB_INTER isubneq ; rightscan=RAYCAST(a-step) EXX PUSH HL LD A,L SUB H LD L,A ;a-step LD (cura),A CALL RAYCAST POP HL JP I_SUB_SCANQ ;else - see above ENDIF ;interpolate ;============================ IF sprites viewrange=6 DOSORTSPRITES=1 ;CURSPRITES_RECSZ=5;4 SCANMONS LD A,(curX) SUB viewrange LD (scmonX),A LD A,(curY) SUB viewrange LD (scmonY),A LD HL,cursprites if DOSORTSPRITES LD (HL),0 ;end of sprites endif LD (scaneof),HL LD HL,MONSTRS+1 ;1+начало табл.монстров/предметов ld hx,-1 ;monster index jp SCMONS0 ;цикл скан-я видимых монстров/предметов SCMONNx LD A,L ADD A,8 LD L,A JR C,SCMxIH SCMONS0 inc hx ;monster index LD A,(HL) ;X INC A RET Z scmonX=$+1 SUB 0 CP viewrange*2+1 JP NC,SCMONNx INC L inc L LD A,(HL) scmonY=$+1 SUB 0 CP viewrange*2+1 JR C,SCMONY LD A,L ADD A,6 LD L,A JP NC,SCMONS0 SCMxIH INC H JP SCMONS0 SCMONY DEC L dec L dec L LD C,(HL) INC L LD B,(HL) ;Xx INC L LD E,(HL) INC L LD D,(HL) ;Yy INC L PUSH HL PUSH BC inc l ;skip DIR (TODO use) LD L,(HL) ;TYPE*8+phase ld H,0 ;ADD HL,HL ;ADD HL,HL ;ADD HL,HL LD BC,MONSTAB-8 ADD HL,BC LD A,(HL) ;ID текстуры (в зависимости от фазы) if !atm add a,a;ld a,r if doublescr and (spritesinpg*2-1)*2 else and (spritesinpg-1)*2 endif add a,0xc0+(texturesinpg*2);0xea endif ld lx,a POP BC ;calculate sprite position LD HL,(curYy) SBC HL,DE ;Yy ex de,hl;EXD LD HL,(curXx) SBC HL,BC ;Xx CALL OBJMUL ;BC=dist ;DE=xscr IF lores SRA D RR E ENDIF LD HL,pixperchr*scrwid/2-256 SBC HL,DE INC H jr NZ,SCANnSPR ;X out of screen IF lores BIT 7,L jr NZ,SCANnSPR ;X out of screen ENDIF ;write data to cursprites ;ID 8 (0=end) ;dist 16 ;xscr 8 ;monster index if DOSORTSPRITES == 0 LD A,L ;xscr scaneof=$+1 ld hl,0 ld e,lx ld (hl),e ;id inc l ld (hl),c inc l ld (hl),b ;bc=dist inc l ld (hl),a ;xscr inc l if CURSPRITES_RECSZ == 5 ld a,hx ld (hl),a ;monster index inc l endif ld (hl),0 ld (scaneof),hl else PUSH BC EXX POP BC LD HL,cursprites+((-(CURSPRITES_RECSZ-2))&0xff) SCANsort0 if CURSPRITES_RECSZ == 5 INC L endif INC L inc L LD A,(HL) OR A jr Z,SCANins INC L LD E,(HL) INC L LD D,(HL) ;de=dist ex de,hl;EXD SBC HL,BC ex de,hl;EXD jr NC,SCANsort0 DEC L dec L SCANins PUSH BC scaneof=$+1 LD DE,0 LD A,E SUB L INC A ;bytes to move LD C,A LD B,0 LD H,D ld L,E LD A,E ADD A,CURSPRITES_RECSZ;4 LD E,A LD (scaneof),A LDDR INC HL POP BC LD A,lx;1 ;A=ID текстуры ;BC'=dist ;L'=xscr LD (HL),A INC L LD (HL),C INC L LD (HL),B INC L EXX LD A,L EXX LD (HL),A ;xscr INC L if CURSPRITES_RECSZ == 5 ld a,hx ld (hl),a ;monster index inc l endif EXX endif SCANnSPR ; POP HL INC L inc L inc L inc HL INC L JP SCMONS0 DRAWSPRITES ;ID 8 (0=end) ;dist 16 ;xscr 8 ;monster index LD IY,cursprites DRAWSPRITES0 ; LD A,(IY) ;id OR A RET Z INC IY LD C,(IY) INC IY LD B,(IY) ;bc=dist INC IY ;A=ID if atm==0 EXX LD D,a ;ID (не адрес) ;ld d,0xe2 ;адрес EXX endif if atm add a,a add a,a ld hl,tsprites-4 add a,l ld l,a jr nc,$+3 inc h ld a,(hl) if atm ld (drawspritepg),a endif inc hl ld a,(hl) LD HX,a;#80+22;#C0 ;texx_center ;TODO на 48К что-то не то ;ld hx,22/2 inc hl ld a,(hl) if atm ld (drawspritetexxleft),a endif ;TODO inc hl ld a,(hl) if atm ld (drawspritetexxright),a endif ;TODO endif LD L,(IY) ;xscr INC IY if CURSPRITES_RECSZ == 5 INC IY endif ;L=xscr ;BC=dist INC B DJNZ gFILLNCLOSE LD A,108;64 ;от этого числа зависит только ширина спрайта при максимальном приближении, но не максимальная высота (она ограничена этим числом и сравнением дальше, закомментированным) ;108 чуть ниже ATM экрана, 128 запас около 8 пикс снизу CP C jr nc,DRAWSPRITES0 ;лампы не уменьшаем ;TODO уметь отличать врагов от ламп jr C,$+3 LD C,A ;спрайт слишком близко!!! уменьшим gFILLNCLOSE PUSH BC ;dist ;приводим к 128..255 LD DE,#000 INC B DEC B LD A,C jr Z,MOTOLOGRLQ DUP 5;6 INC D SRL B RRA jr Z,MOTOLOGRLE EDUP MOTOLOGRLQ ; ;OR A ;JP M,$+5 ;>=128 ;LD A,128 ;<128 ;;cp 96 ;;jr nc,$+4 ;;ld a,96 ;спрайт слишком близко!!! увеличим dist для уменьшения высоты MOTOLOGRLE ; LD C,A ;128..255 ;D=0..5 LD B,tlogd/256 LD A,(BC) ;log(dist) = 128..255 for arg>=128 if atm==0 SUB 16;64 ;0..127 for arg=64..127 ;??? endif LD C,A ;0 for arg<64 LD B,tlogd2sca/256 SRA D RR E ;DE=+0,+#80,..+#300 ex de,hl;EXD ADD HL,BC LD C,(HL) ;scale# ex de,hl;EXD ; POP DE ;dist if atm ld a,l ld h,d ld l,e srl h rr l add hl,de ex de,hl ;de = de * 1.5 ld l,a else IF loresspr SLA E RL D ENDIF SLA E RL D ;DE=texx step = de * 4 endif IF loresspr_hires|optresspr RES 0,L ENDIF LD H,distbuf/256+2 ;ID,texx,dist LD A,C ;scale# CP (HL) if !atm ld hx,0xc0 ;TODO endif CALL NC,DRAWSPRITE ;object center is visible ;TODO независимо от видимости центра JP DRAWSPRITES0 ;умножение ;A=+-0.7 ;HL=A*DE ;A сохраняется!!! MULT LD HL,0 MULTADD RLCA JR NC,MULTPLU DUP 6 SRA D RR E RLCA JR C,$+4 SBC HL,DE EDUP RLCA RET C SRA D RR E OR A SBC HL,DE RET MULTPLU DUP 6 SRA D RR E RLCA JR NC,$+3 ADD HL,DE EDUP RLCA RET NC SRA D RR E ADD HL,DE RET OBJMULQ POP AF ;X LD D,#40 ;X out of screen RET ;пересчет координат объекта (Xx=HL, Yy=DE) ;в координаты на экране (DE=xscr, BC=расстояние) OBJMUL PUSH HL ;X PUSH DE ;Y PUSH HL ;X LD HL,(curangle) ;L=центр взгляда LD C,(HL) ;sin=шаг по Y LD A,-64 SUB L LD L,A LD B,(HL) ;-COS=шаг по X ;Bc=DXdy=COSsin LD A,C CPL CALL MULT ;HL=A*DE=-sin*Y POP DE ;X LD A,B CALL MULTADD ;HL=-COS*X-sin*Y=d(расстояние по объекта) POP DE ;Y BIT 7,H jr NZ,OBJMULQ ;если расстояние<0,то объект за спиной=>exit LD (_OBJd1),HL CALL MULT;A=B=-COS, HL=-COS*Y POP DE ;X LD A,C CALL MULTADD ;HL=-COS*Y+sin*X=xscr*d ex de,hl;EXD _OBJd1=$+1 LD BC,0 ;BC=d ;после MONDIV получим DE=xscr ;jp MONDIV ENDIF ;sprites ;деление ;DE=+-7.8;BC=+7.8 ;DE=DE/BC=+-8.7/2 ;BC сохраняется!!! MONDIV LD H,0 LD A,D SLA E RLA JP C,MONDIVNEG ;если делимое<0 LD L,A INC E LD A,E DUP 7 SBC HL,BC JR NC,$+3 ADD HL,BC RLA ADC HL,HL EDUP CPL LD D,A DUP 7 SBC HL,BC JR NC,$+3 ADD HL,BC RLA ADD HL,HL EDUP SBC HL,BC JR NC,$+3 ADD HL,BC RLA CPL LD E,A RET ;если делимое<0 MONDIVNEG CPL LD L,A SBC A,A XOR E DUP 7 SBC HL,BC JR NC,$+3 ADD HL,BC RLA ADC HL,HL EDUP LD D,A DUP 7 SBC HL,BC JR NC,$+3 ADD HL,BC RLA ADD HL,HL EDUP SBC HL,BC JR NC,$+3 ADD HL,BC RLA LD E,A RET