base:dysp_d017
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
base:dysp_d017 [2016-04-22 13:09] – created compyx | base:dysp_d017 [2016-04-26 13:52] (current) – added link to github repo compyx | ||
---|---|---|---|
Line 7: | Line 7: | ||
Anyway, a DYSP can be done in many ways, the way I'm describing below is probably the easiest way, since it keeps the timing for each raster line constant by ' | Anyway, a DYSP can be done in many ways, the way I'm describing below is probably the easiest way, since it keeps the timing for each raster line constant by ' | ||
+ | {{: | ||
==== Assembling the code ==== | ==== Assembling the code ==== | ||
- | The code below is in [[http:// | + | The code below is in [[http:// |
- | < | + | < |
+ | Update: The code is now hosted on [[https:// | ||
+ | ==== Sprite stretching theory ==== | ||
+ | |||
+ | I'm not going into detail on how sprite stretching works, there' | ||
===== The Problem ===== | ===== The Problem ===== | ||
- | Moving sprites into the side border is fairly easy, but requires cycle exact timing. There are plenty of articles here which explain this. Using a constant Y-position for the sprites makes timing | + | Moving sprites into the side border is fairly easy, but requires cycle exact timing. There are plenty of articles here which explain this. Using a constant Y-position for the sprites makes the timing |
There' | There' | ||
+ | |||
+ | |||
+ | ===== The Solution ===== | ||
+ | |||
+ | Using the $d017 sprite stretching technique, we can make our sprites arbitrarily high, repeating each line of a sprite for as long as we like. This keeps our border opening routine simple. | ||
+ | |||
+ | Here's the routine, basically an adjusted FLD with side border opening and sprite stretching. | ||
+ | The interesting part is the d017_table access, this allows use to stretch (or not) each line of each sprite: | ||
+ | <code 6502tasm> | ||
+ | ; The $d017 stretcher | ||
+ | ; | ||
+ | ; Basically an FLD with $d017 manipulation and open borders: we use the FLD | ||
+ | ; effect to inhibit bad lines, giving us 63 cycles on each rasterline, of which | ||
+ | ; a lot of cycles get eaten by the sprites | ||
+ | ; | ||
+ | ; At each line we set Y-stretch to false, immediately followed by true, which | ||
+ | ; causes a line of a sprite to be stretched indefinitely. When we set the | ||
+ | ; Y-stretch to false at a line (after the initial false condition), we allow | ||
+ | ; the VIC to update its position in the sprite matrix, thus displaying a line | ||
+ | ; of a sprite | ||
+ | ; | ||
+ | ; This loop can be unrolled and optimized to allow for raster splits, if | ||
+ | ; desired | ||
+ | stretcher | ||
+ | ldy #0 | ||
+ | ldx #0 | ||
+ | - sty $d017 ; set Y-stretch to false | ||
+ | lda d017_table, | ||
+ | sta $d017 | ||
+ | lda d011_table, | ||
+ | bit $ea | ||
+ | nop | ||
+ | nop | ||
+ | dec $d016 ; open side border and do FLD to inhibit | ||
+ | sta $d011 ; bad lines | ||
+ | inc $d016 | ||
+ | inx | ||
+ | cpx #64 | ||
+ | bne - | ||
+ | rts | ||
+ | </ | ||
+ | |||
+ | ==== Stretching the first and last sprite line ==== | ||
+ | |||
+ | The trick to variable Y-positioning is to stretch the first line of a sprite until we reach the Y-position where we want the sprite to display, then displaying 19 lines of the sprite (not stretching the sprite(s)), and then stretching the last line of the sprite until the loop ends. | ||
+ | |||
+ | Suppose we would want to display three sprites, each one one pixel lower than the next. ' | ||
+ | |||
+ | < | ||
+ | Sprites | ||
+ | --------------- | ||
+ | A00 | ||
+ | A01 | ||
+ | A02 | ||
+ | A03 | ||
+ | A04 | ||
+ | ... | ||
+ | A20 | ||
+ | A20 | ||
+ | A20 | ||
+ | </ | ||
+ | |||
+ | ==== Generating the $d017 values ==== | ||
+ | |||
+ | Generating the correct $d017 value is quite simple, but takes some cycles. | ||
+ | |||
+ | * fill $d017 table with $ff (all sprites are stretched) | ||
+ | * for each SPRITE: | ||
+ | - get Y-position of SPRITE | ||
+ | - mask out bits in $d017 table, starting at Y-position, for 19 lines | ||
+ | * next SPRITE | ||
+ | |||
+ | In pseudo-code, | ||
+ | < | ||
+ | ; fill $d017 table with $ff | ||
+ | ldx #0 | ||
+ | lda #$ff | ||
+ | - sta $1000,x | ||
+ | inx | ||
+ | cpx #64 | ||
+ | bne - | ||
+ | |||
+ | ; render sprite 0 | ||
+ | ldy sprite0_y | ||
+ | ldx #0 | ||
+ | - lda $1000,x | ||
+ | and # | ||
+ | sta $1000,x | ||
+ | iny | ||
+ | inx | ||
+ | cpx #19 ; repeat 19 times | ||
+ | bne - | ||
+ | |||
+ | ; more code ... | ||
+ | |||
+ | ; render sprite 7 | ||
+ | ldy sprite7_y | ||
+ | ldx #0 | ||
+ | - lda $1000,x | ||
+ | and # | ||
+ | sta $1000,x | ||
+ | iny | ||
+ | inx | ||
+ | cpx #19 | ||
+ | bne - | ||
+ | </ | ||
+ | |||
+ | ==== Limitations ==== | ||
+ | |||
+ | This of course means we can only use 19 pixels high sprites, lines 0 and 20 are cleared so we don't see the stretched sprite data. | ||
+ | |||
===== The Code ===== | ===== The Code ===== | ||
+ | |||
+ | Putting it all together, we end up with the code below. I use two sinus tables for the X-movement, giving us 344 pixels total movement (actually a little less to avoid the DMA sprite access bug in the right border) and a single sinus for the Y movement. | ||
+ | |||
+ | Again, this code is not up to (my) demo standards: change the border color to non-black and you'll see the border-opening bugs at the start of the routine. | ||
<code 6502tasm> | <code 6502tasm> |
base/dysp_d017.txt · Last modified: 2016-04-26 13:52 by compyx