home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / enterprs / c128 / text / hacking6.arc / DYCP.TXT < prev    next >
Text File  |  1993-09-16  |  21KB  |  514 lines

  1.  
  2. ================================================================================
  3. The Demo Corner: DYCP - Horizontal Scrolling
  4. by Pasi 'Albert' Ojala (po87553@cs.tut.fi or albert@cc.tut.fi))
  5.         Written: 16-May-91 Translation 02-Jun-92
  6.  
  7.     DYCP - too many sprites !?
  8.     --------------------------
  9.  
  10. DYCP - Different Y Character Position - is a name for a horizontal scroller,
  11. where characters go smoothly up and down during their voyage from right to
  12. left. One possibility is a scroll with 8 characters - one character in each
  13. sprite, but a real demo coder won't be satisfied with that.
  14.  
  15. Demo coders thought that it looks good to make the scrolling text change its
  16. vertical position in the same time it proceeded from the right side of the
  17. screen to the left. The only problem is that there is only eight sprites
  18. and that is not even nearly enough to satisfy the requirements needed for
  19. great look. So the only way is to use screen and somehow plot the text in
  20. graphics, because character columns can not be scrolled individually.
  21. Plotting the characters take absolutely too much time, because you have to
  22. handle each byte seperately and the graphics bitmap must be cleared too.
  23.  
  24.  
  25. _Character hack_
  26.  
  27. The whole DYCP started using character graphics. You plot six character
  28. rows where the character (screen) codes increase to the right and down.
  29. This area is then used like a small bitmap screen. Each of the text chars
  30. are displayed one byte at a time on each six rows high character columns.
  31. This 240 character positions big piece of screen can be moved horizontally
  32. using the x-scroll register (three lowest bits in $D016) and after eight
  33. pixels you move the text itself, like in any scroll. The screen is of course
  34. reduced to 38 columns wide to hide the jittering on the sides.
  35.  
  36. A good coder may also change the character sets during the display and
  37. even double the size of the scroll, but because the raster time happens
  38. to go to waste using this technique anyway, that is not very feasible. There
  39. are also other difficulties in this approach, the biggest is the time needed
  40. to clear the display.
  41.  
  42.  
  43. _Save characters - and time_
  44.  
  45. But why should we move an eight-byte-high character image in a 48-line-high
  46. area, when 16 is really enough ?  We can use two characters for the graphics
  47. bitmap and then move this in eight pixel steps up and down. The lowest
  48. three bits of the y-position then gives us the offset where the data must
  49. be plotted inside this graphical region. The two character codes are usually
  50. selected to be consecutive ones so that the image data has also 16
  51. consecutive bytes. [See picture 1.]
  52.  
  53.  
  54. _Demo program might clear things up_
  55.  
  56. The demo program is coded using the latter algorithm. The program first
  57. copies the Character ROM to ram, because it is faster to use it from there.
  58. You can easily change the program to use your own character set instead,
  59. if you like. The sinus data for the vertical movement is created of a 1/4
  60. of a cycle by mirroring it both horizontally and vertically.
  61.  
  62. Two most time critical parts are clearing the character set and plotting the
  63. new one. Neither of these may happen when VIC is drawing the area where the
  64. scroll is, so there is a slight hurry. Using double buffering technique we
  65. could overcome this limitation, but this is just an example program. For
  66. speed there is CLC only when it is absolutely needed.
  67.  
  68. The NTSC version is a bit crippled, it only covers 32 columns and thus the
  69. characters seem to appear from thin air. Anyway, the idea should become
  70. clear.
  71.  
  72.  
  73. _Want to go to the border ?_
  74.  
  75. Some coders are always trying to get all effects ever done using the C64 go
  76. to the border, and even successfully. The easiest way is to use only a region
  77. of 21 pixels high - sprites - and move the text exactly like in characters.
  78. In fact only the different addressing causes the differences in the code.
  79.  
  80. Eight horizontally expanded sprites will be just enough to fill the side
  81. borders. You can also mix these techiques, but then you have the usual
  82. "chars-in-the-screen-while-border-opened"-problems (however, they are
  83. solvable). Unfortunately sprite-dycp is even more slower than char-dycp.
  84.  
  85.  
  86. _More movement vertically_
  87.  
  88. You might think that using the sprites will restrict the sinus to only
  89. 14 pixels. Not really, the only restriction is that the vertical position
  90. difference between three consequent text character must be less than 14
  91. pixel lines. Each sprites' Y-coordinate will be the minimum of the three
  92. characters residing in that sprite. Line offsets inside the sprites
  93. are then obtained by subtracting the sprite y-coordinate from the character
  94. y-coordinate. Maybe a little hard to follow, but maybe a picture will
  95. clear the situation. [See picture 2.]
  96.  
  97. Scrolling horizontally is easy. You just have to move sprites like you would
  98. use the character horizontal scroll register and after eight pixels you
  99. reset the sprite positions and scroll the text one position in memory.
  100. And of course, you fetch a new character for the scroll. When we have
  101. different and changing sprite y-coordinates, opening the side borders become
  102. a great deal more difficult. However, in this case there is at least two
  103. different ways to do it.
  104.  
  105.  
  106. _Stretch the sprites_
  107.  
  108. The easiest way is to position all of the sprites where the scroll will
  109. be when it is in its highest position. Then stretch the first and last line
  110. of each sprite so that the 19 sprite lines in the middle will be on the
  111. desired place. Opening the borders now is trivial, because all of the sprites
  112. are present on all of the scan lines and they steal a constant amount of
  113. time. However, we lose two sprite lines. We might not want to use the first
  114. and the last line for graphics, because they are stretched.
  115. [See previous C=Hacking Issues for more information about stretching and
  116.  stolen cycles.]
  117.  
  118. A more difficult approach is to unroll the routine and let another routine
  119. count the sprites present in each line and then change the time the routine
  120. uses accordingly. In this way you save time during the display for other
  121. effects, like color bars, because stretching will take at least 12 cycles
  122. on each raster line. On the other hand, if the sinus is constant (user is
  123. not allowed to change it), it is usually possible to embedd the count
  124. routine directly to the border opening part of the routine.
  125.  
  126.  
  127. _More sprites_
  128.  
  129. You don't necassarily need to plot the characters in sprites to have more
  130. than eight characters. Using a sprite multiplexing techiques you can double
  131. or triple the number of sprites available. You can divide the scroll
  132. vertically into several areas and because the y-coordinate of the scroll
  133. is a sinus, there always is a fixed maximum number of sprites in each area.
  134. This number is always smaller than the total number of sprites in the
  135. whole scroll. I won't go into detail, but didn't want to leave this out
  136. completely. [See picture 3.]
  137.  
  138.  
  139. _Smoother and smoother_
  140.  
  141. Why be satisfied with a scroll with only 40 different slices horizontally ?
  142. It should be possible to count own coordinates for each pixel column on
  143. the scroll. In fact the program won't be much different, but the routine
  144. must also mask the unwanted bits and write the byte to memory with ORA+STA.
  145. When you think about it more, it is obvious that this takes a generous amount
  146. of time, handling every bit seperately will take much more than eight times
  147. the time a simple LDA+STA takes. Some coders have avoided this by plotting
  148. the same character to different character sets simultaneously and then
  149. changing the charsets appropriately, but the resulting scroll won't be much
  150. larger than 96x32 pixels.
  151.  
  152. --------------------------------------------------------------------------
  153. Picture 1 - Two character codes will make a graphical bitmap
  154.  
  155. Screen memory:
  156.  ____________________________________
  157. |Char   |Char   |Char   |Char   |  ...
  158. |Code   |Code   |Code   |Code   |
  159. |0      |2      |80     |80     | .
  160. |       |**  ** |       |       | .
  161. |       |**  ** |       |       | .
  162. |*****  |****** |       |       |
  163. |****** | ****  |       |       |
  164. |**__**_|__**___|_______|_______|
  165. |**  ** |  **   | ****  |Char   |
  166. |**  ** |  **   |****** |Code   |
  167. |****** |       |**  ** |6      |
  168. |*****  |       |**     |       |
  169. |Char   |Char   |**  ** |       |
  170. |Code   |Code   |****** |       |
  171. |1      |3      |4****  |*****  |
  172. |_______|_______|_______|******_|
  173. |Char   |Char   |       |**  ** |
  174. |Code   |Code   |       |****** |
  175. |80     |80     |       |*****  |
  176. |       |       |       |**     |
  177. |       |       |Char   |**ar   |
  178. |       |       |Code   |Code   |
  179. |       |       |5      |7      |
  180. |_______|_______|_______|_______|
  181.  
  182. Character set memory:
  183.  
  184.  _________________________________________________________________
  185. |Char 0 |Char 1 |Char 2 |Char 3 |Char 4 |Char 5 |Char 6 |Char 7 | ...
  186. |_______|_______|_______|_______|_______|_______|_______|_______|__
  187.       DDDDDDDD      YYYYYYYY     CCCCCCCC              PPPPPPPP
  188.  First column    Second column   Third column    Fourth column
  189.  
  190. --------------------------------------------------------------------------
  191. Picture 2 - DYCP with sprites
  192.  
  193. Sprite 0
  194.  _______________________
  195. |       |**  ** |       |
  196. |       |**  ** |       |
  197. |       |****** |       |
  198. |*****  | ****  |       |
  199. |****** |  **   |       |
  200. |**  ** |  **   |       |
  201. |**  ** |  **   |       |
  202. |**__**_|_______|_______|
  203. |****** |       | ****  |
  204. |*****  |       |****** |
  205. |       |       |**  ** |
  206. |       |       |**     |
  207. |       |       |**  ** |
  208. |       |       |****** |
  209. |       |       | ****  |
  210. |_______|_______|_______| Sprite 1
  211. |       |       |       | _______________________
  212. |       |       |       ||*****  |       |       |
  213. |       |       |       ||****** |       |       |
  214. |       |       |       ||**  ** |       |       |
  215. |_______|_______|_______||****** |       |       |
  216.                          |*****  |       |       |
  217.                          |**     |       |       |
  218.                          |**     |       |       |
  219.                          |_______|_______|_______|
  220.                          |       |       |       |
  221.                          |       |       |       |
  222.                          |       |       |       |
  223.                          |       | ****  |       |
  224.                          |       | ****  |       |
  225.                          |       |       |****** |
  226.                          |       |       |****** |
  227.                          |_______|_______|__**___|
  228.                          |       |       |  **   |
  229.                          |       |       |  **   |
  230.                          |       |       |  **   |
  231.                          |       |       |  **   |
  232.                          |_______|_______|_______|
  233.  
  234. --------------------------------------------------------------------------
  235. Picture 3 - Sprite multiplexing
  236.  
  237.                                __          Set coordinates for eight sprites
  238.                             __|3 |         that start from the top half.
  239.                            |4 |  |__
  240.                          __|  `--|2 |
  241.                         |5 `--'  |  |
  242.                         |  |     `--'__
  243.                         `--'        |1 |
  244.                                     |  |
  245.                       __            `--'
  246.                      |6 |
  247.                      |  |               __
  248.                      `--'              |0 |
  249.                                        |  |
  250. -__------------------------------------`--'When VIC has displayed the last
  251. |0 |               __                      sprite, set coordinates for the
  252. |  |              |6 |                     sprites in the lower half of the
  253. `--'              |  |                     area.
  254.                   `--'
  255.     __
  256.    |1 |         __
  257.    |  |        |5 |
  258.    `-- __      |  |
  259.       |2 |   __`--'
  260.       |  |__|4 |                           You usually have two sprites that
  261.       `--|3 |  |                           are only 'used' once so that you
  262.          |  `--'                           can change other sprites when VIC
  263.          `__'                              is displaying them.
  264. --------------------------------------------------------------------------
  265.  
  266. DYCP demo program (PAL)
  267.  
  268.  
  269. SINUS=  $CF00   ; Place for the sinus table
  270. CHRSET= $3800   ; Here begins the character set memory
  271. GFX=    $3C00   ; Here we plot the dycp data
  272. X16=    $CE00   ; values multiplicated by 16 (0,16,32..)
  273. D16=    $CE30   ; divided by 16  (16 x 0,16 x 1 ...)
  274. START=  $033C   ; Pointer to the start of the sinus
  275. COUNTER= $033D  ; Scroll counter (x-scroll register)
  276. POINTER= $033E  ; Pointer to the text char
  277. YPOS=   $0340   ; Lower 4 bits of the character y positions
  278. YPOSH=  $0368   ; y positions divided by 16
  279. CHAR=   $0390   ; Scroll text characters, multiplicated by eight
  280. ZP=     $FB     ; Zeropage area for indirect addressing
  281. ZP2=    $FD
  282. AMOUNT= 38      ; Amount of chars to plot-1
  283. PADCHAR= 32     ; Code used for clearing the screen
  284.  
  285. *= $C000
  286.  
  287.         SEI             ; Disable interrupts
  288.         LDA #$32        ; Character generator ROM to address space
  289.         STA $01
  290.         LDX #0
  291. LOOP0   LDA $D000,X     ; Copy the character set
  292.         STA CHRSET,X
  293.         LDA $D100,X
  294.         STA CHRSET+256,X
  295.         DEX
  296.         BNE LOOP0
  297.         LDA #$37        ; Normal memory configuration
  298.         STA $01
  299.         LDY #31
  300. LOOP1   LDA #66         ; Compose a full sinus from a 1/4th of a
  301.         CLC             ;   cycle
  302.         ADC SIN,X
  303.         STA SINUS,X
  304.         STA SINUS+32,Y
  305.         LDA #64
  306.         SEC
  307.         SBC SIN,X
  308.         STA SINUS+64,X
  309.         STA SINUS+96,Y
  310.         INX
  311.         DEY
  312.         BPL LOOP1
  313.         LDX #$7F
  314. LOOP2   LDA SINUS,X
  315.         LSR
  316.         CLC
  317.         ADC #32
  318.         STA SINUS+128,X
  319.         DEX
  320.         BPL LOOP2
  321.  
  322.         LDX #39
  323. LOOP3   TXA
  324.         ASL
  325.         ASL
  326.         ASL
  327.         ASL
  328.         STA X16,X       ; Multiplication table (for speed)
  329.         TXA
  330.         LSR
  331.         LSR
  332.         LSR
  333.         LSR
  334.         CLC
  335.         ADC #>GFX
  336.         STA D16,X       ; Dividing table
  337.         LDA #0
  338.         STA CHAR,X      ; Clear the scroll
  339.         DEX
  340.         BPL LOOP3
  341.         STA POINTER     ; Initialize the scroll pointer
  342.         LDX #7
  343.         STX COUNTER
  344. LOOP10  STA CHRSET,X    ; Clear the @-sign..
  345.         DEX
  346.         BPL LOOP10
  347.  
  348.         LDA #>CHRSET    ; The right page for addressing
  349.         STA ZP2+1
  350.         LDA #<IRQ       ; Our interrupt handler address
  351.         STA $0314
  352.         LDA #>IRQ
  353.         STA $0315
  354.         LDA #$7F        ; Disable timer interrupts
  355.         STA $DC0D
  356.         LDA #$81        ; Enable raster interrupts
  357.         STA $D01A
  358.         LDA #$A8        ; Raster compare to scan line $A8
  359.         STA $D012
  360.         LDA #$1B        ; 9th bit
  361.         STA $D011
  362.         LDA #30
  363.         STA $D018       ; Use the new charset
  364.         CLI             ; Enable interrupts and return
  365.         RTS
  366.  
  367. IRQ     INC START       ; Increase counter
  368.         LDY #AMOUNT
  369.         LDX START
  370. LOOP4   LDA SINUS,X     ; Count a pointer for each text char and according
  371.         AND #7          ;  to it fetch a y-position from the sinus table
  372.         STA YPOS,Y      ;   Then divide it to two bytes
  373.         LDA SINUS,X
  374.         LSR
  375.         LSR
  376.         LSR
  377.         STA YPOSH,Y
  378.         INX             ; Chars are two positions apart
  379.         INX
  380.         DEY
  381.         BPL LOOP4
  382.  
  383.         LDA #0
  384.         LDX #79
  385. LOOP11  STA GFX,X       ; Clear the dycp data
  386.         STA GFX+80,X
  387.         STA GFX+160,X
  388.         STA GFX+240,X
  389.         STA GFX+320,X
  390.         STA GFX+400,X
  391.         STA GFX+480,X
  392.         STA GFX+560,X
  393.         DEX
  394.         BPL LOOP11
  395.  
  396. MAKE    LDA COUNTER     ; Set x-scroll register
  397.         STA $D016
  398.         LDX #AMOUNT
  399.         CLC             ; Clear carry
  400. LOOP5   LDY YPOSH,X     ; Determine the position in video matrix
  401.         TXA
  402.         ADC LINESL,Y    ; Carry won't be set here
  403.         STA ZP          ; low byte
  404.         LDA #4
  405.         ADC LINESH,Y
  406.         STA ZP+1        ; high byte
  407.         LDA #PADCHAR    ; First clear above and below the char
  408.         LDY #0          ; 0. row
  409.         STA (ZP),Y
  410.         LDY #120        ; 3. row
  411.         STA (ZP),Y
  412.         TXA             ; Then put consecuent character codes to the places
  413.         ASL             ;  Carry will be cleared
  414.         ORA #$80    ; Inverted chars
  415.         LDY #40         ; 1. row
  416.         STA (ZP),Y
  417.         ADC #1          ; Increase the character code, Carry won't be set
  418.         LDY #80         ; 2. row
  419.         STA (ZP),Y
  420.  
  421.         LDA CHAR,X      ; What character to plot ? (source)
  422.         STA ZP2         ;  (char is already multiplicated by eight)
  423.         LDA X16,X       ; Destination low byte
  424.         ADC YPOS,X      ;  (16*char code + y-position's 3 lowest bits)
  425.         STA ZP
  426.         LDA D16,X       ; Destination high byte
  427.         STA ZP+1
  428.  
  429.         LDY #6          ; Transfer 7 bytes from source to destination
  430.         LDA (ZP2),Y : STA (ZP),Y
  431.         DEY             ; This is the fastest way I could think of.
  432.         LDA (ZP2),Y : STA (ZP),Y
  433.         DEY
  434.         LDA (ZP2),Y : STA (ZP),Y
  435.         DEY
  436.         LDA (ZP2),Y : STA (ZP),Y
  437.         DEY
  438.         LDA (ZP2),Y : STA (ZP),Y
  439.         DEY
  440.         LDA (ZP2),Y : STA (ZP),Y
  441.         DEY
  442.         LDA (ZP2),Y : STA (ZP),Y
  443.         DEX
  444.         BPL LOOP5    ; Get next char in scroll
  445.  
  446.         LDA #1
  447.         STA $D019       ; Acknowledge raster interrupt
  448.  
  449.         DEC COUNTER     ; Decrease the counter = move the scroll by 1 pixel
  450.         BPL OUT
  451. LOOP12  LDA CHAR+1,Y    ; Move the text one position to the left
  452.         STA CHAR,Y      ;  (Y-register is initially zero)
  453.         INY
  454.         CPY #AMOUNT
  455.         BNE LOOP12
  456.         LDA POINTER
  457.         AND #63         ; Text is 64 bytes long
  458.         TAX
  459.         LDA SCROLL,X    ; Load a new char and multiply it by eight
  460.         ASL
  461.         ASL
  462.         ASL
  463.         STA CHAR+AMOUNT ; Save it to the right side
  464.         DEC START       ; Compensation for the text scrolling
  465.         DEC START
  466.         INC POINTER     ; Increase the text pointer
  467.         LDA #7
  468.         STA COUNTER     ; Initialize X-scroll
  469.  
  470. OUT     JMP $EA7E       ; Return from interrupt
  471.  
  472. SIN     BYT 0,3,6,9,12,15,18,21,24,27,30,32,35,38,40,42,45
  473.         BYT 47,49,51,53,54,56,57,59,60,61,62,62,63,63,63
  474.                         ; 1/4 of the sinus
  475.  
  476. LINESL  BYT 0,40,80,120,160,200,240,24,64,104,144,184,224
  477.         BYT 8,48,88,128,168,208,248,32
  478.  
  479. LINESH  BYT 0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,3
  480.  
  481. SCROLL  SCR "THIS@IS@AN@EXAMPLE@SCROLL@FOR@"
  482.         SCR "COMMODORE@MAGAZINE@BY@PASI@OJALA@@"
  483.                         ; SCR will convert text to screen codes
  484.  
  485. --------------------------------------------------------------------------
  486. Basic loader for the Dycp demo program (PAL)
  487.  
  488. 1 S=49152
  489. 2 DEFFNH(C)=C-48+7*(C>64)
  490. 3 CH=0:READA$,A:PRINTA$:IFA$="END"THENPRINT"<white><clr>":SYS49152:END
  491. 4 FORF=0TO31:Q=FNH(ASC(MID$(A$,F*2+1)))*16+FNH(ASC(MID$(A$,F*2+2)))
  492. 5 CH=CH+Q:POKES,Q:S=S+1:NEXT:IFCH=ATHEN3
  493. 6 PRINT"CHECKSUM ERROR":END
  494. 100 DATA 78A9328501A200BD00D09D0038BD00D19D0039CAD0F1A9378501A01FA942187D, 3441
  495. 101 DATA 75C19D00CF9920CFA94038FD75C19D40CF9960CFE88810E4A27FBD00CF4A1869, 4302
  496. 102 DATA 209D80CFCA10F3A2278A0A0A0A0A9D00CE8A4A4A4A4A18693C9D30CEA9009D90, 3231
  497. 103 DATA 03CA10E58D3E03A2078E3D039D0038CA10FAA93885FEA99B8D1403A9C08D1503, 3338
  498. 104 DATA A97F8D0DDCA9818D1AD0A9A88D12D0A91B8D11D0A91E8D18D05860EE3C03A026, 3864
  499. 105 DATA AE3C03BD00CF2907994003BD00CF4A4A4A996803E8E88810EAA900A24F9D003C, 3256
  500. 106 DATA 9D503C9DA03C9DF03C9D403D9D903D9DE03D9D303ECA10E5AD3D038D16D0A226, 3739
  501. 107 DATA 18BC68038A7995C185FBA90479AAC185FCA920A00091FBA07891FB8A0A0980A0, 4224
  502. 108 DATA 2891FB6901A05091FBBD900385FDBD00CE7D400385FBBD30CE85FCA006B1FD91, 4440
  503. 109 DATA FB88B1FD91FB88B1FD91FB88B1FD91FB88B1FD91FB88B1FD91FB88B1FD91FBCA, 6225
  504. 110 DATA 109FEE19D0CE3D031028B99103999003C8C026D0F5AD3E03293FAABDBFC10A0A, 3593
  505. 111 DATA 0A8DB603CE3C03CE3C03EE3E03A9078D3D034C7EEA000306090C0F1215181B1E, 2159
  506. 112 DATA 202326282A2D2F3133353638393B3C3D3E3E3F3F3F00285078A0C8F018406890, 2268
  507. 113 DATA B8E008305880A8D0F82000000000000000010101010101020202020202020314, 1379
  508. 114 DATA 08091300091300010E000518010D100C05001303120F0C0C00060F1200030F0D, 304
  509. 115 DATA 0D0F040F1205000D0107011A090E050002190010011309000F0A010C01000000, 257
  510. 200 DATA END,0
  511.  
  512. ================================================================================
  513.  
  514.