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

Forums > C64 Coding > Linking wizardry
2014-10-31 14:41

Registered: Oct 2002
Posts: 445
Linking wizardry

You wanted to have some linking wizardry, so here's how things were done in Comaland:

The central part:

In $demofolder/link there's a Makefile. The example shows the process for doing one side. More imageX.d64 can of course be generated to build more sides, but i shortened things here to give at least a minimal chance to keep the overview. Some additional shellscript with sed wizardry was used to autogenerate a .bat for the windows whiners :-P
Targets like image1.d64 or vice1 can be used to build and fire up only a single side for standalone testing. Still, Alt-W is your best friend ;-)

export PATH := tools:../../link/tools/:$(PATH)
SHELL = /bin/bash
BITNAX = bitnax
D64WRITE = d64write
X64 = x64

.PHONY: all toolchain vice vice1

all: toolchain image1.d64

        $(MAKE) -C ../../../tool/c6510
        $(MAKE) -C ../../../tool/acme/src
        $(MAKE) -C ../../../tool/dasm
        $(MAKE) -C ../../../tool/bitfire
        $(MAKE) -C ../../../tool/bitnax
        $(MAKE) -C ../../../tool/dreamass

        cp ../../../tool/c6510/c6510 tools/
        cp ../../../tool/acme/src/acme tools/
        cp ../../../tool/dasm/dasm tools/
        cp ../../../tool/dreamass/dreamass tools/
        cp ../../../tool/bitfire/d64write tools/
        cp ../../../tool/bitnax/bitnax tools/

vice: all
        $(X64) -pal -autostart "image1.d64:*" -truedrive -model c64c

vice1: toolchain image1.d64
        $(X64) -pal -autostart "image1.d64:*" -truedrive -model c64c


image1.d64: comaland.prg bootside1.prg tune1.prg rasterrot.prg explode.prg bitmap.prg bitmap_fadeout2.prg shadowscroll.prg shadow_fadeout.prg plotballs_fadein.prg plotballs.prg plotballs_fadeout.prg comalanddef.prg  escos.prg note.prg
        $(D64WRITE) -c $@ --side 1 -a 49 ../bitbreaker/dirart/side1.prg \
                                --boot comaland.prg \
                                -b bootside1.prg \
                                -b rasterrot.prg \
                                -b tune1.prg \
                                -b explode.prg \
                                -b bitmap1.prg \
                                -b bitmap2.prg \
                                -b bitmap3.prg \
                                -b bitmap4.prg \
                                -b bitmap5.prg \
                                -b bitmap_fadeout2.prg \
                                -b comalanddef1.prg \
                                -b comalanddef2.prg \
                                -b plotballs_fadein.prg \
                                -b plotballs.prg \
                                -b plotballs_fadeout.prg \
                                -b shadowscroll1.prg \
                                -b shadowscroll2.prg \
                                -b shadowscroll3.prg \
                                -b shadow_fadeout.prg \
                                -b escos1.prg \
                                -b escos2.prg \
                                -b escos3.prg \
                                -s "erotic note"

##################### SIDE 1 ##################################
note.prg: force_look
        cd ../Axis/note/; $(MAKE) $(MAKE_FLAGS)
        $(BITNAX) --bitfire --sfx 0x4000 -o "erotic note" ../Axis/note/note

comaland.prg: force_look
        cd ../bootloader/stage1/; $(MAKE) $(MAKE_FLAGS) link_exit=0x0100 SIDE=1
        $(BITNAX) --sfx 0x0900 -o $@ ../bootloader/stage1/stage1

bootside1.prg: force_look
        cd ../bootloader/stage2/; $(MAKE) $(MAKE_FLAGS) link_exit=0x2000 SIDE=1
        $(BITNAX) --bitfire -o $@ ../bootloader/stage2/stage2

tune1.prg: ../../Music/dEViLOCk/tune_side10x900.prg
        $(BITNAX) --bitfire -o $@ --load-addr 0xe000 $^

rasterrot.prg: force_look
        cd ../Axis/RasterRotate/; $(MAKE) $(MAKE_FLAGS) link_exit=8192
        $(BITNAX) --bitfire -o $@ ../Axis/RasterRotate/rasterrot

explode.prg: force_look
        cd ../Mirage/FontExplodeMultiplex; $(MAKE) $(MAKE_FLAGS) link_exit=0x300c
        $(BITNAX) --bitfire -o $@ ../Mirage/FontExplodeMultiplex/explode

