]> hydra-www.ietfng.org Git - acmetensortoys-chiptunes/commitdiff
Batch of untested changes (eep!) main
authorNathaniel Wesley Filardo <nwf@pf.priv.oc.ietfng.org>
Wed, 25 Aug 2010 08:58:43 +0000 (04:58 -0400)
committerNathaniel Wesley Filardo <nwf@pf.priv.oc.ietfng.org>
Wed, 25 Aug 2010 08:58:43 +0000 (04:58 -0400)
Makefile
docs/packedformat.new
progenv/tracker_optimize.pl
target/main.c
target/script.ld [new file with mode: 0644]

index 02ad9c4b9347634bd1312ecaf12ba24a0bc390b3..072902ecca02cf91c42d0ea7007cba3f187876fd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
-CPU_CPP_NAME=__AVR_ATmega88__
-CPU_CC_NAME=avr4
+CPU_CPP_NAME=__AVR_ATmega328__
+CPU_CC_NAME=atmega328p
 CPU_LD_NAME=avr4
 CPU_LD_NAME=avr4
+       # Be sure to also adjust the values in target/script.ld
+       
 CPU_FREQUENCY=20000000
 SAMPLE_RATE=16000
 
 CPU_FREQUENCY=20000000
 SAMPLE_RATE=16000
 
@@ -10,9 +12,10 @@ tracker/%: CFLAGS=-Wall -Wextra -Werror
 tracker/%: CC=gcc
 
 target/%: CPPFLAGS=-I. -D${CPU_CPP_NAME}
 tracker/%: CC=gcc
 
 target/%: CPPFLAGS=-I. -D${CPU_CPP_NAME}
-target/%: CFLAGS=-O2 -g -B/usr/avr/lib -Wall -Wextra -Werror -mmcu=${CPU_CC_NAME}
+target/%: CFLAGS=-O2 -g -B/usr/avr/lib -Wall -Wextra -Werror -mmcu=${CPU_CC_NAME} \
+                       -Wl,-T -Wl,target/script.ld
 target/%: ASFLAGS=-mmcu=${CPU_CC_NAME}
 target/%: ASFLAGS=-mmcu=${CPU_CC_NAME}
-target/%: LDFLAGS=-Tdata 0x800160 -M -m ${CPU_LD_NAME}
+target/%: LDFLAGS=-M -T target/script.ld -m ${CPU_LD_NAME} 
 target/%: CC=avr-gcc
 target/%: LD=avr-ld
 target/%: AS=avr-as
 target/%: CC=avr-gcc
 target/%: LD=avr-ld
 target/%: AS=avr-as
@@ -30,9 +33,8 @@ progenv/gentimes.h: progenv/gentimes.pl
 
 progenv/gentimes.o: progenv/gentimes.h
 
 
 progenv/gentimes.o: progenv/gentimes.h
 
-.INTERMEDIATE: songs/%.h
-songs/%.s songs/%.h : songs/%.song | progenv/tracker_optimize.pl
-       perl progenv/tracker_optimize.pl --optimize --packout=songs/$*.s --headout=songs/$*.h --packver=1 < $^
+songs/%.s : songs/%.song | progenv/tracker_optimize.pl
+       perl progenv/tracker_optimize.pl --optimize --packout=songs/$*.s --packver=1 < $^
 
     # For use with e.g. "play --rate 16000 -b8 -L -c1 -e un -t raw"
 songs/%.raw : songs/%.song | tracker/tracker
 
     # For use with e.g. "play --rate 16000 -b8 -L -c1 -e un -t raw"
 songs/%.raw : songs/%.song | tracker/tracker
@@ -43,8 +45,8 @@ tracker/chip.o: progenv/gentimes.h
 tracker/tracker: tracker/main.o tracker/chip.o tracker/gui.o progenv/gentimes.o
        ${CC} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ 
 
 tracker/tracker: tracker/main.o tracker/chip.o tracker/gui.o progenv/gentimes.o
        ${CC} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ 
 
-target/%.o: target/main.c target/asm.S songs/%.s progenv/gentimes.c target/config.h | progenv/gentimes.h songs/%.h
-       ${CC} ${CPPFLAGS} ${CFLAGS} --include="songs/$*.h" -o $@ $^
+target/%.o: target/main.c target/hyperbola.c target/asm.S songs/%.s progenv/gentimes.c target/config.h | progenv/gentimes.h
+       ${CC} ${CPPFLAGS} ${CFLAGS} -funit-at-a-time --combine -o $@ $^
 
 target/%.hex: target/%.o
        ${LD} ${LDFLAGS} --oformat ihex -o $@ $^ > target/mapfile
 
 target/%.hex: target/%.o
        ${LD} ${LDFLAGS} --oformat ihex -o $@ $^ > target/mapfile
