?login_element?

Subversion Repositories NedoOS

Rev

Rev 832 | Blame | Compare with Previous | Last modification | View Log | Download

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