bitmap.prg: force_look
        cd ../Lavazza/bitmapscroller/; $(MAKE) $(MAKE_FLAGS) link_exit=0x0400
        $(BITNAX) --bitfire -o $(basename $@)1.prg --cut-input-addr 0x3000 0xffff ../Lavazza/bitmapscroller/bitmap
        $(BITNAX) --bitfire -o $(basename $@)2.prg ../Lavazza/bitmapscroller/part2.prg
        $(BITNAX) --bitfire -o $(basename $@)3.prg ../Lavazza/bitmapscroller/part3.prg
        $(BITNAX) --bitfire -o $(basename $@)4.prg ../Lavazza/bitmapscroller/part4.prg
        $(BITNAX) --bitfire -o $(basename $@)5.prg ../Lavazza/bitmapscroller/part5.prg

bitmap_fadeout2.prg: force_look
        cd ../CRT/bitmap_fadeout2/; $(MAKE) $(MAKE_FLAGS) link_exit=0x6400
        $(BITNAX) --bitfire -o $@ ../CRT/bitmap_fadeout2/bitmap_fadeout2

comalanddef.prg: force_look
        cd ../Bob/bob_yazoo/; $(MAKE) $(MAKE_FLAGS) link_exit=0xf000;
        $(BITNAX) --bitfire -o $(basename $@)1.prg --cut-input-addr 0xbff8 0xffff --load-addr 0xe400 ../Bob/bob_yazoo/comalanddef
        $(BITNAX) --bitfire -o $(basename $@)2.prg --cut-input-addr 0x2000 0xbff8 ../Bob/bob_yazoo/comalanddef

plotballs_fadein.prg: force_look
        cd ../bitbreaker/plotball_fadein/; $(MAKE) $(MAKE_FLAGS) link_exit=0x4000;
        $(BITNAX) --bitfire -o $@ --load-addr 0x9b00 ../bitbreaker/plotball_fadein/plotball_fadein

plotballs.prg: force_look
        cd ../bitbreaker/plotballs/; $(MAKE) $(MAKE_FLAGS) link_exit=0x0400;
        $(BITNAX) --bitfire -o $@ ../bitbreaker/plotballs/plotballs

plotballs_fadeout.prg: force_look
        cd ../bitbreaker/plotball_fadeout/; $(MAKE) $(MAKE_FLAGS) link_exit=0x2000;
        $(BITNAX) --bitfire -o $@ ../bitbreaker/plotball_fadeout/plotball_fadeout

shadowscroll.prg: force_look
        cd ../CRT/shadowscroll; $(MAKE) $(MAKE_FLAGS) link_exit=0x0400
        $(BITNAX) --bitfire -o $(basename $@)1.prg --cut-input-addr 0xcff0 0xffff ../CRT/shadowscroll/shadowscroll
        $(BITNAX) --bitfire -o $(basename $@)2.prg --cut-input-addr 0x2000 0xbff8 ../CRT/shadowscroll/shadowscroll
        $(BITNAX) --bitfire -o $(basename $@)3.prg --cut-input-addr 0xbff8 0xcff0 ../CRT/shadowscroll/shadowscroll

shadow_fadeout.prg: force_look
        cd ../CRT/shadow_fadeout/; $(MAKE) $(MAKE_FLAGS) link_exit=0x2000
        $(BITNAX) --bitfire -o $@ ../CRT/shadow_fadeout/shadow_fadeout

escos.prg: force_look
        cd ../Swallow/escos_scroll; $(MAKE) $(MAKE_FLAGS) link_exit=0x0100
        $(BITNAX) --bitfire -o $(basename $@)1.prg --cut-input-addr 0xbff0 0xffff --load-addr 0xe400 ../Swallow/escos_scroll/escos
        $(BITNAX) --bitfire -o $(basename $@)2.prg --cut-input-addr 0x2000 0xbff0 ../Swallow/escos_scroll/escos
        cp ../Swallow/escos_scroll/low.prg $(basename $@)3.prg


        -rm *.prg *.d64
        -rm ../Axis/note/note
        -rm ../bootloader/stage1/stage1
        -rm ../bootloader/stage2/stage2
        -rm ../Axis/RasterRotate/rasterrot
        -rm ../Lavazza/bitmapscroller/bitmap
        -rm ../CRT/bitmap_fadeout2/bitmap_fadeout2
        -rm ../CRT/shadowscroll/shadowscroll
        -rm ../CRT/shadow_fadeout/shadow_fadeout
        -rm ../bitbreaker/plotball_fadein/plotball_fadein
        -rm ../bitbreaker/plotballs/plotballs
        -rm ../bitbreaker/plotball_fadeout/plotball_fadeout
        -rm ../Mirage/FontExplodeMultiplex/explode
        -rm ../Swallow/escos_scroll/escos
        -rm ../Bob/bob_yazoo/comalanddef
        -rm "erotic note"

        #$(MAKE) -C ../../../tool/c6510 clean
        #$(MAKE) -C ../../../tool/acme/src clean
        #$(MAKE) -C ../../../tool/dasm clean
        #$(MAKE) -C ../../../tool/bitfire clean
        #$(MAKE) -C ../../../tool/bitnax clean
        #$(MAKE) -C ../../../tool/dreamass clean