@@ -53,7 +55,7 @@ target/%.da: target/%.o
        avr-objdump -S $^ > $@
 
 clean:
        avr-objdump -S $^ > $@
 
 clean:
-       rm -f songs/*.s songs/*.h songs/*.raw
+       rm -f songs/*.s songs/*.raw
        rm -f tracker/*.o tracker/tracker
        rm -f target/*.o target/mapfile target/*.hex
        rm -f progenv/gentimes.[ch]
        rm -f tracker/*.o tracker/tracker
        rm -f target/*.o target/mapfile target/*.hex
        rm -f progenv/gentimes.[ch]
index ccbd9539ddc1452ae6efdfb72d3571daf1d84694..1de4329aff6a4e8eba266c3fb7a946a8e025c04b 100644 (file)
@@ -56,7 +56,7 @@ instrument:
     ccccpppppppp        = command c, parameter p
     (for each cmd)
     
     ccccpppppppp        = command c, parameter p
     (for each cmd)
     
-    Note tht the reduction to 12 bits (from 16) doesn't destroy
+    Note that the reduction to 12 bits (from 16) doesn't destroy
     seekability, since we know that even commands begin on a byte
     boundary and odd begin on a byte-and-a-nibble boundary.
 
     seekability, since we know that even commands begin on a byte
     boundary and odd begin on a byte-and-a-nibble boundary.
 
@@ -71,10 +71,6 @@ instrument:
     expect to free up a little under 69 bytes then, or a little over four
     bytes per instrument on average.)
 
     expect to free up a little under 69 bytes then, or a little over four
     bytes per instrument on average.)
 
-    XXX Despite the gains, this restricts us from growing the command
-    vocabulary available to instruments.  That might be OK, as there
-    seem to be few we actually want, but
-
 track:
     000                                       = blank line
     100xxxxxxx                                = note x, instr 0 (last)
 track:
     000                                       = blank line
     100xxxxxxx                                = note x, instr 0 (last)
index 357f7f6a88d9610fcea0e7e38aafb400b90e7c05..4560e773c25c9d83e5b9bc0697ae53f442ea019b 100644 (file)
@@ -599,6 +599,61 @@ sub packout($$$$$$) {
     print $FH "songdata_end:\n";
 }
 
     print $FH "songdata_end:\n";
 }
 
+sub packout_new($$$$$$) {
+    my ($FH, $v, $params, $asr, $atr, $air) = @_;
+
+    my $psong = pack_song($v, $params, $asr);
+    my $ptrks = pack_tracks($v, $params, $atr);
+    my $pinss = pack_instrs($v, $params, $air);
+
+    # header
+    print $FH ".section .rosdata,\"a\"\n";
+
+    # song
+    print $FH "\t.global\tsongdata\n\nsongdata:\n";
+    printf $FH "\t.byte\t0x%02x\n", (scalar $#$asr)+1;
+    print $FH map { sprintf "\t.byte\t0x%02x\n", ord $_ }
+        split //, pack 'B*', $psong, "\n";
+    print $FH "songdata_end:\n";
+
+    # ptrtab for instruments
+    print $FH "\n.global\titab\n\nitab:\n";
+    for my $iix ($$params{'BASE_INSTR'}..$#$pinss) {
+        printf $FH "\t.word\titab_$iix\n";
+    }
+#    # lentab for instruments
+#    print $FH "\n.global\tilentab\n\nilentab:\n";
+#    printf $FH "\t.byte\t0x%02x\n", $#$pinss - $$params{'BASE_INSTR'} + 1;
+#    for my $iix ($$params{'BASE_INSTR'}..$#$pinss) {
+#        printf $FH "\t.byte\t0x%02x\n", (length $$pinss[$iix])/8;
+#    }
+    for my $iix ($$params{'BASE_INSTR'}..$#$pinss) {
+#        print $FH "\nilentab_$iix:\n";
+        print $FH "\nitab_$iix:\n";
+        print $FH map { sprintf "\t.byte\t0x%02x\n", ord $_ }
+            split //, pack 'B*', $$pinss[$iix], "\n";
+    }
+
+    # ptrtab for instruments
+    print $FH "\n.global\tttab\n\nttab:\n";
+    for my $iix ($$params{'BASE_TRACK'}..$#$ptrks) {
+        printf $FH "\t.word\tttab_$iix\n";
+    }
+#    # lentab for tracks
+#    print $FH "\n.global\ttlentab\n\ntlentab:\n";
+#    printf $FH "\t.byte\t0x%02x\n", $#$ptrks + 1;
+#    for my $iix ($$params{'BASE_TRACK'}..$#$ptrks) {
+#        printf $FH "\t.byte\t0x%02x\n", (length $$ptrks[$iix])/8;
+#    }
+    for my $iix ($$params{'BASE_TRACK'}..$#$ptrks) {
+#        print $FH "\ntlentab_$iix:\n";
+        print $FH "\nttab_$iix:\n";
+        print $FH map { sprintf "\t.byte\t0x%02x\n", ord $_ }
+            split //, pack 'B*', $$ptrks[$iix], "\n";
+    }
+}
+
+
 sub packheadout($$$$$$) {
     my ($FH, $v, $params, $asr, $atr, $air) = @_;
 
 sub packheadout($$$$$$) {
     my ($FH, $v, $params, $asr, $atr, $air) = @_;
 
@@ -635,7 +690,8 @@ if (defined $TRACKOUTF) {
 }
 
 if (defined $PACKOUTF) {
 }
 
 if (defined $PACKOUTF) {
-    die "Also need --headout" if not defined $HEADOUTF;
+    die "Also need --headout"
+        if not defined $HEADOUTF and $PACKVER < 1;
 
     die "Too many input channels"
         if $$iverpar{'channels'} > $$overpar{'NR_CHAN'};
 
     die "Too many input channels"
         if $$iverpar{'channels'} > $$overpar{'NR_CHAN'};
@@ -644,12 +700,18 @@ if (defined $PACKOUTF) {
     die "Too many tracks!"
         if $#$atr > 2**$$overpar{'PACKSIZE_SONGTRACK'}-1;
 
     die "Too many tracks!"
         if $#$atr > 2**$$overpar{'PACKSIZE_SONGTRACK'}-1;
 
-    open PACKOUT,">$PACKOUTF" or die "Can't open $PACKOUTF: $!";
-    packout(*PACKOUT, $iverpar, $overpar, $asr, $atr, $air);
-    close PACKOUT;
+    if ($PACKVER < 1) {
+        open PACKOUT,">$PACKOUTF" or die "Can't open $PACKOUTF: $!";
+        packout(*PACKOUT, $iverpar, $overpar, $asr, $atr, $air);
+        close PACKOUT;
 
 
-    open HEADOUT,">$HEADOUTF" or die "Can't open $HEADOUTF: $!";
-    packheadout(*HEADOUT, $iverpar, $overpar, $asr, $atr, $air);
-    close HEADOUT;
+        open HEADOUT,">$HEADOUTF" or die "Can't open $HEADOUTF: $!";
+        packheadout(*HEADOUT, $iverpar, $overpar, $asr, $atr, $air);
+        close HEADOUT;
+    } else {
+        open PACKOUT,">$PACKOUTF" or die "Can't open $PACKOUTF: $!";
+        packout_new(*PACKOUT, $iverpar, $overpar, $asr, $atr, $air);
+        close PACKOUT;
+    }
 }
 
 }
 
index 258a3e36da0ac116f6d79e92b19d4d6864cc62f0..64389571abb1894ba2cf9b08d8dc1b089ce6f27d 100644 (file)
@@ -1,3 +1,5 @@
+#include <stddef.h>
+
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
@@ -19,11 +21,13 @@ u8 trackwait;
 u8 trackpos;
 u8 playsong;
 u8 songpos;
 u8 trackpos;
 u8 playsong;
 u8 songpos;
+u8 songlen;
 
 u32 noiseseed = 1;
 
 u8 light[2];
 
 
 u32 noiseseed = 1;
 
 u8 light[2];
 
+
 /* The layout of this structure is known to assembler */
 volatile struct oscillator {
        u16     freq;
 /* The layout of this structure is known to assembler */
 volatile struct oscillator {
        u16     freq;
@@ -34,19 +38,23 @@ volatile struct oscillator {
 } osc[NR_CHAN];
 
 struct unpacker {
 } osc[NR_CHAN];
 
 struct unpacker {
-       u16     nextbyte;
+       u8*     nextbyte;
        u8      buffer;
        u8      bits;
        u8      buffer;
        u8      bits;
+               // XXX RAMPACKS
+               // 0x80 : PGM(1) vs RAM(0)
+               // 0x07 : bits remaining in buffer
 };
 
 struct channel {
        struct unpacker         trackup;
 };
 
 struct channel {
        struct unpacker         trackup;
+       u8                      flags;
        u8                      tnum;
        s8                      transp;
        u8                      tnote;
        u8                      tnum;
        s8                      transp;
        u8                      tnote;
-       u8                      lastinstr;
-       u8                      inum;
-       u16                     iptr;
+       u8*                     ilast;
+       u8*                     iptr;
+       u8                      ioff;
        u8                      iwait;
        u8                      inote;
        s8                      bendd;
        u8                      iwait;
        u8                      inote;
        s8                      bendd;
@@ -60,12 +68,11 @@ struct channel {
        u16                     slur;
 } channel[NR_CHAN];
 
        u16                     slur;
 } channel[NR_CHAN];
 
-u16 resources[16 + MAXTRACK];
-
 struct unpacker songup;
 
 struct unpacker songup;
 
+extern u8* itab[] __ATTR_PROGMEM__;
+extern u8* ttab[] __ATTR_PROGMEM__;
 extern u8 songdata[] __ATTR_PROGMEM__;
 extern u8 songdata[] __ATTR_PROGMEM__;
-#define readsongbyte(x) pgm_read_byte_near(&songdata[x]);
 
 /* This is the AVR-LIBC standard dance for disabling the WDT */
     static uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
 
 /* This is the AVR-LIBC standard dance for disabling the WDT */
     static uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
@@ -80,16 +87,29 @@ extern u8 songdata[] __ATTR_PROGMEM__;
       wdt_disable();
     }
 
       wdt_disable();
     }
 
