Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Shortest code for stable raster timer setup
2020-01-20 16:20
Krill

Registered: Apr 2002
Posts: 2855
Shortest code for stable raster timer setup

While working on my ICC 2019 4K entry (now postponed to ICC 2020, but i hope it'll be worth the wait), i came up with this (14 bytes):
initstabilise   lda $d012
                ldx #10          ; 2
-               dex              ;   (10 * 5) + 4
                bpl -            ; 54
                nop              ; 2
                eor $d012 - $ff,x; 5 = 63
                bne initstabilise; 7 = 70

                [...]; timer setup
The idea is to loop until the same current raster line is read at the very beginning (first cycle) and at the very end (last cycle) of a raster line, implying 0 cycles jitter.

With 63 cycles per line on PAL, the delay between the reads must be 63 cycles (and not 62), reading $d012 at cycle 0 and cycle 63 of a video frame's last line (311), which is one cycle longer due to the vertical retrace.

The downside is that effectively only one line per video frame is attempted, so the loop may take a few frames to terminate, and the worst case is somewhere just beyond 1 second.

The upside is that it always comes out at the same X raster position AND raster line (0), plus it leaves with accu = 0 and X = $ff, which can be economically re-used for further init code.

Now, is there an even shorter approach, or at least a same-size solution without the possibly-long wait drawback?
 
... 177 posts hidden. Click here to view all posts....
 
2020-01-20 23:20
Krill

Registered: Apr 2002
Posts: 2855
Quoting ChristopherJam
Haha well if we can pad with other code, just put something else that doesn't touch X in place of dex:bmi *-1, and we're down to 10 bytes :)
True, but it's quite hard to hit exactly, uhm, 1189 cycles. :)

Quoting ChristopherJam
and put all the init code somewhere that'll be overwritten by decrunched graphics or mainloop code.
In the usual size coding categories, you want the init code to be as small as possible as well, though, as the executable size counts. :)
2020-01-20 23:25
ChristopherJam

Registered: Aug 2004
Posts: 1382
Well, I'm assuming more "just enough to pad the gap between comparison becoming true and being in the DMA enabled area", so just a couple dozen cycles should be safe.

Fair point on minimizing initcode.
2020-01-21 16:16
Rastah Bar

Registered: Oct 2012
Posts: 336
Quoting Krill
With 63 cycles per line on PAL, the delay between the reads must be 63 cycles (and not 62), reading $d012 at cycle 0 and cycle 63 of a video frame's last line (311), which is one cycle longer due to the vertical retrace.

Funny, didn't know that. Does Vice emulate it? Hoxs doesn't.
2020-01-21 16:52
Krill

Registered: Apr 2002
Posts: 2855
Quoting Rastah Bar
Quoting Krill
With 63 cycles per line on PAL, the delay between the reads must be 63 cycles (and not 62), reading $d012 at cycle 0 and cycle 63 of a video frame's last line (311), which is one cycle longer due to the vertical retrace.

Funny, didn't know that. Does Vice emulate it? Hoxs doesn't.
From https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/sr..
    /* Line 0 is 62 cycles long, while line (SCREEN_HEIGHT - 1) is 64
       cycles long.  As a result, the counter is incremented one
       cycle later on line 0.  */
2020-01-21 17:33
Rastah Bar

Registered: Oct 2012
Posts: 336
Oh, I see. Thanks.
2020-01-27 21:18
Copyfault

Registered: Dec 2001
Posts: 467
Quoting Krill
Ah, bummer. This is the correct one with even-numbered lines only. =)
initstabilise   ldx #10
                lda $d012
                lsr              ; 2
                asl              ; 2
-               dex              ;   (10 * 5) + 4
                bpl -            ; 54
                cmp $d012        ; 4 = 62
                bne initstabilise; 9 = 71
Absolutely fantastic, Krill! It feels tempting to shave off another byte by exchanging [lsr:asl] by an and-instruction, i.e.
newline_loop:
           ldx #$f7
           lda $d012-$f7,x
           and inc_opcode:#$e8
           //-p-a-g-e-b-r-e-a-k
           bne inc_opcode
           cmp $d012
           bne newline_loop
