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: 2980
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-28 11:37
Rastah Bar
Account closed

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: 1409
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: 478
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: 478
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.
2020-01-29 05:52
ChristopherJam

Registered: Aug 2004
Posts: 1409
Cheers, Copyfault.

I was wondering about the pagebreak myself, but didn't want to constrain the code (of course, as writ it needs to avoid a page break, but that's slightly easier).

I agree that the ldy#val you've proposed belongs to the init code, and hence is a valid way to avoid the RMW without increasing the code size.

All that said, my submission and your modifications to it are all vulnerable to failing if they enter in the middle of line zero - only a 0.3% chance, but still not ideal. The following take avoids that, albeit at the cost of re-introducing the write to $d012. Possibly a bonus if you want to set up a raster interrupt for line $000 or $100 mind :)
sync:
    inc $d012   ; result will be zero on cycles 0-7 or 8 of raster line $ff
    bne sync    ; (or very rarely, cycle 9..62)

    .res 27,$ea ; wait 62-8=54 cycles. Replace with 54 cycles of init code

    inc $d012   ; if result is nonzero then we are too late.
    bne sync    ; carry on if we read on cycle 62, 62 cycles after cycle 0


edit: this one probably also compresses better than the earlier versions - the two code snippets both start with EE 12 D0 D0
2020-01-29 16:53
Krill

Registered: Apr 2002
Posts: 2980
Quoting ChristopherJam
sync:
    inc $d012   ; result will be zero on cycles 0-7 or 8 of raster line $ff
    bne sync    ; (or very rarely, cycle 9..62)

    .res 27,$ea ; wait 62-8=54 cycles. Replace with 54 cycles of init code

    inc $d012   ; if result is nonzero then we are too late.
    bne sync    ; carry on if we read on cycle 62, 62 cycles after cycle 0


edit: this one probably also compresses better than the earlier versions - the two code snippets both start with EE 12 D0 D0
Excellent! =D

Seems to work just fine here in my real-world code. Fast, reliable, short, packs well AND is pretty elegant. A keeper. :)
2020-01-29 18:14
JackAsser

Registered: Jun 2002
Posts: 2014
Quote: Quoting ChristopherJam
sync:
    inc $d012   ; result will be zero on cycles 0-7 or 8 of raster line $ff
    bne sync    ; (or very rarely, cycle 9..62)

    .res 27,$ea ; wait 62-8=54 cycles. Replace with 54 cycles of init code

    inc $d012   ; if result is nonzero then we are too late.
    bne sync    ; carry on if we read on cycle 62, 62 cycles after cycle 0


edit: this one probably also compresses better than the earlier versions - the two code snippets both start with EE 12 D0 D0
Excellent! =D

Seems to work just fine here in my real-world code. Fast, reliable, short, packs well AND is pretty elegant. A keeper. :)


I haven't really tried to understand it actually. Will this lock on any raster line or just 0 or 256? Or what are the limitations?
2020-01-29 18:27
Krill

Registered: Apr 2002
Posts: 2980
$100 only, i think.
2020-01-29 18:47
Frantic

Registered: Mar 2003
Posts: 1648
How nice! :)
2020-01-29 20:59
ChristopherJam

Registered: Aug 2004
Posts: 1409
Cheers all.

Yup, locks to line $100.

Assumes sprites disabled and no interrupts occur.
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... | 19 - 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
MWR/Visdom
Nordischsound/Hokuto..
Freeze/Blazon
B.A./QUANTUM
iAN CooG/HVSC
Mike
St0rmfr0nt/Quantum
4gentE/ΤRIΛD
Case/Padua
Martinland
Airwolf/F4CG
Walt/Bonzai
Neotec/Padua
TheRyk/MYD!
Guests online: 109
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 Layers  (9.6)
2 No Listen  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Swappers
1 Derbyshire Ram  (10)
2 Jerry  (9.8)
3 Violator  (9.7)
4 Acidchild  (9.7)
5 Cash  (9.6)

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