Index

1. Introduction

↑ back to top ↑

2. Prerequisities

↑ back to top ↑

3. Setup GIT

↑ back to top ↑

4. Coding Guidelines

In general: code like you want. If everything works within the framework noone cares. If it doesn't you could make Spider cry, who is good friends with Jesus, so it's like you make Jesus cry. Oh and of course: every time you deliver code that doesn't work with the framework A KITTEN DIES!

4.1 The Most Important Rule

Do *not* use 'SEI' !!!

There may be certain situations where you might think you need SEI. In those cases be assured: You are wrong. You will never ever need to use SEI when coding within the framework.

  • If you want to turn off I/O -> do it in a timing uncritical moment.
  • If you want to register your IRQ -> look in the code examples.
  • If you want to do rasterpolling and wait for next frame -> use the fw_wait_irq routine.
  • If the framework IRQ rasterline doesn't fit your needs -> gently put it elsewhere (and gently restore to $000 at the end of your part).
  • If you want to use 'SEI' for other reasons -> Don't do it! Ask Spider for help or to patch the framework until your case is covered.
  • If you use 'SEI' anyway -> at least *TWO* KITTEN WILL DIE!
↑ back to top ↑

4.2 VIC Bank Switching

As the framework uses the famous loader by Krill, doing VIC bank switching the usual way will break the loader. The "Krill-Safe" method for changing the VIC bank is:

    ; $dd00 = %xxxxxx11 -> bank0: $0000-$3fff
    ; $dd00 = %xxxxxx10 -> bank1: $4000-$7fff
    ; $dd00 = %xxxxxx01 -> bank2: $8000-$bfff
    ; $dd00 = %xxxxxx00 -> bank3: $c000-$ffff

    lda #%000000xx ; <- your desired VIC bank value, see above
    sta $dd00
          

A little hint: if you don't know your final memory layout and vic bank setup when starting your part you could setup the vic bank, video memory and charset like so:

vicbank               = $4000
charset               = vicbank+$0000
vidmem0               = vicbank+$0800
sprite_data           = vicbank+$0c00
sprite_base           = <((sprite_data-vicbank)/$40)

    lda #<!(vicbank/$4000) & 3
    sta $dd00

    lda # <(((vidmem0-vicbank)/$400) << 4)+ <(((charset-vicbank)/$800) << 1)
    sta $d018
          

Then you usually only have to change the value of the 'vicbank' label/symbol (and eventually the offset values) later.

↑ back to top ↑

4.3. Random Numbers

At the time of writing there is no safe way to create real random numbers within the framework. You obviously can't use SID, as there's a tune playing, but you also can't use the CIA because the framwork does a CIA timer setup for 63 cycle counting at init.

Consider the use of pseudo-random numbers or even a random-table instead. In many cases this will be "random enough". In a demo you usually want the exact same behaviour anyway everytime it is executed.

↑ back to top ↑

5. Overview Tables

5.1 Framework Memory Layout

$0000 - $0001 as usual FRAMEWORK/PARTS
$0002 - $0004 zeropage for irq save/restore A,X,Y FRAMEWORK/PARTS
$0005 - $00DF zeropage free for use in parts PARTS
$00E0 - $00FF zeropage used by framework FRAMEWORK
$0100 - $01FF stack FRAMEWORK/PARTS
$0200 - $02FF framework code FRAMEWORK
$0300 - $03FF framework irq FRAMEWORK
$0400 - $07FF free for use in parts (at runtime) FRAMEWORK INIT/PARTS
$0800 - $0BFF krill loader resident FRAMEWORK
$0C00 - $1FFD space for music FRAMEWORK
$1FFE - $1FFF lo/hi pointer to part startaddress PARTS
$2000 - $FFF7 free for use in parts (at runtime)* PARTS
$FFF8 - $FFFF vectors FRAMEWORK/PARTS

* $D000-$FFF7 is free to use at runtime, but uncrunched code and data should fit into memory between $1FFE - $CFFF, as loading into I/O - Kernal area is not activated.

↑ back to top ↑

