base:dysp_cycle_table
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
base:dysp_cycle_table [2016-04-26 14:35] – ; compyx | base:dysp_cycle_table [2016-04-26 15:42] – compyx | ||
---|---|---|---|
Line 47: | Line 47: | ||
</ | </ | ||
+ | By altering the branch instruction to skip a variable amount of bytes of code, we can determine the number of cycles the loop must waste on a raster line. Generally speaking, the more sprites we have on a line, the more cycles the VIC eats, which means we have to branch further to skip more cycles. | ||
+ | The "cpx #$e0 ... bit $ea" code is used to waste cycles with an accuracy of a single cycle, I use the same trick to time VSP's (with a few more "cpx #$e0" instructions). | ||
+ | |||
+ | Here's how it works (simplified): | ||
+ | <code 6502tasm> | ||
+ | ; here we waste 2 + 2 + 3 = 7 cycles: | ||
+ | .1000 bpl $1002 | ||
+ | .1002 cpx #$e0 ; 2 | ||
+ | .1004 cpx #$e0 ; 2 | ||
+ | .1006 bit $ea ; 3 | ||
+ | |||
+ | ; adjusting the branch, we can waste 6 cycles: | ||
+ | .1000 bpl $1003 ; we branch into the argument of CPX #$e0 at $1003 | ||
+ | .1002 cpx #$e0 ; which means we execute CPX #$e0 at $1003, | ||
+ | .1004 cpx #$e0 ; then CPX #$24 at $1005 | ||
+ | .1006 bit $ea ; and finally NOP at $1007 | ||
+ | |||
+ | ; so, for the above code , the CPU executes this: | ||
+ | .1000 bpl $1003 | ||
+ | ; .1002 gets skipped | ||
+ | .1003 cpx #$e0 ; 2 | ||
+ | .1005 cpx #$24 ; 2 | ||
+ | .1007 | ||
+ | </ | ||
+ | |||
+ | So for each additional byte we branch over, we either end at BIT $EA (3 cycles) or NOP (2 cycles). Now we can waste anywhere between 0 (no sprites) and 17 cycles (all 8 sprites). | ||
+ | |||
+ | |||
+ | ==== Calculating how many cycles we use ==== | ||
+ | |||
+ | === cycle table == | ||
+ | |||
+ | To determine how many cycles we need to waste, we need to know how many cycles each combination of sprites uses. That's where the ' | ||
+ | |||
+ | The tool is also on [[https:// | ||
+ | |||
+ | === sprite enable table === | ||
+ | |||
+ | Now to determine which values to pick from the ' | ||
+ | |||
+ | For each sprite, at the proper Y-position, we ORA 21 values of the sprite enable table with the bit value for that particular sprite: $01 for sprite 0, $02 for sprite 1, up to $80 for sprite 7. | ||
+ | |||
+ | An illustration might help: suppose we have sprite 0 at Y-offset 0, sprite 1 at Y-offset 3 and sprite 2 at Y-offset 5: | ||
+ | |||
+ | < | ||
+ | Sprite ORA values | ||
+ | Y-offset | ||
+ | -------- | ||
+ | 00 01 01 | ||
+ | 01 01 01 | ||
+ | 02 01 01 | ||
+ | 03 01 02 03 | ||
+ | 04 01 02 03 | ||
+ | 05 01 02 04 07 | ||
+ | 06 01 02 04 07 | ||
+ | </ | ||
+ | |||
+ | === loop timing table === | ||
+ | |||
+ | Using this result, we can use the ' | ||
+ | proper value for the ' | ||
+ | <code 6502tasm> | ||
+ | ldx #0 | ||
+ | - ldy sprite_enable, | ||
+ | lda cycles,y | ||
+ | sta timing,x | ||
+ | inx | ||
+ | cpx # | ||
+ | bne - | ||
+ | rts | ||
+ | </ | ||
+ | |||
+ | ===== Done ==== | ||
+ | |||
+ | And there you have it, we now have a D.Y.S.P. with flexible Y-positions. Naturally all this calculating eats cycles, which is why my code uses a lot of unrolled loops. | ||
==== The Code ==== | ==== The Code ==== | ||
+ | |||
+ | Finally, the code. It also contains a user interface, allowing the user to change the DYSP's movements with a joystick in port 2. | ||
+ | |||
<code 6502tasm> | <code 6502tasm> | ||
; vim: set et ts=8 sw=8 sts=8 syntax=64tass : | ; vim: set et ts=8 sw=8 sts=8 syntax=64tass : |
base/dysp_cycle_table.txt · Last modified: 2016-04-26 15:47 by compyx