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 > CSDb Entries > Release id #249931 : Two Tricks That Will Make You a Ridiculously Productive C64 Demo Coder
2025-02-08 01:45
Mixer

Registered: Apr 2008
Posts: 460
Release id #249931 : Two Tricks That Will Make You a Ridiculously Productive C64 Demo Coder

I thank you for the great talk Trident. The talk invited some reflection.

It is interesting that you come up with what is essentially scheduling and threads/processes from the simple need of making code easier to manage. This observation connects to something that in my experience happens in software development all the time.

The code that we produce has two classes of observers. One is the processor for which the readability or structure does not matter much. There may be some better performing sequences of instructions, but apart from that it has no preference. Then there is the human, the programmer who translates the human intent to processor code via a sequence of substitutions.

Lets say that there are two kind of problems, complex and difficult. Computing is complex. The foundations are very simple, just bits and binary logic, but to do something useful requires a lot of these components and the complexity emerges. Doing a back flip or climbing up a tree are difficult. They are difficult because of physical limitations of humans interacting with the world.

The complexity and difficulty meet in the human brain. Our brain has physical limitations and can only manage a couple of items in a few second interval. This means that in order to work with complex things, we must split everything into small chunks of just a few parts at a time. Thus it is a natural need for us to substitute groups of concepts with aggregate concepts and so on. This way the structure and organization of code and coding concepts are for humans by humans. This need also explains the thousands of design patterns and programming languages and frameworks that we've built for managing just our own concepts.

Our productivity increases when we find a new concept that can be substituted over an older one. In groups our productivity increases as we share these concepts. In projects and organizations we often choose to use particular tools or technology that is common for all programmers and so on, instead of what the processor might find most efficient.

One implication of all this is that when we plan stuff for people to do, we should take the brain into account and plan work for humans, not for "the processor" or a "process". Basically this means just splitting stuff into chunks and accepting that people can only do what they can see that they can do next. They've been researching why software is shit for decades and figured out ways to manage people and common information (agile, scrum, kanban, lean...) and so on, but that's another rant...

Well, anyway...
 
... 22 posts hidden. Click here to view all posts....
 
2025-02-10 22:47
trident

Registered: May 2002
Posts: 101
i got asked for a complete but minimal example of working code that implements anonymous irq handlers and protothreads. so i thought i'd might as well post it here.

the code below is written for kickassembler, but it should be easy to adopt for other assemblers.

.macro irq_set(name, rasterline) {
    lda #<name
    sta $fffe
    lda #>name
    sta $ffff
    lda #rasterline
    sta $d012
    lda $d011
    and #$7f
    ora #(rasterline & $100) >> 1
    sta $d011

}

.macro irq_wait(rasterline) {
    irq_set(next, rasterline)
    inc $d019
    rti
next:
}

.macro pt_wait_ticks(pt, ticks) {
    lda #0
    sta count + 1
    lda #<again
    sta pt
    lda #>again
    sta pt + 1
again:
count: lda #0
    cmp #ticks
    beq done
    inc count + 1
    rts
done:
}

    * = $0801 "Basic Upstart"
    BasicUpstart(start)

    * = $0810 "Program"
start:
{
    sei
    lda #$7f
    sta $dc0d
    bit $dc0d

    lda #$01
    sta $d01a

    lda #$35
    sta $01

    irq_set(irq, 0)
    cli

    jmp *
}


irq:
{
    lda #$e
    sta $d020

    irq_wait($40)
    lda #2
    sta $d020

    irq_wait($80)
    lda #3
    sta $d020

    irq_wait($f8)
    lda #4
    sta $d020

    jsr sequence

    irq_set(irq, 0)
    inc $d019
    rti
}

sequence:
{
    jmp (pt)

again:
    pt_wait_ticks(pt, 2 * 50)
    lda #5
    sta $d021

    pt_wait_ticks(pt, 2 * 50)
    lda #6
    sta $d021

    jmp again

pt: .word again
}


