| |
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.... |
| |
Bitbreaker
Registered: Oct 2002 Posts: 510 |
I am a bit divided in regards of using macros for readability and simplicity. Pouring a huge blob of unrolled code into a simple repeating macro makes sense while developing, but when getting into a release stage, i had at times found myself introducing a code generator in the end to get away with half the memory footprint when compressed.
Also introducing macros for anonymous irqs introduces a bit of code overhead, also redundant writes to $ffff are not covered (but could of course within the macro).
I am honoured that still two codeexamples from mine made it into the talk :-D For the fun parts, i'd say yes, for other parts, i'd say no.
What i am a fan of is, to move the sid player call and a frame counter increment into a nmi call that is called once a frame in the lower border. That call is part of the resident loader portion and thus safe to be called anytime. This saves a lot of hassle when handing over music beteen parts. De facto music is decoupled from the normal business at all, except when NMIs are needed for a effect. The frame counter can be cleared with a macro and sync to with another tiny macro. I tend to not trade too much memory for convenience. Also a simple SEI inhibits any further irqs happening friom a running part, no hookes to be changed and be kept in sync to avoid sound glitches. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11513 |
What faker said - i am not a friend of macros either. Used to use them a lot back when crossassemblers were new to me, today i only use them when i need to repeat relatively large portions of code. For small snippets they just make stuff less readable to me (eg i find Krills loader super unreadable due to all the macros).
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?
One "convenient thing" i have used in past demos is a global music "tick" counter, which increases by one every music tick (instead of frames). That made it very easy to have the flow in artphosis - every "wait" thing uses the tick counter, so everything is synced to beats with zero effort. |
| |
Krill
Registered: Apr 2002 Posts: 3092 |
Quoting chatGPZeg i find Krills loader super unreadable due to all the macros You keep saying that, but please, do tell me a better way to abstract away hardware-specific register access (C-64/C-128/Plus4 currently) than having HAL macros for that. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11513 |
i'd just put the ifdefs into the code, not hide them in macros |
| |
Krill
Registered: Apr 2002 Posts: 3092 |
Quoting chatGPZi'd just put the ifdefs into the code, not hide them in macros Then there'd be config ifdefs mixed with platform ifdefs all over the place. Plus code duplication. Pretty sure this would suck more than it does now.
Mods: Sorry for off-topic. Feel free to fork this or something if this goes on. =) |
| |
Mr SQL
Registered: Feb 2023 Posts: 158 |
I prefer Assembly but agree with the macros and Framework library concepts to create reusable demo routines as utilities.
This is similar to adding assembly to BASIC bitd. The same arguments for/against still apply. |
| |
Peiselulli
Registered: Oct 2006 Posts: 84 |
Pah, anything else than monitor coding sucks :-) |
| |
Jetboy
Registered: Jul 2006 Posts: 362 |
Quote: Pah, anything else than monitor coding sucks :-)
Been there, done that. I don't want to be there anymore :) |
| |
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 :) |
| |
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. |
Previous - 1 | 2 | 3 | 4 - Next |