This is the main file to build the demo, there are blocks per side to be built. The part that writes all parts on disk builds up the dependencies to all the other targets.
Each part is build in a saparate subtarget in a separate dir with separate Makefile (tiny and can be copied over and adopted easily) also each part contains the entry point for the next upcoming part (link_exit). The compiled parts are split up and packed with bitnax. The chunks are choosen wisely so that they fit in during loading and not destroy/overwrite any code/data that is still in use. That is the nifty part about linking, stuffing as much as possible data into mem while still showing cool things on the screen. Also parts should split up wisely in size, so that they won't reach or go over the end of mem. If needed, the chunks can also be loaded to different locations by changing their load-address on packing.

The bootloader:

There's some code fragments for a stage1 and stage2 for the bootloader.

- contains code for installing the loader and code for loading stage 2
- contains persistent code that gives exit points for parts to be able to load things without own code (as it might be overwritten)
- contains music call and base irq that can take over the music while no part running. Also it keeps counting up the frame counter to be able to sync things.
- thus each side gets an installer/bootloader for safety reasons for free as well

best placed @ $0100, but set the stackpointer to $ff before doing so.
The side specific stuff is happening here, like loading the music and starting it at the same frame for every try to keep teh demo in sync. Here it is also a good idea to set the music calls to different addresses if the music locations differes from side to side.


A sync point needs to be installed everywhere, where loading is not covered by a effect, as it is the only part that is not deterministic (still, longer depack times and such can also shift the sync). Also take care that the sync point waits a reasonable amount of frames longer than loading takes, to respect slower loading floppys. To find out the minimum time, you can freeze the machine after loading with a !byte $02 and read out the frame counter. It is usually a good idea to give about one second extra time.
Also, the demo is not synched to the music, but the music synched to the demo in the final step, or an recurring process. Why not offload some of the pain to the musicians :-P

The Parts:

Each part has a own folder, like:

Each of those folders also contains a Makefile like:

ACME = acme
ACMEOPT = -v1 -f cbm

.PHONY: clean

all: bumble

bumble: afli.asm bumble_pic.prg
        ${ACME} ${ACMEOPT} -DRELEASE=1 -Dlink_exit=$(link_exit) -o $@ $<
        ${ACME} ${ACMEOPT} -o $@.prg $<
        ../../../../tool/bitnax/bitnax --sfx 0x9000 -o $@.prg $@.prg

        -rm bumble bumble.prg

As you see, the target is build in a different way by using the RELEASE define. Also the parts can then make conditional assembly and either take precautions for a release or standalone version.
All this only works if the assembler accepts external defines. So far c6510, acme, dreamass and dasm do, but some only accept decimal values for that, liek dreamass, so take care on the link_exit define

A part loading another might then look like the following:

!ifdef RELEASE {
                ;reset frame counter
                lda #$00
                sta link_frame_count+0
                sta link_frame_count+1

                ;load + depack some part
                jsr link_loadnext_uncr

                ;load some part
                jsr link_loadnext_raw

                ;sync to frame counter
                +wait_frame_count $0200
} else {
                ;or wait for a trigger from your effect if you are sure it takes longer than loading
trig            lda #$00
                beq trig

                ;fadeout the effect
                jsr fadeout

                ;unlink irq to resident irq handler

                ;depack last part loaded and start it
                +link_uncr_jmp link_exit

I'd add more details if that codebase64 would just be enabled for editing again :-) This is the suckless approach i guess, but of course not the most comfortable. Now throw in your bloated frameworks :-P
... 57 posts hidden. Click here to view all posts....
2014-11-03 15:57

Registered: Dec 2001
Posts: 952
@stein: thanks for that, I really like that you can pass an argument in A, and that it has priority handling.
2014-11-03 18:41

Registered: May 2002
Posts: 416
Great thread, apart from the fact that HCL now forced me to learn how to code in an xdev environment. :(
2014-11-03 20:48

Registered: Aug 2009
Posts: 55
What Stein wrote about the looping of music and using commands in the patterns to indicate when it ends and either A) loop again or B) Continues to next song/patterns is neat.

It is a bit similar to the idea I've had for a very long time of a tackmo demo where you could pause a part by say press space at a certain time and then the part would loop forever until you again pressed space for continue with the demo. This would allow a trackmo to also become a "press space" demo for those parts you would like to watch for a longer time.

An example is when a coder spent half a year on a effect, and it goes by in a demo in less than 20 seconds... By having a "press space to enter space-mode", this effect could be enjoyed forever :) Until you exit by pressing space again.

