?login_element?

Subversion Repositories NedoOS

Rev

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