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
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
ld a,(IMavision+1)
sub (hl) ;DIR
inc l ;skip DIR (TODO use)
LD L,(HL) ;TYPE*8+phase
ld H,0
LD BC,MONSTAB-8
ADD HL,BC
if doublescr
;a=mydir-objdir. если около 128, смотрит на нас. около 0 - от нас. около 64 - влево?
sub 32
rlca
rlca
rlca
and 6
add a,ZOMBIEMANrotate-ZOMBIEMANgo
ld c,a ;mydir-objdir
endif
LD A,(HL) ;ID текстуры (в зависимости от фазы)
ld lx,a ;!=0
if doublescr
ld a,l
cp 0xff&(3*8+0 + (MONSTAB-8))
jr z,goside_phase1
cp 0xff&(3*8+1 + (MONSTAB-8))
;jr z,goside_phase2
jr nz,nogoside
goside_phase2
goside_phase1
ld b,0
add hl,bc
ld a,(hl)
ld lx,a
nogoside
endif
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
EXX
LD D,a ;ID (не адрес)
EXX
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