-static void initup(struct unpacker *up, u16 offset) {
-       up->nextbyte = offset;
+static void initup(struct unpacker *up, u8 *ptr) {
+       up->nextbyte = ptr;
        up->bits = 0;
 }
 
 static u8 readbit(struct unpacker *up) {
        u8 val;
 
        up->bits = 0;
 }
 
 static u8 readbit(struct unpacker *up) {
        u8 val;
 
+#if 0
+       /* XXX RAMPACKS If we have RAM packs, use this instead */
+       if(!(up->bits & 0x7)) {
+               up->buffer =
+                       (up->bits & 0x80)
+                               ? pgm_read_byte_near(up->nextbyte)
+                               : *up->nextbyte;
+               up->nextbyte++;
+               up->bits |= 7;
+       } else {
+               up->bits--;
+       }
+#endif
        if(!up->bits) {
        if(!up->bits) {
-               up->buffer = readsongbyte(up->nextbyte++);
+               up->buffer = pgm_read_byte_near(up->nextbyte++);
                up->bits = 8;
        }
 
                up->bits = 8;
        }
 
@@ -100,7 +120,7 @@ static u8 readbit(struct unpacker *up) {
        return val;
 }
 
        return val;
 }
 
-u16 readchunk(struct unpacker *up, u8 n) {
+static u16 readchunk(struct unpacker *up, u8 n) {
        u16 val = 0;
        u8 i;
 
        u16 val = 0;
        u8 i;
 
@@ -113,24 +133,22 @@ u16 readchunk(struct unpacker *up, u8 n) {
        return val;
 }
 
        return val;
 }
 
-static void readinstr(u8 num, u8 pos, u8 *dest) {
-    u16 base = resources[num];
-
-       u8 s0 = readsongbyte(base + pos + pos/2 + 0);
-       u8 s1 = readsongbyte(base + pos + pos/2 + 1);
-    if(pos & 1) {
-        dest[0] = s0 >> 4;
-        dest[1] = s1;
-    } else {
-        dest[0] = s1 & 0xF;
-        dest[1] = s0; 
-    }
+static void readinstr_pgm(u8* base, u8 pos, u8 *dest) {
+       u8 s0 = pgm_read_byte_near(base + pos + pos/2 + 0);
+       u8 s1 = pgm_read_byte_near(base + pos + pos/2 + 1);
+       if(pos & 1) {
+               dest[0] = s0 >> 4;
+               dest[1] = s1;
+       } else {
+               dest[0] = s1 & 0xF;
+               dest[1] = s0; 
+       }
 }
 
 static void runcmd(u8 ch, u8 cmd, u8 param) {
        switch(cmd) {
                case CMD_ISTOP:
 }
 
 static void runcmd(u8 ch, u8 cmd, u8 param) {
        switch(cmd) {
                case CMD_ISTOP:
-                       channel[ch].inum = 0;
+                       channel[ch].iptr = NULL;
                        break;
                case CMD_DUTY:
                        osc[ch].duty = param << 8;
                        break;
                case CMD_DUTY:
                        osc[ch].duty = param << 8;
@@ -142,7 +160,7 @@ static void runcmd(u8 ch, u8 cmd, u8 param) {
                        channel[ch].inertia = param << 1;
                        break;
                case CMD_IJUMP:
                        channel[ch].inertia = param << 1;
                        break;
                case CMD_IJUMP:
-                       channel[ch].iptr = param;
+                       channel[ch].ioff = param;
                        break;
                case CMD_BENDD:
                        channel[ch].bendd = param;
                        break;
                case CMD_BENDD:
                        channel[ch].bendd = param;
@@ -175,7 +193,7 @@ static void runcmd(u8 ch, u8 cmd, u8 param) {
        }
 }
 
        }
 }
 
-static void playroutine() {
+static void playtrack() {
        u8 ch;
 
        if(playsong) {
        u8 ch;
 
        if(playsong) {
@@ -186,24 +204,31 @@ static void playroutine() {
 
                        if(!trackpos) {
                                if(playsong) {
 
                        if(!trackpos) {
                                if(playsong) {
-                                       if(songpos >= SONGLEN) {
+                                       if(songpos >= songlen) {
                                                playsong = 0;
                                                playsong = 0;
+                                               light[1] = 0xFF;
                                        } else {
                                                for(ch = 0; ch < NR_CHAN; ch++) {
                                                        u8 gottransp;
                                                        u8 transp;
                                        } else {
                                                for(ch = 0; ch < NR_CHAN; ch++) {
                                                        u8 gottransp;
                                                        u8 transp;
+                                                       u8 ntnum;
 
                                                        gottransp = readchunk(&songup, 1);
 
                                                        gottransp = readchunk(&songup, 1);
-                                                       channel[ch].tnum = readchunk(&songup, PACKSIZE_SONGTRACK);
+                                                       ntnum = readchunk(&songup, PACKSIZE_SONGTRACK);
                                                        if(gottransp) {
                                                                transp = readchunk(&songup, PACKSIZE_SONGTRANS);
                                                                if(transp & 0x8) transp |= 0xf0;
                                                        } else {
                                                                transp = 0;
                                                        }
                                                        if(gottransp) {
                                                                transp = readchunk(&songup, PACKSIZE_SONGTRANS);
                                                                if(transp & 0x8) transp |= 0xf0;
                                                        } else {
                                                                transp = 0;
                                                        }
+                                                       channel[ch].tnum = ntnum;
                                                        channel[ch].transp = (s8) transp;
                                                        channel[ch].transp = (s8) transp;
+
                                                        if(channel[ch].tnum) {
                                                        if(channel[ch].tnum) {
-                                                               initup(&channel[ch].trackup, resources[16 + channel[ch].tnum - 1]);
+                                                               initup(&channel[ch].trackup,
+                                                                       (u8*) pgm_read_word_near(
+                                                                               &ttab[channel[ch].tnum-1]));
+                                                               // XXX TINDR
                                                        }
                                                }
                                                songpos++;
                                                        }
                                                }
                                                songpos++;
@@ -227,7 +252,10 @@ static void playroutine() {
                                                if(fields & 2) instr = readchunk(&channel[ch].trackup, PACKSIZE_TRACKINST);
                                                if(note) {
                                                        channel[ch].tnote = note + channel[ch].transp;
                                                if(fields & 2) instr = readchunk(&channel[ch].trackup, PACKSIZE_TRACKINST);
                                                if(note) {
                                                        channel[ch].tnote = note + channel[ch].transp;
-                                                       if(!instr) instr = channel[ch].lastinstr;
+                                                       if(!instr) {
+                                                               channel[ch].iptr = channel[ch].ilast;
+                                                               goto instr_common;
+                                                       }
                                                }
                                                if(instr) {
                                                        if(instr == 2) light[1] = 5;
                                                }
                                                if(instr) {
                                                        if(instr == 2) light[1] = 5;
@@ -240,9 +268,12 @@ static void playroutine() {
                                                        if(instr == 7) {
                                                                light[0] = light[1] = 30;
                                                        }
                                                        if(instr == 7) {
                                                                light[0] = light[1] = 30;
                                                        }
-                                                       channel[ch].lastinstr = instr;
-                                                       channel[ch].inum = instr;
-                                                       channel[ch].iptr = 0;
+                                                       channel[ch].ilast
+                                                               = channel[ch].iptr
+                                                               = (u8*) pgm_read_word_near(&itab[instr-1]);
+                                                               // XXX IINDR
+instr_common:
+                                                       channel[ch].ioff = 0;
                                                        channel[ch].iwait = 0;
                                                        channel[ch].bend = 0;
                                                        channel[ch].bendd = 0;
                                                        channel[ch].iwait = 0;
                                                        channel[ch].bend = 0;
                                                        channel[ch].bendd = 0;
@@ -269,17 +300,22 @@ static void playroutine() {
                        }
                }
        }
                        }
                }
        }
+}
+
+static void updateinstruments() {
+       u8 ch;
 
        for(ch = 0; ch < NR_CHAN; ch++) {
                s16 vol;
                u16 duty;
                u16 slur;
 
 
        for(ch = 0; ch < NR_CHAN; ch++) {
                s16 vol;
                u16 duty;
                u16 slur;
 
-               while(channel[ch].inum && !channel[ch].iwait) {
+               while(channel[ch].iptr && !channel[ch].iwait) {
                        u8 il[2];
 
                        u8 il[2];
 
-                       readinstr(channel[ch].inum, channel[ch].iptr, il);
-                       channel[ch].iptr++;
+                       // XXX RAMPACKS
+                       readinstr_pgm(channel[ch].iptr, channel[ch].ioff, il);
+                       channel[ch].ioff++;
 
                        runcmd(ch, il[0], il[1]);
                }
 
                        runcmd(ch, il[0], il[1]);
                }
@@ -336,16 +372,26 @@ static void playroutine() {
 }
 
 void initresources() {
 }
 
 void initresources() {
-       u8 i;
-       struct unpacker up;
+       songlen = pgm_read_byte_near(&songdata[0]);
+       initup(&songup, &songdata[1]);
+}
 
 
-       initup(&up, 0);
-       for(i = 0; i < 16 + MAXTRACK; i++) {
-               resources[i] = readchunk(&up, PACKSIZE_RESOURCE);
+#if 0
+XXX MULTISONG TINDR IINDR
+void initsongtabs(u8 idx) {
+       int i;
+       u16 songbase = pgm_read_byte_near(&songaddrs[idx]);
+       u8 ni = pgm_read_byte_near(songbase++) & 0xF;
+       for (i = 0; i < ni; i++) {
+               iindr[i] = pgm_read_byte_near(songbase++);
        }
        }
-
-       initup(&songup, resources[0]);
+       u8 nt = pgm_read_byte_near(songbase++) & 0x3F;
+       for (i = 0; i < nt; i++) {
+               tindr[i] = pgm_read_byte_near(songbase++);
+       }
+       initup(&songup, songbase);
 }
 }
+#endif
 
 void initsong() {
        timetoplay = 0;
 
 void initsong() {
        timetoplay = 0;
@@ -355,24 +401,59 @@ void initsong() {
        songpos = 0;
 
        osc[0].volume = 0;
        songpos = 0;
 
        osc[0].volume = 0;
-       channel[0].inum = 0;
+       channel[0].iptr = NULL;
        osc[1].volume = 0;
        osc[1].volume = 0;
-       channel[1].inum = 0;
+       channel[1].iptr = NULL;
        osc[2].volume = 0;
        osc[2].volume = 0;
-       channel[2].inum = 0;
+       channel[2].iptr = NULL;
        osc[3].volume = 0;
        osc[3].volume = 0;
-       channel[3].inum = 0;
+       channel[3].iptr = NULL;
+}
+
+static void soundirqon() {
+       TCCR0A = 0x02;
+       TCCR0B = T0DIV & 0x7;
+       OCR0A = T0MAX;
+       TIMSK0 |= (1 << OCIE0A);
 }
 
 }
 
+static void soundirqoff() {
+       TIMSK0 &= ~(1 << OCIE0A);
+}
+
+static void hwouton() {
+#ifdef TARGET_AUDIO_PORT
+       TARGET_AUDIO_DDR = 0xff;
+       TARGET_AUDIO_PORT = 0;
+#endif
+
+#ifdef TARGET_AUDIO_PWM_OC2B
+               TCCR2A = (1 << COM2B1) | (1 << WGM21) | (1 << WGM20);
+               TCCR2B = (1 << CS20);
+               OCR2B = 0;
+               TARGET_AUDIO_PWM_OC2B_DDR |= (1 << TARGET_AUDIO_PWM_OC2B_PIN);
+#endif
+}
+
+static void hwoutoff() {
+#ifdef TARGET_AUDIO_PORT
+       TARGET_AUDIO_DDR = 0x00;
+#endif
+
+#ifdef TARGET_AUDIO_PWM_OC2B
+               TARGET_AUDIO_PWM_OC2B_DDR &= ~(1 << TARGET_AUDIO_PWM_OC2B_PIN);
+#endif
+}
+
+int main() __attribute__((naked,noreturn));
 int main() {
        asm("cli");
        CLKPR = 0x80;
        CLKPR = 0x80;
 
 int main() {
        asm("cli");
        CLKPR = 0x80;
        CLKPR = 0x80;
 
+#ifdef TARGET_LIGHT_PORT
        TARGET_LIGHT_DDR = TARGET_LIGHT_ZERO | TARGET_LIGHT_ONE;
        TARGET_LIGHT_DDR = TARGET_LIGHT_ZERO | TARGET_LIGHT_ONE;
-       TARGET_AUDIO_DDR = 0xff;
-
-       TARGET_AUDIO_PORT = 0;
+#endif
 
        initsong();
        initresources();
 
        initsong();
        initresources();
@@ -383,19 +464,16 @@ int main() {
 
        TIMSK0 = 0x02;
 
 
        TIMSK0 = 0x02;
 
-#ifdef TARGET_AUDIO_PWM_OC2B
-        TCCR2A = (1 << COM2B1) | (1 << WGM21) | (1 << WGM20);
-        TCCR2B = (1 << CS20);
-        OCR2B = 0;
-        TARGET_AUDIO_PWM_OC2B_DDR |= (1 << TARGET_AUDIO_PWM_OC2B_PIN);
-#endif
+       soundirqon();
+       hwouton();
 
        asm("sei");
        for(;;) {
                while(!timetoplay);
 
                timetoplay--;
 
        asm("sei");
        for(;;) {
                while(!timetoplay);
 
                timetoplay--;
-               playroutine();
+               playtrack();
+               updateinstruments();
        }
 }
 
        }
 }
 
diff --git a/target/script.ld b/target/script.ld
new file mode 100644 (file)
index 0000000..e683e26
--- /dev/null
@@ -0,0 +1,243 @@
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:4)
+MEMORY
+{
+  text        (rx) : ORIGIN = 0       , LENGTH = 16K
+  rosdata     (rx) : ORIGIN = 0x2000  , LENGTH = 16K
+  data      (rw!x) : ORIGIN = 0x800100, LENGTH = 0xfe00
+  eeprom    (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
+  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
+  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
+  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
+}
+PHDRS
+{
+  headers PT_PHDR FILEHDR PHDRS ;
+  text PT_LOAD ;
+  data PT_LOAD ;
+}
+SECTIONS
+{
+  .hash          : { *(.hash)          }
+  .dynsym        : { *(.dynsym)                }
+  .dynstr        : { *(.dynstr)                }
+  .gnu.version   : { *(.gnu.version)   }
+  .gnu.version_d   : { *(.gnu.version_d)       }
+  .gnu.version_r   : { *(.gnu.version_r)       }
+  .rel.init      : { *(.rel.init)              }
+  .rela.init     : { *(.rela.init)     }
+  .rel.text      :
+    {
+      *(.rel.text)
+      *(.rel.text.*)
+      *(.rel.gnu.linkonce.t*)
+    }
+  .rela.text     :
+    {
+      *(.rela.text)
+      *(.rela.text.*)
+      *(.rela.gnu.linkonce.t*)
+    }
+  .rel.fini      : { *(.rel.fini)              }
+  .rela.fini     : { *(.rela.fini)     }
+  .rel.rodata    :
+    {
+      *(.rel.rodata)
+      *(.rel.rodata.*)
+      *(.rel.gnu.linkonce.r*)
+    }
+  .rela.rodata   :
+    {
+      *(.rela.rodata)
+      *(.rela.rodata.*)
+      *(.rela.gnu.linkonce.r*)
+    }
+  .rel.data      :
+    {
+      *(.rel.data)
+      *(.rel.data.*)
+      *(.rel.gnu.linkonce.d*)
+    }
+  .rela.data     :
+    {
+      *(.rela.data)
+      *(.rela.data.*)
+      *(.rela.gnu.linkonce.d*)
+    }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.got       : { *(.rel.got)               }
+  .rela.got      : { *(.rela.got)              }
+  .rel.bss       : { *(.rel.bss)               }
+  .rela.bss      : { *(.rela.bss)              }
+  .rel.plt       : { *(.rel.plt)               }
+  .rela.plt      : { *(.rela.plt)              }
+  /* Internal text space or external memory.  */
+  .text   :
+  {
+    *(.vectors)
+    KEEP(*(.vectors))
+    /* For data that needs to reside in the lower 64k of progmem.  */
+    *(.progmem.gcc*)
+    *(.progmem*)
+    . = ALIGN(2);
+     __trampolines_start = . ;
+    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
+    *(.trampolines)
+    *(.trampolines*)
+     __trampolines_end = . ;
+    /* For future tablejump instruction arrays for 3 byte pc devices.
+       We don't relax jump/call instructions within these sections.  */
+    *(.jumptables)
+    *(.jumptables*)
+    /* For code that needs to reside in the lower 128k progmem.  */
+    *(.lowtext)
+    *(.lowtext*)
+     __ctors_start = . ;
+     *(.ctors)
+     __ctors_end = . ;
+     __dtors_start = . ;
+     *(.dtors)
+     __dtors_end = . ;
+    KEEP(SORT(*)(.ctors))
+    KEEP(SORT(*)(.dtors))
+    /* From this point on, we don't bother about wether the insns are
+       below or above the 16 bits boundary.  */
+    *(.init0)  /* Start here after reset.  */
+    KEEP (*(.init0))
+    *(.init1)
+    KEEP (*(.init1))
+    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
+    KEEP (*(.init2))
+    *(.init3)
+    KEEP (*(.init3))
+    *(.init4)  /* Initialize data and BSS.  */
+    KEEP (*(.init4))
+    *(.init5)
+    KEEP (*(.init5))
+    *(.init6)  /* C++ constructors.  */
+    KEEP (*(.init6))
+    *(.init7)
+    KEEP (*(.init7))
+    *(.init8)
+    KEEP (*(.init8))
+    *(.init9)  /* Call main().  */
+    KEEP (*(.init9))
+    *(.text)
+    . = ALIGN(2);
+    *(.text.*)
+    . = ALIGN(2);
+    *(.fini9)  /* _exit() starts here.  */
+    KEEP (*(.fini9))
+    *(.fini8)
+    KEEP (*(.fini8))
+    *(.fini7)
+    KEEP (*(.fini7))
+    *(.fini6)  /* C++ destructors.  */
+    KEEP (*(.fini6))
+    *(.fini5)
+    KEEP (*(.fini5))
+    *(.fini4)
+    KEEP (*(.fini4))
+    *(.fini3)
+    KEEP (*(.fini3))
+    *(.fini2)
+    KEEP (*(.fini2))
+    *(.fini1)
+    KEEP (*(.fini1))
+    *(.fini0)  /* Infinite loop after program termination.  */
+    KEEP (*(.fini0))
+     _etext = . ;
+  }  >text :text
+  .rosdata :
+  {
+       PROVIDE (__ros_start = .) ;
+    *(.rosdata)
+    KEEP (*(.rosdata))
+    *(.rosdata.*)
+    KEEP (*(.rosdata.*))
+       PROVIDE (__ros_end = .) ;
+  }  >rosdata :text
+  .data :
+  {
+     PROVIDE (__data_start = .) ;
+    *(.data)
+    *(.data*)
+    *(.rodata)  /* We need to include .rodata here if gcc is used */
+    *(.rodata*) /* with -fdata-sections.  */
+    *(.gnu.linkonce.d*)
+    . = ALIGN(2);
+     _edata = . ;
+     PROVIDE (__data_end = .) ;
+  }  >data :data
+  .bss   : AT (ADDR (.bss))
+  {
+     PROVIDE (__bss_start = .) ;
+    *(.bss)
+    *(.bss*)
+    *(COMMON)
+     PROVIDE (__bss_end = .) ;
+  }  >data :data
+   __data_load_start = LOADADDR(.data);
+   __data_load_end = __data_load_start + SIZEOF(.data);
+  /* Global data not cleared after reset.  */
+  .noinit  :
+  {
+     PROVIDE (__noinit_start = .) ;
+    *(.noinit*)
+     PROVIDE (__noinit_end = .) ;
+     _end = . ;
+     PROVIDE (__heap_start = .) ;
+  }  >data :data
+  .eeprom  :
+  {
+    *(.eeprom*)
+     __eeprom_end = . ;
+  }  >eeprom
+  .fuse  :
+  {
+    KEEP(*(.fuse))
+    KEEP(*(.lfuse))
+    KEEP(*(.hfuse))
+    KEEP(*(.efuse))
+  }  >fuse
+  .lock  :
+  {
+    KEEP(*(.lock*))
+  }  >lock
+  .signature  :
+  {
+    KEEP(*(.signature*))
+  }  >signature
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+}