| |
Mixer
Registered: Apr 2008 Posts: 457 |
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.... |
| |
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. |
| |
Oswald
Registered: Apr 2002 Posts: 5110 |
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. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11445 |
you can do that without NMI though :) |
| |
MagerValp
Registered: Dec 2001 Posts: 1081 |
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? |
| |
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. |
| |
MagerValp
Registered: Dec 2001 Posts: 1081 |
Excellent, thank you! |
| |
trident
Registered: May 2002 Posts: 100 |
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. |
| |
MuZZa
Registered: Nov 2020 Posts: 17 |
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
|
| |
Digger
Registered: Mar 2005 Posts: 446 |
Great stuff. I saw Bexxx doing this instead:
jmp pt:*+3
Then there's no need to declare a memory for the jump address unless one needs to use ZP ofc. |
| |
bexxx
Registered: Nov 2023 Posts: 7 |
This is one of the possible implementation options :)
My childish self just loves self modifying code and illegal opcodes because that sounds cool :).
I did implement enable triggering of PTs like this:
handleRedTrafficLightSprites: {
jmp pt: exit
triggerStart:
delay_repeatable(pt, 2 * 50)
// show green traffic light
... all your sequence code
exit:
lda #<exit
sta pt
lda #>exit
sta pt+1
rts
}
do a
jsr handleRedTrafficLightSprites
as usual to execute it (disabled/enabled) and trigger it with
jsr handleRedTrafficLightSprites.triggerStart
depending on your needs you might not want to execute the first iteration here and just setup the pt ptrs, add rts accordingly.
Cheers,
bexxx |
Previous - 1 | 2 | 3 | 4 - Next |