?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. PRSPR_BYSCRADDR=1
  2.  
  3.         macro MASKBYTE
  4.         ld a,(hl)
  5.         and e
  6.         or d
  7.         ld (hl),a
  8.         endm
  9.         macro DOWNBYTE
  10.         add hl,bc
  11.         endm
  12.  
  13. prspr
  14. ;в 4000,8000 уже включен экран (setpgsscr40008000)
  15. ;iy=sprite data+2 = spraddr+4
  16.        if PRSPR_BYSCRADDR
  17. ;de=scraddr
  18.         ex de,hl
  19.        else
  20. ;e=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1))
  21. ;c=y = -(sprmaxhgt-1)..199 (кодируется как есть)
  22.        endif
  23. ;(iy-3)=sprhgt
  24. ;(iy-4)=sprwid
  25. ;по x,y, ширине, высоте найти адрес на экране, куда выводим видимую часть спрайта
  26. ;спрайт полной высоты и ширины должен работать максимально быстро!
  27.        if PRSPR_BYSCRADDR
  28.         ld hx,0xff
  29.        else
  30.         ld a,scrwid+(sprmaxwid-1)
  31.         sub e ;x ;a=расстояние до правой границы экрана
  32.         ld hx,a
  33.         ;ld lx,0 ;по умолчанию нет фальшивого экрана, выход по правой границе экрана будет сразу ;для полной ширины не надо - выход будет по окончанию спрайта
  34.          ;ld lx,0 ;для спрайта полной высоты, клипированного справа - выход сразу на границе
  35.         ld a,e ;x
  36.         sub sprmaxwid-1
  37.         jr nc,prsprnocropleft
  38. ;[найти адрес начала видимой части спрайта:]
  39. ;[сначала столбец (прибавить hgt*2*число скрытых столбцов) можно в цикле, т.к. пропуск столбцов бывает редко]
  40. ;или включить фальшивый экран в 0x4000,0x8000 и заменить адреса выхода на переключалку страниц, так можно работать со спрайтами процедурой
  41. ;a=-число отрезанных слева столбцов
  42. ;посчитать hx для правильного выхода из фальшивого экрана
  43. ;посчитать lx для правильного выхода из спрайта в y-клипированной выводилке
  44.         ld l,a
  45.         add a,(iy-4)
  46.         ld lx,a ;sprwid-число отрезанных слева столбцов
  47. ;если <=0, то спрайта нет на экране!!! выходим!!!
  48.          ret m
  49.          ret z
  50.         xor a
  51.         sub l
  52.         ld hx,a ;число отрезанных слева столбцов
  53.         push bc
  54.         ld a,(pgfake)
  55.         ;ld (curpg4000),a
  56.         SETPG16K
  57.         ;ld (curpg8000),a
  58.         SETPG32KLOW
  59. ;hl будет вычислен с ошибкой +64
  60.         pop bc
  61.         ld a,l
  62.         or a
  63. prsprnocropleft
  64.        endif
  65.         ld (prsprqsp),sp
  66.        if PRSPR_BYSCRADDR
  67.         ld bc,40
  68.        else
  69. ;NC
  70.         ld b,0
  71.         ld l,c ;y
  72.         rra ;x bit 0
  73.         ;ld h,0x40/32/2
  74.         ;jr nc,$+4 ;x bit 0
  75.         ; ld h,0x80/32/2
  76.          ld h,b;0
  77.          rl h
  78.          inc h
  79.         srl a ;x bit 1
  80.          rl h ;0x40/32/2 или 0x80/32/2
  81.         add hl,hl
  82.         add hl,hl
  83.         add hl,bc
  84.         add hl,hl
  85.         add hl,hl
  86.         add hl,hl ;y*40+scrbase
  87.          if scrbase&0xff
  88.          add a,scrbase&0xff
  89.          endif
  90. ;a=x/4
  91.         add a,l
  92.         ld l,a
  93.         adc a,h
  94.         sub l
  95.         ld h,a ;hl=scr ;не может быть переполнения при отрицательных x? maxhl = 199*40 + 127 = 8087
  96.         ld a,c ;y
  97.         ;add a,sprmaxhgt-1
  98.         ;sub sprmaxhgt-1
  99.         ;jp c,prsprcroptop
  100.          cp scrhgt
  101.          jp nc,prsprcroptop
  102.         add a,(iy-3) ;sprhgt
  103. prspr_curscrhgtplus1=$+1
  104.         cp scrhgt+1 ;200=OK, >200=crop
  105.         jp nc,prsprcropbottom        
  106. ;hx=расстояние до правой границы экрана (columns)
  107. ;x=156: hx=4
  108. ;x=157: hx=3
  109. ;x=158: hx=2
  110. ;x=159: hx=1
  111. ;если нет клипирования справа, то при нечётном x и чётном sprwid надо сделать строго hx>sprwid/2!
  112. ;lx важен только при клипировании слева
  113.          ld a,hx
  114.          inc a
  115.          srl a
  116.          ld hx,a ;lx не пересчитываем, он завышен в 2 раза, но тут в полном спрайте есть выход по ширине раньше
  117. ;hx=расстояние до правой границы экрана (double columns)
  118. ;x=156: hx=2
  119. ;x=157: hx=2
  120. ;x=158: hx=1
  121. ;x=159: hx=1
  122.         ld c,40 ;b=0
  123.        endif
  124. ;iy=sprite data+2
  125.         ld e,(iy-2)
  126.         ld d,(iy-1)
  127.         ld sp,iy
  128. ;выбрать ветку в зависимости от sprhgt
  129.         ld a,(iy-3) ;sprhgt
  130.         cp 16
  131.         jr z,prspr16
  132.         jr nc,prspr24
  133. prspr8
  134.         ld a,prspr8column&0xff
  135.         ld (prsprcolumnpatch),a
  136.         ld (prsprcolumnpatch2),a
  137.         jp prspr8column+1
  138. prspr16
  139.         ld a,prspr16column&0xff
  140.         ld (prsprcolumnpatch),a
  141.         ld (prsprcolumnpatch2),a
  142.         jp prspr16column+1
  143. prspr24
  144.         cp 32
  145.         jr z,prspr32
  146.         ld a,prspr24column&0xff
  147.         ld (prsprcolumnpatch),a
  148.         ld (prsprcolumnpatch2),a
  149.         jp prspr24column+1
  150. prspr32
  151.         ld a,prspr32column&0xff
  152.         ld (prsprcolumnpatch),a
  153.         ld (prsprcolumnpatch2),a
  154.         jp prspr32column+1
  155.         align 256
  156. ;отдельная процедура для спрайта полной высоты, т.к. там не надо на каждом столбце переставлять sp
  157. prspr32column
  158.         dup 8
  159.         pop de
  160.         MASKBYTE
  161.         DOWNBYTE
  162.         edup
  163. prspr24column
  164.         dup 8
  165.         pop de
  166.         MASKBYTE
  167.         DOWNBYTE
  168.         edup
  169. prspr16column
  170.         dup 8
  171.         pop de
  172.         MASKBYTE
  173.         DOWNBYTE
  174.         edup
  175. prspr8column
  176.         display prspr32column," HSB equal to ",$
  177.         dup 7
  178.         pop de
  179.         MASKBYTE
  180.         DOWNBYTE
  181.         edup
  182.         pop de
  183.         MASKBYTE
  184. ;найти адрес следующего столбца на экране или выйти        
  185. ;4000,8000,[c000]6000,a000,[e001]4001... ;единственное расположение для такой логики (из-за константы 0xa0) (другой вариант - константа 0x60? тогда надо экран в 0000!!!)
  186. ;нельзя использовать строки, где h=0xa0, т.е. верхние 7 строк (остаётся 193 строки), иначе надо ld a,0x9f...inc a (+2t)
  187.         pop de ;годится только для спрайтов полной высоты (не прокатит даже если делать pop всех данных столбца, т.к. сдвиг hl разный - разве что и hl сдвигать при клипировании)
  188.         ld a,0x9f;0xa0
  189.         cp h
  190.         adc hl,de ;de = 0x4000 - ((sprhgt-1)*40)
  191.          ret c ;выход по ширине спрайта, там надо восстановить sp и константу в стеке
  192. prsprcolumnpatch=$+1
  193.         jp pe,prspr16column ;в половине случаев
  194. ;8000->с000 (надо 6000) или a000->e001 (надо 4001)
  195.          inc a
  196.         xor h
  197.         ld h,a
  198.          dec hx
  199. goprsprcolumn
  200.          jp nz,prspr16column
  201. prsprcolumnpatch2=$-2
  202.          ;выход по границе экрана
  203. ;10+11+15+14 = 40t (+5+9)
  204. ;это может быть граница фальшивого экрана! надо иметь возможность продолжить (с hl-64 из-за ошибки адреса при отрицательных x?)
  205. ;        ld a,(pgfake)
  206. ;curpg4000=$+1
  207.         ld a,(curpg16k) ;ok
  208. pgfake2=$+1
  209.         cp 0
  210.         jp nz,prsprqright ;действительно выход по правой границе
  211. ;был фальшивый экран для клипирования по левой границе, продолжаем на настоящем экране
  212.         ld hx,lx
  213.         ld bc,-64
  214.         add hl,bc ;из-за ошибки адреса при отрицательных x
  215.          dec c ;NZ!!!
  216. ;как не запороть стек? даже если инлайнить вызов, там внутри всё равно rst
  217.         ld (prsprmaybeqrightsp),sp
  218.         ld sp,tempsp
  219.         call setpgsscr40008000 ;выключаем фальшивый экран, включаем настоящий
  220. prsprmaybeqrightsp=$+1
  221.         ld sp,0
  222.         ld bc,40
  223.         ;ld lx,b;0 ;второй раз будет действительно выход
  224.         jp goprsprcolumn ;NZ!!!
  225. ;можно то же самое сделать при спрайте кодом (патчи не нужны, de присваивать только если меняется, 13-1 байт (36.5t) лишних на столбец, выход по dec hx:ret z и просто ret в конце)
  226. ;а как делать вход в середину, если спрайты кодом, а de присваивается только при изменении? сначала рисовать в фальшивый экран и переключать по call z?
  227. ;но клипирование по y уже надо делать с данными спрайта, а не с кодом (т.е. нужна копия спрайта в виде данных)
  228.  
  229. ;выход по ширине спрайта (сюда попали по ret)
  230. prsprqwid
  231. ;у нас de взят с прошлого раза, и обработчик прерываний может запороть стек
  232.         ld hl,$
  233.         push hl ;если произошло прерывание, то теперь стек в порядке
  234. prsprqright
  235. prsprqsp=$+1
  236.         ld sp,0
  237.         ret
  238.  
  239.        
  240. ;для вывода спрайта неполной высоты:
  241.  
  242. ;клипирование снизу
  243. prsprcropbottom
  244. ;a=sprbottom
  245. ;e?1=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1))
  246. ;c?2=y = -(sprmaxhgt-1)..199 (кодируется как есть)
  247. ;(iy-3)?3=sprhgt
  248. ;(iy-4)?4=sprwid
  249. ;hl=scr
  250. prspr_curscrhgt=$+1
  251.         sub scrhgt;200
  252.         ;sub (iy-3) ;sprhgt
  253.          ld d,(iy-3) ;sprhgt
  254.          sub d
  255.         ld c,a ;-sprvisiblehgt = sprbottom-200-sprhgt
  256. ;если клипировано слева, то сейчас lx = sprwid-число отрезанных слева столбцов
  257. ;иначе lx не задано
  258.        
  259.         ld a,(iy-4) ;sprwid
  260.         cp hx ;расстояние до правого края экрана
  261.         ;jr nc,$
  262.         jr nc,prsprcropygo;_cropx ;берём меньшее из sprwid и расстояния до правой границы экрана
  263.         ld hx,a
  264.         jp prsprcropygo
  265.  
  266. prsprcroptop
  267. ;a=sprtop
  268. ;e?1=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1))
  269. ;c?2=y = -(sprmaxhgt-1)..199 (кодируется как есть)
  270. ;(iy-3)?3=sprhgt
  271. ;(iy-4)?4=sprwid
  272. ;hl=scr неверный (выше экрана)
  273.        
  274.         neg ;a=number of lines to crop
  275.          ld d,(iy-3) ;sprhgt
  276.          sub d
  277. ;a = -sprvisiblehgt = -(sprtop+sprhgt) = linestocrop-sprhgt
  278. ;если sprvisiblehgt<=0, то спрайта нет на экране!!! выходим!!!
  279.          ret p
  280.         ld c,a ;-sprvisiblehgt = -(sprtop+sprhgt) = linestocrop-sprhgt
  281.  
  282. ;если клипировано слева, то сейчас lx = sprwid-число отрезанных слева столбцов
  283. ;иначе lx не задано
  284.        
  285.         ld a,(iy-4) ;sprwid
  286.         cp hx ;расстояние до правого края экрана
  287.         jr nc,prsprcropygo_cropx ;берём меньшее из sprwid и расстояния до правой границы экрана
  288.         ld hx,a
  289. prsprcropygo_cropx
  290.  
  291.          ld a,c
  292.          add a,d ;a=number of lines to crop
  293.         add a,a
  294. ;прибавить 2*число скрытых строк к адресу
  295.         add a,ly
  296.         ld ly,a
  297.         jr nc,$+4
  298.         inc hy
  299.        
  300.         ld a,e ;x
  301.         sub sprmaxwid-1 ;NC для положительных x
  302.         srl a
  303.         ld h,0x40
  304.         jr nc,$+4 ;x bit 0
  305.          ld h,0x80
  306.         srl a
  307.         jr nc,$+4 ;x bit 1
  308.          set 5,h
  309.        if scrbase&0xff
  310.        add a,scrbase&0xff
  311.        endif
  312.         ld l,a
  313.        
  314. prsprcropygo
  315. ;d=(iy-3)?3=sprhgt
  316. ;(iy-4)?4=sprwid
  317.         ld a,d ;sprhgt
  318.         ;add a,c ;-sprvisiblehgt
  319.         ; add a,3 ;inc a
  320.         ;add a,a
  321.         ;ld (prsprNspraddpatch),a ;2*(sprhgt-sprvisiblehgt)+2 +4
  322.          inc a
  323.          add a,a
  324.         ld (prsprNspraddpatch),a ;2*sprhgt+2
  325.  
  326.         ld a,c ;-sprvisiblehgt
  327.         add a,a
  328.         add a,c
  329.         add a,a
  330.         ld (prsprNpatch),a ;PRSPR24 и т.п. (по 6 байт)        
  331.  
  332.         ex de,hl
  333.          ;ld b,-1 ;убрать за счёт перемещения ld h
  334.          ;ld h,0x40/32-1
  335.          inc c
  336.         ld l,c ;-sprvisiblehgt
  337.         add hl,hl
  338.         add hl,hl
  339.          ld h,0x40/8-1 -1
  340.          jr nz,$+4
  341.          ld h,0x40/8 ;для sprvisiblehgt-1 == 0
  342.         add hl,bc
  343.         add hl,hl
  344.         add hl,hl
  345.         add hl,hl
  346.         ld (prsprNscraddpatch),hl ;0x4000 - ((sprvisiblehgt-1)*40)
  347.         ex de,hl
  348.  
  349. ;hl=scr
  350.         ;ld c,40
  351.         jp prsprN
  352.  
  353. ;выравнивание на нужный младший байт адреса:
  354. _lowaddr=256-(sprmaxhgt*6)
  355.         ds (_lowaddr-$)&0xff
  356. ;младший байт адреса равен 256-(sprvisiblehgt*6)
  357. PRSPR32
  358.         dup 8
  359.         MASKBYTE
  360.         DOWNBYTE
  361.         pop de
  362.         edup
  363. PRSPR24
  364.         MASKBYTE
  365.         DOWNBYTE
  366.         pop de
  367. PRSPR23
  368.         MASKBYTE
  369.         DOWNBYTE
  370.         pop de
  371. PRSPR22
  372.         MASKBYTE
  373.         DOWNBYTE
  374.         pop de
  375. PRSPR21
  376.         MASKBYTE
  377.         DOWNBYTE
  378.         pop de
  379. PRSPR20
  380.         MASKBYTE
  381.         DOWNBYTE
  382.         pop de
  383. PRSPR19
  384.         MASKBYTE
  385.         DOWNBYTE
  386.         pop de
  387. PRSPR18
  388.         MASKBYTE
  389.         DOWNBYTE
  390.         pop de
  391. PRSPR17
  392.         MASKBYTE
  393.         DOWNBYTE
  394.         pop de
  395. PRSPR16
  396.         MASKBYTE
  397.         DOWNBYTE
  398.         pop de
  399. PRSPR15
  400.         MASKBYTE
  401.         DOWNBYTE
  402.         pop de
  403. PRSPR14
  404.         MASKBYTE
  405.         DOWNBYTE
  406.         pop de
  407. PRSPR13
  408.         MASKBYTE
  409.         DOWNBYTE
  410.         pop de
  411. PRSPR12
  412.         MASKBYTE
  413.         DOWNBYTE
  414.         pop de
  415. PRSPR11
  416.         MASKBYTE
  417.         DOWNBYTE
  418.         pop de
  419. PRSPR10
  420.         MASKBYTE
  421.         DOWNBYTE
  422.         pop de
  423. PRSPR9
  424.         MASKBYTE
  425.         DOWNBYTE
  426.         pop de
  427. PRSPR8
  428.         MASKBYTE
  429.         DOWNBYTE
  430.         pop de
  431. PRSPR7
  432.         MASKBYTE
  433.         DOWNBYTE
  434.         pop de
  435. PRSPR6
  436.         MASKBYTE
  437.         DOWNBYTE
  438.         pop de
  439. PRSPR5
  440.         MASKBYTE
  441.         DOWNBYTE
  442.         pop de
  443. PRSPR4
  444.         MASKBYTE
  445.         DOWNBYTE
  446.         pop de
  447. PRSPR3
  448.         MASKBYTE
  449.         DOWNBYTE
  450.         pop de
  451. PRSPR2
  452.         MASKBYTE
  453.         DOWNBYTE
  454.         pop de
  455. PRSPR1
  456.         display PRSPR32," HSB equal to ",$
  457.         MASKBYTE
  458.        
  459. ;найти адрес следующего столбца на экране или выйти        
  460. ;4000,8000,[c000]6000,a000,[e001]4001...
  461. ;восстановить начальный hl
  462. prsprNscraddpatch=$+1
  463.         ld bc,0 ;bc = 0x4000 - ((sprvisiblehgt-1)*40)
  464.         ld a,0x9f;0xa0
  465.         cp h
  466.         adc hl,bc
  467.         jp pe,prsprNcolumnq ;в половине случаев
  468. ;8000->с000 (надо 6000) или a000->e001 (надо 4001)
  469.          inc a
  470.         xor h
  471.         ld h,a
  472. prsprNcolumnq
  473.         dec hx
  474.         jp z,prsprNmaybeqright ;это может быть граница фальшивого экрана! надо иметь возможность продолжить (с hl-64 из-за ошибки адреса при отрицательных x?)
  475. prsprNcolumnqq
  476. ;найти адрес данных следующего столбца спрайта
  477. ;можно просто сделать много пустых pop de, т.к. пропуск строк бывает редко
  478. prsprNspraddpatch=$+1
  479.         ld bc,0 ;bc = 2*(sprhgt-sprvisiblehgt)+2
  480.         add iy,bc
  481. prsprN
  482. ;iy=sprite data
  483.         ld c,40
  484.         ld sp,tempsp ;чтобы не намусорить новым de в старых данных
  485.         ld e,(iy-2)
  486.         ld d,(iy-1)
  487.         ld sp,iy
  488. prsprNpatch=$+1
  489.         jp PRSPR24
  490.        
  491. prsprNmaybeqright
  492. ;curpg8000=$+1
  493. ;        ld a,0
  494.         ld a,(curpg32klow) ;ok
  495. pgfake=$+1
  496.         cp 0
  497.         jp nz,prsprqright ;действительно выход
  498.         ld hx,lx
  499.         ld bc,-64
  500.         add hl,bc ;из-за ошибки адреса при отрицательных x
  501.         ld sp,tempsp
  502.         call setpgsscr40008000 ;выключаем фальшивый экран, включаем настоящий
  503.         ;ld bc,40
  504.         ;ld lx,b;0 ;второй раз будет действительно выход
  505.         jp prsprNcolumnqq
  506.