the code changes the border color on a few places on the screen and blinks the screen color once per second. there are a few things missing, such as saving and restoring the registers in the interrupt handlers, and that pt variable must not end up on a page boundary. and possibly a few other things. i guess this could be seen as an exercise for the reader :)
2025-02-11 08:33
Bitbreaker

Registered: Oct 2002
Posts: 510
Quoting chatGPZ

That NMI-for-Music is something i have to think about - not sure i like it, but it sounds like a good idea :)

Edit: how are you dealing with the case when you need the processing time in the border for something else? just write a different timer value for one frame (that seems glitchy). or us a slightly smaller timer value, and wait (in a transition or so) until the music call arrives at the wanted new position?


I usually issue that NMI at rasterline $ff (but any other position is possible), so it is still possible to open borders with ease. I have never been in trouble, i always placed the music call somewhere at that place, even when still using raster IRQs for that and let the rest of things happen on the other rasterlines on screen. Moving is possible, but a bit of work in any case. THCMs sample stuff uses NMIs, and sid playing is bogus in that case anyway. It made my life way easier, especially when linking parts together. There are macros to switch the music between irq/nmi mode, hotswap so to say.
There's still visual glitches to cope with more than enough, but fighting sound glitches is like twice the work.
2025-02-11 22:57
JackAsser

Registered: Jun 2002
Posts: 2038
Quote: Quoting chatGPZ

That NMI-for-Music is something i have to think about - not sure i like it, but it sounds like a good idea :)

Edit: how are you dealing with the case when you need the processing time in the border for something else? just write a different timer value for one frame (that seems glitchy). or us a slightly smaller timer value, and wait (in a transition or so) until the music call arrives at the wanted new position?


I usually issue that NMI at rasterline $ff (but any other position is possible), so it is still possible to open borders with ease. I have never been in trouble, i always placed the music call somewhere at that place, even when still using raster IRQs for that and let the rest of things happen on the other rasterlines on screen. Moving is possible, but a bit of work in any case. THCMs sample stuff uses NMIs, and sid playing is bogus in that case anyway. It made my life way easier, especially when linking parts together. There are macros to switch the music between irq/nmi mode, hotswap so to say.
There's still visual glitches to cope with more than enough, but fighting sound glitches is like twice the work.


Must say I like this approach. I might adopt it. It's quite seldom you have timing critical stuff in the lower border anyways. (I had during the BasicFader in Codeboys, but that's it basically and it's not even shown! :D). But the full border on the whole PAL-frame is open there.
2025-02-12 09:39
Oswald

Registered: Apr 2002
Posts: 5126
sometimes you use both kind of interrupts. Ninja's 4x4 routine uses timer irq's for doing the fli (bit faster no need to change d012 each time), and raster irq to enable disable these interrupts only for the screen area.
2025-02-12 10:30
chatGPZ

Registered: Dec 2001
Posts: 11510
you can do that without NMI though :)
2025-02-12 21:11
MagerValp

Registered: Dec 2001
Posts: 1082
In the Q&A was it JackAsser that brought up eight concurrent protothreads? The audio wasn't great so maybe I got that wrong, but it sounded like source for that was available somewhere?
2025-02-13 00:40
JackAsser

Registered: Jun 2002
Posts: 2038
Quote: In the Q&A was it JackAsser that brought up eight concurrent protothreads? The audio wasn't great so maybe I got that wrong, but it sounded like source for that was available somewhere?

Yes. I mentioned Copper Booze, source available. But it’s really not proto threads there, but full threading in a cooperative way. I.e. full task switch including split stack per task.
2025-02-13 16:42
MagerValp

Registered: Dec 2001
Posts: 1082
Excellent, thank you!
2025-02-14 14:00
trident

Registered: May 2002
Posts: 101
speaking of concurrency, another cool thing with protothreads is how easy it is to implement concurrent protothreads (multiple protothreads running at the same time). you just need to define another subroutine with a protothread inside it and call that too.

for example, something like this:

