Login

Subversion Repositories NedoOS

Rev

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

       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