5.2 Important Framework Registers

fw_irq_lo lo-byte of your first irq in the frame
fw_irq_hi hi-byte of your first irq in the frame
fw_d011_value $d011 value that is set at the end of the framework irq
fw_d012_value $d012 value that is set at the end of the framework irq
fw_color_d020 value of $d020 to be set at line $000 by framework irq
fw_color_d021 value of $d021 to be set at line $000 by framework irq
fw_global_ct
fw_global_ct+1
fw_global_ct+2
continuous 24 bit counter ( READONLY!!!! )
fw_preserve_screen if set to 1 the framework will keep the current values of $d011, $d016, $d018 while loading the next part. i.e. for keeping a PETSCII on the screen make sure that fw_d011_value is setup correctly!!!
↑ back to top ↑

5.3 Important Framework Routines

fw_irq
fw_irq_addr
framework irq
fw_wait_irq waits until framework irq is over (at least 1 frame)
↑ back to top ↑

6. Code Examples

6.1 Including the Framework

In order to use the framework you have to at least include the symbols/labels from frameworksymbols.inc and put the entry point of your code into addresses $1ffe/$1fff (lo/hi).

Of course you usually also want to be able to test your part standalone. Therefore include the framework-noloader.prg at $0400 if the RELEASE variable is 0.

Usually Spider will deliver the soundtrack not only as a whole, but also split into snippets to be found in src/framework/music/. So if you want to sync your part to a specific music section, just include the SID file you want.

ATTENTION: the framework-noloader.prg is already build with the whole tune, so acme will give you a warning that you overwrite memory. Therefore it's also important to include the SID file afterwards.

!source "../../bin/framework/frameworksymbols.inc"

!if RELEASE = 0 {
  *= $0400
    !bin "../../bin/framework/framework-noloader.prg",,2

  *= fw_music_init
    !bin "../framework/music/TUNESNIPPET.sid",,$7e
}

*= $1ffe
    !byte <code_start
    !byte >code_start
          
↑ back to top ↑

6.2 Setup your IRQ

As there is already a raster-irq running when your code starts you must not setup your IRQ in the usual way. Instead you have to write the values you need into the framework registers.

fw_irq_lo is the pendant to $fffe, fw_irq_hi the pendant to $ffff and fw_d011_value/fw_d012_value of course are the values for $d011/$d012.

ATTENTION: Be aware that after this setup your IRQ fires the first time in the next frame, no matter what value for $d012 you have given. So if you want to have a synced mainloop afterwards, better jsr fw_wait_irq again.

    jsr fw_wait_irq

    lda #<MYIRQ
    sta fw_irq_lo
    lda #>MYIRQ
    sta fw_irq_hi

    lda #MYIRQ_RASTERLINE
    sta fw_d012_value
    lda #MY_D011_VALUE
    sta fw_d011_value
          
↑ back to top ↑

6.3 Rasterpolling

If you don't need any IRQ and all your routines will fit into one frame and want to to a part in the oldskewl 'rasterpolling' way, you can easily do that.

But there are a few things you should be aware of:

  • As mentioned above: do *not* use 'SEI'!
  • Think from 'top to bottom', instead of 'bottom to top'
  • The 'top' will be around rasterline $011-$01A (in dependence of the music), the 'bottom' will be as usual at $138.

Here's an example how a 'typical' rasterpolling mainloop could look like:

mainloop:
    jsr fw_wait_irq
                                  ; <- RASTER around $011-$01A here

    ; .. some code in the top border ..

    lda #$32
    cmp $d012
    beq *-3
                                  ; <- RASTER around the beginning of the screen here

    ; .. some code in the screen ..

    lda #$fe
    cmp $d012
    beq *-3
                                  ; <- RASTER around the end of the screen here

    ; .. some code in the lower border ..

    ; !IMPORTANT! be sure lower border code is done *before* RASTER wraps to $000

    jmp mainloop
          
↑ back to top ↑

7. GT Music Syncing

↑ back to top ↑

8. SW Music Syncing

↑ back to top ↑