?login_element?

Subversion Repositories NedoOS

Rev

Rev 555 | Rev 660 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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