Unfortunately, rasline $00 (or $100 resp.) breaks this :(


Also gave it a try to utilise the operand of the [ldx #10] in your code as $0a -> asl, but it all ends up with >=15 bytes total netweight.

Anyway, thanks for sharing and "en passant" giving something to ponder about ;)
2020-01-28 11:37
Rastah Bar

Registered: Oct 2012
Posts: 336
I tried something like this:
start:  ldx $d011
        bpl start:
loop:   pha
        cpx $d012
        pla
        inc safe_mem,x
        bcs loop:

But it can stabilize either on the PHA or on the INC safe_mem,x so no cigar.
2020-01-28 20:12
ChristopherJam

Registered: Aug 2004
Posts: 1382
Like the mathematician's hypothetical can opener, let us assume we have 50 cycles worth of init code that we are happy to run as many as seven times over.

Then we can sync with just ten bytes of code, in at most seven frames.
sync:
    lda $d012   ; will be zero on cycles 0,1,2,3,4,5 or 6
    bne sync

    .res 25,$ea ; replace this with 50 cycles of init code

    lsr $d012   ; if it's zero, either we're too early on line 0, or we're on line 256..  
    bcc sync    ; fall through if we read on cycle 62, 56 after cycle 6

We use lsr instead of lda for the second test, as lda would result in a 63 cycle loop.
2020-01-28 21:43
Copyfault

Registered: Dec 2001
Posts: 467
Quoting ChristopherJam
Like the mathematician's hypothetical can opener, let us assume we have 50 cycles worth of init code that we are happy to run as many as seven times over.

Then we can sync with just ten bytes of code, in at most seven frames.
sync:
    lda $d012   ; will be zero on cycles 0,1,2,3,4,5 or 6
    bne sync

    .res 25,$ea ; replace this with 50 cycles of init code

    lsr $d012   ; if it's zero, either we're too early on line 0, or we're on line 256..  
    bcc sync    ; fall through if we read on cycle 62, 56 after cycle 6

We use lsr instead of lda for the second test, as lda would result in a 63 cycle loop.
Woohaaaa, lovely! I knew you still have some variants hidden deep in your brains. So lucky I was right:)
This [lsr $d012] is really tricky. Hope it does not harm that we actually *set* a value for raster-irq this way, but it shouldn't as long as we have irqs disabled (what I silently assumed as a healthy setting). If the init-code uses index registers -which is usually the case-, one might want to style this approach even further...
sync:
    ldy #val
    lax $d012
    bne sync
    // here we are at cycle 3..9 of rasterline $00 (or 2..8 of rasterline $100)
    /*
    // 50 cycles of init code go here
    */
    // after that init code block we are @cycle 53..59 of rasterline $00(52..58 of line $100)
    lda $d012   // the R-cycle occurs @cycle 57..63 -> 63 = cycle 0 of line 1
                // in rasterline $100 this will end up @cycle 56..62, thus always without reaching the next line 
    beq sync    // branch not taken only when line 1 is reached
This way, we'd get x=0 and y loaded with a value of our choice on entering the init code block and we avoid _writing_ something to $d012, while still ensuring that the upper $d012-reads happen in a regular 65-cycle-distance.
However, the 10-byte-trophy stays with you, CJ! (though I'd like to argue that this [ldy#val] belongs more to the init code;);)).

Let's wait another day, maybe Krill will come up with yet another "brainbomb":)
2020-01-28 21:52
Copyfault

Registered: Dec 2001
Posts: 467
Quoting Copyfault
[...]
sync:
    ldy #val
    lax $d012
    bne sync
    // here we are at cycle 3..9 of rasterline $00 (or 2..8 of rasterline $100)
    /*
    // 50 cycles of init code go here
    */
    // after that init code block we are @cycle 53..59 of rasterline $00(52..58 of line $100)
    lda $d012   // the R-cycle occurs @cycle 57..63 -> 63 = cycle 0 of line 1
                // in rasterline $100 this will end up @cycle 56..62, thus always without reaching the next line 
    beq sync    // branch not taken only when line 1 is reached
Hmm, wait, wouldn't having a pagebreack between the upper [lax $d012] and the [beq sync] be enough?
sync:
    lax $d012
    bne sync
    /*
    // 50 cycles of init code go here
    */
    lda $d012
    //-p-a-g-e-b-r-e-a-k-
    beq sync
Ok, that nice [ldy #val] is no more, but this way the cycle-distance between the upper $d012-reads amounts to 64, which is coprime to 63.
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... | 20 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
dstar/Fairlight
Skate/Plush
Martinland
Guests online: 102
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.7)
5 Edge of Disgrace  (9.7)
6 No Bounds  (9.6)
7 Aliens in Wonderland  (9.6)
8 Comaland 100%  (9.6)
9 Uncensored  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 Layers  (9.6)
2 Cubic Dream  (9.6)
3 Party Elk 2  (9.6)
4 Copper Booze  (9.6)
5 TRSAC, Gabber & Pebe..  (9.5)
6 Rainbow Connection  (9.5)
7 Dawnfall V1.1  (9.5)
8 It's More Fun to Com..  (9.5)
9 Daah, Those Acid Pil..  (9.5)
10 Birth of a Flower  (9.5)
Top Groups
1 Nostalgia  (9.4)
2 Oxyron  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 SHAPE  (9.3)
Top Musicians
1 Rob Hubbard  (9.7)
2 Stinsen  (9.7)
3 Jeroen Tel  (9.6)
4 Linus  (9.6)
5 psych858o  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.072 sec.