In my prototype for this, I have used the same technique as Stein talked about, but in a different way. My way of doing this is by waiting for a effect command in the song to show the "press space message", the song will thereafter play another pattern, and at the end of that pattern, if space hasn't been pressed, the demo will just continue. If spacebar is pressed, the song will play until end of the song pattern and then switch to song nr 2 (or 3, or 4 etc) in the subsongs to play a sequence of a completely new song that loops for that effect.

Again, in the end of that sub-song, you get the possibility to exit by pressing space again. When that happens, and space is pressed, the song will have a transition in the last pattern so it fits back to the main melody in song nr.1, and then continue the demo and the song from that Point in song 1 as if spacebar never been pressed. And the trackmo continues.

I could share my prototype for this if any is interested. :)

2014-11-03 21:24

Registered: Jul 2007
Posts: 356
This most excellent thread seems like a good place to remind people about Spindle (Spindle 1.0).

It provides a 2D map of page usage over time, like Axis asked for. It splits parts into chunks and loads them incrementally, like radiantx suggested. It is faster than Krill's loader, thanks to on-the-fly GCR decoding. Because it's open source, it can easily be adapted to any special requirements.

Of course, it's not the final answer to everything. It has been designed primarily for design-time flexibility (turning linking into a creative activity, like film editing) and loading speed, at the cost of a relatively high memory footprint (1 kB) and sub-optimal compression (due to out-of-order decrunching). But it's there if you need it, or if you just want some inspiration.
2014-11-04 19:32
Pex Mahoney Tufvesson

Registered: Sep 2003
Posts: 38
Spindle seems nice. Next time I do a trackmo, I'll use it for sure! But that might be next X, so there's plenty of time for anyone else to do it before me!

Oh, and I'm all for single makefiles. And I love in-details assembly code listings. Or "I'll show mine if you'll show yours", one of my favorite games all-time! ;)
Have a noise night!
2014-11-07 14:46

Registered: Aug 2011
Posts: 26
Spindle looks very promising, but is it compatible with the variations in c64 drives? I mean, the GCR decoding on the fly is pure art, and with icu-peaking, spindle has dream speed. But what happens with 280 and 320 rpm drives? As far as i know, single drives could be this extreme, or?

Best regards
2014-11-07 15:52

Registered: Jul 2007
Posts: 356
Spindle relies on the same timing assumptions as Krill's loader.

Motor speed tolerance is discussed in this forum thread. See e.g. my post from 2012-10-24. Krill replies that no trouble has been reported with his 130-cycle loop, but I seem to remember that he changed it to 128 later.
2014-11-07 21:45

Registered: Aug 2011
Posts: 26
Ok thx
2014-11-19 08:54

Registered: Jan 2003
Posts: 360
Last night I've ditched my Makefile and used the DKjr project as a test case for building with SCons.
The result is a much leaner build script that correctly handles dependencies not just for includes but also incbin data, is easier to understand and maintain and something I can properly share between different projects without headaches.
2014-11-21 16:17

Registered: Oct 2004
Posts: 212
This thread has prompted me to finally try to clean-up and prepare my attempt at an imperative build tool for release, after 5-odd years of incremental fiddling and personal use.

I'd like to take this opportunity to call on the community for a couple of guinea pigs to help test and critique the tool before locking down the design for a public release (or a public burning of the source out of shame.)

It's basically a build engine tacked on to a Lua interpreter, with some assorted features to help track implicit dependencies and the like.

Anyone dissatisfied with make and wanting to try something new? Then feel free to drop me a PM and we'll see whether you share my taste for minimalism, aversion to shell-scripting and desire for rapid iteration. I promise there's no obligation to try it, just take a quick look and see whether it might be something for you and your project.

Disclaimer: Windows/POSIX only. Software may be bug-ridden.
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 - 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
Users Online
Guests online: 37
Top Demos
1 Unboxed  (9.7)
2 Uncensored  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 The Shores of Reflec..  (9.6)
7 Lunatico  (9.6)
8 X Marks the Spot  (9.5)
9 Wonderland XII  (9.5)
10 OMG Got Balls!  (9.5)
Top onefile Demos
1 Smile to the Sky  (9.5)
2 Instinct  (9.5)
3 Daah, Those Acid Pil..  (9.5)
4 Dawnfall V1.1  (9.4)
5 Crystal Gazer  (9.4)
6 Rewind  (9.4)
7 Pandemoniac Part 2 o..  (9.4)
8 Bad Boy  (9.4)
9 Official X2018 Report  (9.4)
10 Party Horse  (9.4)
Top Groups
1 Fossil  (9.6)
2 PriorArt  (9.6)
3 Oxyron  (9.4)
4 Booze Design  (9.4)
5 Censor Design  (9.3)
Top Fullscreen Graphicians
1 Facet  (10)
2 Joe  (9.9)
3 Veto  (9.8)
4 Mirage  (9.6)
5 Jailbird  (9.6)

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