?login_element?

Subversion Repositories NedoOS

Rev

Blame | 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,$
  245.         jr nc,prsprcropygo;_cropx ;берём меньшее из sprwid и расстояния до правой границы экрана
  246.         ld hx,a
  247.         jp prsprcropygo
  248.  
  249. prsprcroptop
  250. ;a=sprtop
  251. ;e?1=x = -(sprmaxwid-1)..159 (кодируется как x+(sprmaxwid-1))
  252. ;c?2=y = -(sprmaxhgt-1)..199 (кодируется как есть)
  253. ;(iy-3)?3=sprhgt
  254. ;(iy-4)?4=sprwid
  255. ;hl=scr неверный (выше экрана)
  256.        
  257.         neg ;a=number of lines to crop
  258.          ld d,(iy-3) ;sprhgt
  259.          sub d
  260. ;a = -sprvisiblehgt = -(sprtop+sprhgt) = linestocrop-sprhgt
  261. ;если sprvisiblehgt<=0, то спрайта нет на экране!!! выходим!!!
  262.          ret p
  263.         ld c,a ;-sprvisiblehgt = -(sprtop+sprhgt) = linestocrop-sprhgt
  264.  
  265. ;если клипировано слева, то сейчас lx = sprwid-число отрезанных слева столбцов
  266. ;иначе lx не задано
  267.        
  268.         ld a,(iy-4) ;sprwid
  269.         cp hx ;расстояние до правого края экрана
  270.         jr nc,prsprcropygo_cropx ;берём меньшее из sprwid и расстояния до правой границы экрана
  271.         ld hx,a
  272. prsprcropygo_cropx
  273.  
  274.          ld a,c
  275.          add a,d ;a=number of lines to crop
  276.         add a,a
  277. ;прибавить 2*число скрытых строк к адресу
  278.         add a,ly
  279.         ld ly,a
  280.         jr nc,$+4
  281.         inc hy
  282.        
  283.         ld a,e ;x
  284.         sub sprmaxwid-1 ;NC для положительных x
  285.         srl a
  286.         ld h,0x40
  287.         jr nc,$+4 ;x bit 0
  288.          ld h,0x80
  289.         srl a
  290.         jr nc,$+4 ;x bit 1
  291.          set 5,h
  292.        if scrbase&0xff
  293.        add a,scrbase&0xff
  294.        endif
  295.         ld l,a
  296.        
  297. prsprcropygo
  298. ;d=(iy-3)?3=sprhgt
  299. ;(iy-4)?4=sprwid
  300.         ld a,d ;sprhgt
  301.         ;add a,c ;-sprvisiblehgt
  302.         ; add a,3 ;inc a
  303.         ;add a,a
  304.         ;ld (prsprNspraddpatch),a ;2*(sprhgt-sprvisiblehgt)+2 +4
  305.          inc a
  306.          add a,a
  307.         ld (prsprNspraddpatch),a ;2*sprhgt+2
  308.  
  309.         ld a,c ;-sprvisiblehgt
  310.         add a,a
  311.         add a,c
  312.         add a,a
  313.         ld (prsprNpatch),a ;PRSPR24 и т.п. (по 6 байт)        
  314.  
  315.         ex de,hl
  316.          ;ld b,-1 ;убрать за счёт перемещения ld h
  317.          ;ld h,0x40/32-1
  318.          inc c
  319.         ld l,c ;-sprvisiblehgt
  320.         add hl,hl
  321.         add hl,hl
  322.          ld h,0x40/8-1 -1
  323.          jr nz,$+4
  324.          ld h,0x40/8 ;для sprvisiblehgt-1 == 0
  325.         add hl,bc
  326.         add hl,hl
  327.         add hl,hl
  328.         add hl,hl
  329.         ld (prsprNscraddpatch),hl ;0x4000 - ((sprvisiblehgt-1)*40)
  330.         ex de,hl
  331.  
  332. ;hl=scr
  333.         ;ld c,40
  334.         jp prsprN
  335.  
  336. ;выравнивание на нужный младший байт адреса:
  337. _lowaddr=256-(sprmaxhgt*6)
  338.         ds (_lowaddr-$)&0xff
  339. ;младший байт адреса равен 256-(sprvisiblehgt*6)
  340. PRSPR32
  341.         dup 8
  342.         MASKBYTE
  343.         DOWNBYTE
  344.         pop de
  345.         edup
  346. PRSPR24
  347.         MASKBYTE
  348.         DOWNBYTE
  349.         pop de
  350. PRSPR23
  351.         MASKBYTE
  352.         DOWNBYTE
  353.         pop de
  354. PRSPR22
  355.         MASKBYTE
  356.         DOWNBYTE
  357.         pop de
  358. PRSPR21
  359.         MASKBYTE
  360.         DOWNBYTE
  361.         pop de
  362. PRSPR20
  363.         MASKBYTE
  364.         DOWNBYTE
  365.         pop de
  366. PRSPR19
  367.         MASKBYTE
  368.         DOWNBYTE
  369.         pop de
  370. PRSPR18
  371.         MASKBYTE
  372.         DOWNBYTE
  373.         pop de
  374. PRSPR17
  375.         MASKBYTE
  376.         DOWNBYTE
  377.         pop de
  378. PRSPR16
  379.         MASKBYTE
  380.         DOWNBYTE
  381.         pop de
  382. PRSPR15
  383.         MASKBYTE
  384.         DOWNBYTE
  385.         pop de
  386. PRSPR14
  387.         MASKBYTE
  388.         DOWNBYTE
  389.         pop de
  390. PRSPR13
  391.         MASKBYTE
  392.         DOWNBYTE
  393.         pop de
  394. PRSPR12
  395.         MASKBYTE
  396.         DOWNBYTE
  397.         pop de
  398. PRSPR11
  399.         MASKBYTE
  400.         DOWNBYTE
  401.         pop de
  402. PRSPR10
  403.         MASKBYTE
  404.         DOWNBYTE
  405.         pop de
  406. PRSPR9
  407.         MASKBYTE
  408.         DOWNBYTE
  409.         pop de
  410. PRSPR8
  411.         MASKBYTE
  412.         DOWNBYTE
  413.         pop de
  414. PRSPR7
  415.         MASKBYTE
  416.         DOWNBYTE
  417.         pop de
  418. PRSPR6
  419.         MASKBYTE
  420.         DOWNBYTE
  421.         pop de
  422. PRSPR5
  423.         MASKBYTE
  424.         DOWNBYTE
  425.         pop de
  426. PRSPR4
  427.         MASKBYTE
  428.         DOWNBYTE
  429.         pop de
  430. PRSPR3
  431.         MASKBYTE
  432.         DOWNBYTE
  433.         pop de
  434. PRSPR2
  435.         MASKBYTE
  436.         DOWNBYTE
  437.         pop de
  438. PRSPR1
  439.         display PRSPR32," HSB equal to ",$
  440.         MASKBYTE
  441.        
  442. ;найти адрес следующего столбца на экране или выйти        
  443. ;4000,8000,[c000]6000,a000,[e001]4001...
  444. ;восстановить начальный hl
  445. prsprNscraddpatch=$+1
  446.         ld bc,0 ;bc = 0x4000 - ((sprvisiblehgt-1)*40)
  447.         ld a,0x9f;0xa0
  448.         cp h
  449.         adc hl,bc
  450.         jp pe,prsprNcolumnq ;в половине случаев
  451. ;8000->с000 (надо 6000) или a000->e001 (надо 4001)
  452.          inc a
  453.         xor h
  454.         ld h,a
  455. prsprNcolumnq
  456.         dec hx
  457.         jp z,prsprNmaybeqright ;это может быть граница фальшивого экрана! надо иметь возможность продолжить (с hl-64 из-за ошибки адреса при отрицательных x?)
  458. prsprNcolumnqq
  459. ;найти адрес данных следующего столбца спрайта
  460. ;можно просто сделать много пустых pop de, т.к. пропуск строк бывает редко
  461. prsprNspraddpatch=$+1
  462.         ld bc,0 ;bc = 2*(sprhgt-sprvisiblehgt)+2
  463.         add iy,bc
  464. prsprN
  465. ;iy=sprite data
  466.         ld c,40
  467.         ld sp,tempsp ;чтобы не намусорить новым de в старых данных
  468.         ld e,(iy-2)
  469.         ld d,(iy-1)
  470.         ld sp,iy
  471. prsprNpatch=$+1
  472.         jp PRSPR24
  473.        
  474. prsprNmaybeqright
  475. ;curpg8000=$+1
  476. ;        ld a,0
  477.         ld a,(curpg32klow) ;ok
  478. pgfake=$+1
  479.         cp 0
  480.         jp nz,prsprqright ;действительно выход
  481.         ld hx,lx
  482.         ld bc,-64
  483.         add hl,bc ;из-за ошибки адреса при отрицательных x
  484.         ld sp,tempsp
  485.         call setpgsscr40008000 ;выключаем фальшивый экран, включаем настоящий
  486.         ;ld bc,40
  487.         ;ld lx,b;0 ;второй раз будет действительно выход
  488.         jp prsprNcolumnqq
  489.