irq:
{
    irq_wait($f8)

    jsr blink_logo
    jsr blink_text

    irq_set(irq, 0)
    inc $d019
    rti
}

blink_logo:
{
    jmp (pt)
pt: .word again

again:
    pt_wait_ticks(pt, 2 * 50)
    lda #5
    sta logo_color

    pt_wait_ticks(pt, 2 * 50)
    lda #6
    sta logo_color

    jmp again
}


blink_text:
{
    jmp (pt)
pt: .word again

again:
    pt_wait_ticks(pt, 1 * 50)
    lda #7
    sta text_color

    pt_wait_ticks(pt, 1 * 50)
    lda #8
    sta text_color

    pt_wait_ticks(pt, 1 * 50)
    lda #9
    sta text_color

    jmp again
}


this will blink both the text_color and the logo_color, with different frequencies.
2025-02-14 19:08
MuZZa

Registered: Nov 2020
Posts: 18
in case there's anyone who uses 64tass...

; Implement of anonymous Irq Handlers and Protothreads
; by Trident Fjälldata 2025 (64tass example)

        ; BASIC START
	* = $0801
	.text 12,8,0,0,$9e,"2061",0,0,0
	
	; CODE START
	*= $080d
    
        sei
        lda #$7f
        sta $dc0d
        bit $dc0d

        lda #$01
        sta $d01a

        lda #$35
        sta $01

        #irq_set irq, 0
        cli

        jmp *
        
        ; Calling the Protothreads
irq
        lda #$0e
        sta $d020

        #irq_wait $40
        lda #$02                        
        sta $d020

        #irq_wait $80
        lda #$03                        
        sta $d020

        #irq_wait $b4
        lda #$04                        
        sta $d020

        #irq_wait $f8
        lda #$06                         
        sta $d020

        jsr sequence

        #irq_set irq, 0
        asl $d019
        rti

sequence
.block
        jmp (pt)

again
        #pt_wait_ticks pt, 2 * 50
        lda #$05
        sta $d021

        #pt_wait_ticks pt, 2 * 50
        lda #$06
        sta $d021

        #pt_wait_ticks pt, 2 * 50
        lda #$07
        sta $d021

        jmp again

pt      .word again
        .endblock

; Macros Definitions
irq_set .macro name, rasterline
        lda #<\name
        sta $fffe
        lda #>\name
        sta $ffff
        lda #\rasterline
        sta $d012
        lda $d011
        and #$7f
        ora #(\rasterline & $100) >> 1
        sta $d011
.endm

irq_wait .macro rasterline
        #irq_set next, \rasterline
        inc $d019
        rti
next
.endm

pt_wait_ticks .macro pt, ticks
        lda #0
        sta count + 1
        lda #<again
        sta \pt
        lda #>again
        sta \pt + 1
again
count
        lda #0
        cmp #\ticks
        beq done
        inc count + 1
        rts
done
.endm
Previous - 1 | 2 | 3 | 4 - 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
Mike
Dr. Doom/RAD
Guests online: 350
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Codeboys & Endians  (9.7)
4 Mojo  (9.6)
5 Coma Light 13  (9.6)
6 Edge of Disgrace  (9.6)
7 Signal Carnival  (9.6)
8 Wonderland XIV  (9.5)
9 Uncensored  (9.5)
10 Comaland 100%  (9.5)
Top onefile Demos
1 Nine  (9.7)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.5)
6 Scan and Spin  (9.5)
7 Onscreen 5k  (9.5)
8 Grey  (9.5)
9 Dawnfall V1.1  (9.5)
10 Rainbow Connection  (9.5)
Top Groups
1 Artline Designs  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Performers  (9.3)
5 Censor Design  (9.3)
Top Organizers
1 Burglar  (9.9)
2 Sixx  (9.8)
3 Irata  (9.7)
4 hedning  (9.7)
5 MWS  (9.7)

Home - Disclaimer
Copyright © No Name 2001-2025
Page generated in: 0.087 sec.