User Tools

Site Tools


base:dysp_cycle_table

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
base:dysp_cycle_table [2016-04-26 14:35] – ; compyxbase:dysp_cycle_table [2016-04-26 15:47] (current) compyx
Line 47: Line 47:
 </code> </code>
  
 +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   nop           ; 2
 +</code>
 +
 +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 'cycles' table comes in, it gives us the amount of cycles sprites use for each 'sprite enable'/$d015 value. I used a little tool to determine those values, using brute force: for each combination I adjusted the cycle-delay until I got the proper value.
 +
 +The tool is also on [[https://github.com/Compyx/dysp-timer|GitHub]], but be warned, the code is a little messy.
 +
 +=== sprite enable table ===
 +
 +Now to determine which values to pick from the 'cycles' table and store in the 'timing' table, we need yet another table, which I call the 'sprite enable' table. This table is cleared each frame, and then populated using ORA for each sprite:
 +
 +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:
 +
 +<code>
 +          Sprite ORA values  Sprite enable
 +Y-offset  spr0   spr1  spr2  table result
 +--------  -----  ----  ----  -------------
 +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
 +</code>
 +
 +=== loop timing table ===
 +
 +Using this result, we can use the 'sprite enable' table values as an index into the cycles table to get the
 +proper value for the 'timing' table used in the border-loop:
 +<code 6502tasm>
 +        ldx #0
 +-       ldy sprite_enable,x
 +        lda cycles,y
 +        sta timing,x
 +        inx
 +        cpx #DYSP_HEIGHT
 +        bne -
 +        rts
 +</code>
 +
 +==== 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 =====
 +
 +Finally, the code. It also contains a little user interface, allowing the user to change the DYSP's movements with a joystick in port 2.
  
-==== The Code ==== 
 <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.1461674157.txt.gz · Last modified: 2016-04-26 14:35 by compyx