Jump to content
--- Ω ---

Christmas Music and/or Programs for our little TI 'Puter

Recommended Posts

Can we try and get some more Christmas songs programmed into the Ti, like O Christmas Tree or Jingle Bell Rock... I also like We Three Kings.

Edited by BuckoBrand
  • Like 1

Share this post


Link to post
Share on other sites

Hey Buck!! I'll try to do We Three Kings before Christmas. :)

 

Maybe you could get on Magellan and make a nice screen to show while the music plays?

  • Like 1

Share this post


Link to post
Share on other sites

Made this in my spare time over the last few days

 

 

 

load and run in XB

 

 

Props to Harry for making XB256 so easy to knock out something like this quickly.

 

Apologies for the music, I had to figure out sheet music and converting it to TI sound calls. I don't think I have that quite down yet. :-)

 

 

Alright, who's next? Your turn... Go!

letitsnow.zip

Christmas8.bin

Edited by LASooner
  • Like 13

Share this post


Link to post
Share on other sites

Reminding of my contribution to Christmas music, as I already posted three weeks ago:

 

http://atariage.com/forums/topic/218452-99389958-discussion-forum/?p=2877365

 

This disk image contains my XMAS program for Geneve OS.

I don't suppose a video of that Christmas demo on Geneve exists on the web does it? I'd love to add it to:

 

http://www.bytecellar.com/2018/12/13/have-a-helping-of-8-bit-holiday-cheer-2018-edition/

 

 

bp

Share this post


Link to post
Share on other sites

Yes, go ahead. Did you already create the video, or do you suggest that I do it?

 

I was hoping a video existed already. I am not currently setup with MESS to emulate Geneve, I'm afraid. Would be superb if you had the ability and inclination to do so, I must say.

 

 

bp

Share this post


Link to post
Share on other sites

I can create it in webm format using the tool simplescreenrecorder.

 

How long should it be? I seem to remember it can run indefinitely, starting over after the last song has finished.

Share this post


Link to post
Share on other sites

I can create it in webm format using the tool simplescreenrecorder.

 

How long should it be? I seem to remember it can run indefinitely, starting over after the last song has finished.

That would be swell. However long you think? Obv the full run-through and if it repeats or persists forever in some way, maybe overall 4 or 5 mins? Whatever you think.

 

Thanks!

 

bp

Share this post


Link to post
Share on other sites

Maybe you are interested in some details about this program ... 25 years ago, I have to check for myself.

 

  • I wrote it in TIC (C99 on the Geneve), also to see how easy it is to directly access devices.
  • Each melody is defined in a DIS/VAR80 file. The SONGS file lists all songs to be played.
  • A simple music engine plays the notes, including a "piano effect" that has a high volume first and then becomes increasingly attenuated.
  • I drew the picture in Myart in Graphics mode 6. The raw picture is shown below. For the flame, I created several mini-frames which are loaded below the visible screen.
  • The mini-frames are copied by using the v9938 logical block copy (bitlbc).

The format of the music files:

  • Every generator has its section, separated by "====" (at least one "=").
  • Tempo the speed, but inverse (higher value is slower)
  • Laenge is length of the decay of a note. Make it shorter for a staccato.
  • Strophenzahl is number of repetitions (stanzas)
  • For each note: xx nn tt: xx is the length (in 32nds; 16 is a half note), nn is the pitch (C-D-E-F-G-A-H plus octave number as natural and lowercase as flat; mind that H is used in Germany instead of B), tt is the attenuation (1 loud, 15 quiet)
  • Pianoeffekt means the piano effect (loud with decay), the opposite Orgeleffekt (organ)
  • Each of the settings can be abbreviated to the first letter.

 

SONGS file:

 

 

ALLEJAHR
IHRKINDER
SCHNEE
TANNENBAUM
KMTIHRHRTN
ESIST1ROS
SUESSERGL
STILLENCHT
ODUFROEHL

 

(I don't know the English titles; only that STILLENCHT, "Stille Nacht", means "Silent night". And from my Ireland trip I know it is "Oiche chiuin" (yes, and I can pronounce it :-) )).

 

ALLEJAHR:

 

 

Pianoeffekt
Tempo 45
Laenge 70
Strophenzahl 3
12 A3 1
4 H3 1
8 A3 1
8 G2 1
16 f2 1
16 E2 1
8 D2 1
4 E2 1
4 f2 1
8 G2 1
8 f2 1
32 E2 1
8 f2 1
8 A3 1
8 H3 1
8 A3 1
16 D3 1
8 c3 1
8 H3 1
8 A3 1
4 G2 1
4 f2 1
8 G2 1
8 A3 1
24 f2 1
8 F2 15
============
Pianoeffekt
12 f2 1
4 G2 1
8 f2 1
8 E2 1
16 D2 1
16 c2 1
8 D2 1
4 c2 1
4 D2 1
8 E2 1
8 D2 1
32 c2 1
32 D2 1
16 H3 1
8 A3 1
8 G2 1
16 D2 1
8 H2 1
8 c2 1
24 D2 1
8 E2 15
=============
Pianoeffekt
8 D0 6
16 D1 6
8 A1 6
8 D1 6
8 A2 6
8 A1 6
8 A2 6
8 f1 6
4 E1 6
4 D1 6
8 c1 6
8 D1 6
8 A2 6
8 H2 6
4 A2 6
4 G1 6
4 f1 6
4 E1 6
8 D1 6
8 f1 6
8 G1 6
8 f1 6
8 G1 6
8 G0 6
8 D1 6
8 G1 6
8 f1 6
4 E1 6
4 D1 6
8 E1 6
8 A1 6
8 D1 6
8 A1 6
8 D0 6
8 C0 15

 

The program itself:

 

 

/* Weihnachtsmusikprogramm -- Version 1.1    */
/* Michael Zapf, 12.12.1993                  */
/* ins Englische uebersetzt am 19.12.1998    */
#include <stdio_h>
#include <video_h>
#define FALSE 0
#define TRUE 1
FILE disk;
char filename[20],buffer[130],s[30];
char *lied[20];
int  rpz[3];
int  *value, *ptr, *ff, rhpos[9];
int  pal[3][16]={{0,0,0},{0,0,0},{1,6,1},{3,7,3},
                 {1,1,7},{2,3,7},{5,1,1},{2,6,7},
                 {7,1,1},{7,3,3},{6,6,1},{6,6,4},
                 {1,4,1},{6,2,5},{5,5,5},{7,7,7}};
int  zeit[3], flag[3], durchgang[3], k, l, lp, aktiv[3];
int  refrain[3], piano[3], tempo, laenge, st, ende;
int  chk, strophen;
int  drvsp;
char zeit1[10],zeit2[10];
char min[3],sek[3];
struct notentyp { int             freq;
                  int             dauer;
                  int             laut;
                  struct notentyp *naechste;
                  struct notentyp *naechsteref; } *liste[3], *note, dummy,
                                                  *stimme[3];
/* Toene aus E/A-Handbuch; 5 Oktaven, jeweils von A bis g         */
/* Kleinbuchstaben sind jeweils einen Halbton hoeher              */
/* Folge: A a H C c D d E F f G g                                 */
int  frequenz[12][5] =
{  {0x93F,0x03C,0xA38,0x735,0x732,0xA2F,0xF2C,0x72A,0x128,0xD25,0xB23,0xB21},
   {0xC1F,0x01E,0x51C,0xC1A,0x419,0xD17,0x816,0x315,0x014,0xE12,0xD11,0xD10},
   {0xE0F,0x00F,0x20E,0x60D,0xA0C,0xE0B,0x40B,0xA0A,0x00A,0x709,0xF08,0x708},
   {0xF07,0x807,0x107,0xB06,0x506,0xF05,0xA05,0x505,0x005,0xC04,0x704,0x304},
   {0x004,0xC03,0x903,0x503,0x203,0x003,0xD02,0xA02,0x802,0x602,0x402,0x202} };
char bez[12] = { 'A', 'a', 'H', 'C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g' } ;
main(argc, argv)
int argc; char *argv[];
{   printf("\f");
    locate(10,10);
    printf("XMAS   ----  a Christmas music program");
    locate(12,10);
    printf("programmed in Clint Pulley's TIC V1.61");
    locate(13,10);
    printf("by Michael Zapf, December 1993");
    locate(17,10);
    printf("CANDLE by Michael Zapf");
    locate(20,10);
    printf("Do not modify the picture! (The program will not ");
    locate(21,10);
    printf("run any more.)");
    locate(24,20);
    printf("Press any key.");
    while (!poll(0)) ;
    time(zeit1);
    if (!laden())
    {   ruecks();
        puts("\nDidn't I tell you to leave the picture untouched?\n");
        exit(7);    }
    time(zeit2);
    drvsp = 23-holezeit(zeit1,zeit2)/2;
    if (drvsp<2) drvsp=2;
    if (argc==2) {  if (chk=einladen(argv[1],drvsp)) play();  }
    else
    {   l=holeliste(lied);
        chk=TRUE;
        while ((poll(0)!=0x1b)&&chk)
            for (lp=0; ((lp<l)&&(poll(0)!=0x1b)&&chk); lp++)
            {   free(ff);
                if (chk=einladen(lied[lp],drvsp)) play();   }   }
    if (chk) ruecks();
    freeall();
    exit(7);    }
/*  Unterprogramme  */
void ruecks()
{   int k;
    for (k=0; k<16; k++) palette(k+1,pal[k][0],pal[k][1],pal[k][2]);
    txtmode();  }
int holezeit(zt1,zt2)
char *zt1,*zt2;
{   int ztdr;
    strncpy(min,zt2+3,2);
    ztdr=atoi(min)*60;
    strncpy(min,zt1+3,2);
    ztdr-=atoi(min)*60;
    strncpy(sek,zt2+6,2);
    ztdr+=atoi(sek);
    strncpy(sek,zt1+6,2);
    ztdr-=atoi(sek);
    if (ztdr<0) ztdr+=3600;
    return ztdr;  }
int holeliste(lieder)
char *lieder[20];
{   int  zahl;
    char liedname[21];
    zahl=0;
    disk=fopen("SONGS","r");
    if (disk==0)
    {   ruecks();
        puts("\nSong list SONGS not found!");
        puts("\n\nYou can use XMAS <music file>.\n");
        exit(7);    }
    while ((fgets(liedname,20,disk)!=NULL)&&(zahl<20))
    {   lieder[zahl] = malloc(22);
        strcpy(lieder[zahl++], liedname); }
    ff = malloc(2);
    fclose(disk);
    return zahl;    }
void play()
{   int gen, weiter,str;
    unsigned rh,rh1;
    char *ton;
    for (str=0; str<strophen; str++)
    {   weiter = TRUE;
        rh=rh1=0;
        for (gen=0; gen<3; gen++)
        {   zeit[gen] = 0;
            flag[gen] = FALSE;
            aktiv[gen] = FALSE;
            stimme[gen] = NULL;
            stimme[gen] = liste[gen];
            refrain[gen] = FALSE;   }
        while (weiter)
        {   for (gen=0; gen<3; gen++)
                if ((kontrolle(gen, &zeit[gen], stimme[gen]->laut)==0)
                   &&(stimme[gen]!=NULL)) flag[gen] = tonausgabe(gen);
            for (k=0; k<tempo; k++) ;
            if (rh++>120)
            {   rh=0;
                if (++rh1== rh1=0;
                bitlbc(220,rhpos[rh1],rpz[2],rhpos[8]+1,27,32,0,0); }
            weiter = flag[0]|flag[1]|flag[2];
            if (poll(0)) weiter=FALSE;  }
        ton = 0xF120;
        *ton = 0x9F; *ton = 0xBF; *ton = 0xDF; *ton = 0xFF;  }  }
int tonausgabe(g)
int g;
{   int  gencode,lautst, freqcd;
    char *ton, *byte;
    if (stimme[g]->naechsteref!=NULL)
    {   note = (refrain[g])? stimme[g]->naechste : stimme[g]->naechsteref;
        refrain[g] = !refrain[g];   }
    else note = stimme[g]->naechste;
    if (note!=NULL)
    {   stimme[g] = note;
        freqcd = note->freq;
        lautst = note->laut;
        zeit[g] = note->dauer * tempo;
        ton = 0xF120;                   /* Tongenerator-Adresse */
        gencode = (g+4) << 13 ;
        freqcd = freqcd | gencode;
        byte = &freqcd;
        *ton = *(byte++); *ton = *byte;
        lautst = (gencode+0x1000) | (lautst<<;
        byte = &lautst;
        *ton = *byte;
        aktiv[g] = TRUE;
        durchgang[g] = 0;
        return TRUE;    }
    else
    {   aktiv[g] = FALSE;
        return FALSE;  }   }
int kontrolle(gn, dauer, lautstk)
int gn, *dauer, lautstk;
{   int  gencode, lautst, lw, fakt;
    char *ton, *byte;
    if (aktiv[gn])
    {   gencode = (gn+4)<<13;
        ton = 0xF120;
        durchgang[gn]++;
        lw = lautstk+durchgang[gn]/laenge;
        if ((!piano[gn]) && (lw>lautstk+3)) lw=lautstk+3;
        if ((--(*dauer)==0)||(lw>15)) lw = 15;
        lautst = gencode+0x1000+(lw<<;
        byte = &lautst;
        *ton = *byte;
        return *dauer;   }  }

/*  Einladen des Bildes  */
int laden()
{   int  i,j,zeile,spalte,z1;
    int  laenge,reclen,rp,rp1,farbe;
    int  unten;
    unsigned check;
    disk = fopen("CANDLE","R128");
    if (disk==0) { puts("\n\nOPEN error!"); return 0; }
    grfmode(6,1);
    bitclr();
    bithbc(0,0,212,0,43,512,0);
    check=0;
    reclen = fread(buffer,128,disk);
    value = buffer;
    for (i=1;i<17;i++)
    {   j = value[i];
        check+=j;
        palette(i,(j>>12)&15,j&15,(j>>&15);   }
    i--; spalte=zeile=1; rp=0; rp1=0; unten=FALSE;
    while ((zeile < 213)||unten)
    {   if (++i >= reclen/2)
        {   reclen = fread(buffer,128,disk);
            if (reclen < 0) { txtmode(); puts("\nREAD error!"); return 0; }
            i = 0;  }
        farbe  = ((value[i]>>12)&15)+1;
        laenge = ((value[i]>>&15)*256+(value[i]&255);
        if (farbe==13) rhpos[rp++] = spalte;
        else
        {   if (farbe==2)
            {   rpz[rp1++] = zeile;
                if (rp1==1)
                {   unten=TRUE; z1=zeile; zeile=220; spalte=rhpos[0]; }
                if (rp1==2)
                {   unten=FALSE; zeile=zeile-220+z1; spalte=rhpos[0]; }
                if ((rp1==3)&&(rp!=0))
                {   rhpos[8]=spalte; rp=0;  }   }
            else line(spalte,zeile,spalte+laenge-1,zeile,farbe);    }
        if ((spalte=spalte+laenge)>512) { zeile++; spalte=1; }
        check+=value[i];   }
    if (check!=27789) check=0;
    fclose(disk);
    return check;  }

/*  Routine zum Einladen der Tondaten  */
int einladen(name,drv)
int drv;
char *name;
{   FILE datei;
    char zeile[81];
    char nme[81];
    int  gen, lng, groesse, i, j, lautst, refanf, refende;
    int  akz, fehl, rh, rh1;
    struct notentyp *ref1, *ref2;
    if ((datei = fopen(name,"r"))==NULL)
    {   ruecks();
        puts("\nError on open!\n");
        return FALSE;   }
    gen = 0;
    groesse = sizeof(dummy);
    for (i=0; i<3; i++)
    {   liste[i] = malloc(groesse);
        piano[i] = FALSE;
        liste[i]->naechste = NULL;
        liste[i]->naechsteref = NULL;   }
    note = liste[0];
    refanf = refende = FALSE;
    ref1 = ref2 = NULL;
    tempo  = 100;
    laenge = 100;
    strophen = 1;
    akz = 0; rh=rh1=0;
    fehl=FALSE;
    while ((fgets(zeile, 81, datei)!=NULL)&&!fehl)
    {   akz++;
        if (rh++>drv)
        {   rh=0;
            if (++rh1== rh1=0;
            bitlbc(220,rhpos[rh1],rpz[2],rhpos[8]+1,27,32,0,0); }
        switch(zeile[0])
        {   case '=':   if (++gen==3)
                        {   ruecks();
                            puts("\nToo many voices!\n");
                            fehl=TRUE;  break;  }
                        note = liste[gen];
                        ref1 = ref2 = NULL;
                        break;
            case 'S':   sscanf(zeile,"%s %d",nme,&strophen);  break;
            case 'P':   piano[gen] = TRUE; break;
            case 'O':   piano[gen] = FALSE; break;
            case 'L':   sscanf(zeile, "%s %d", nme, &laenge);
                        if (laenge>500)
                        {   ruecks();
                            puts("\nTone length > 500!\n");
                            fehl=TRUE;  }
                        break;
            case 'T':   sscanf(zeile, "%s %d", nme, &tempo);
                        if (tempo>1000)
                        {   ruecks();
                            puts("\nTempo > 1000!\n");
                            fehl=TRUE;  }
                        break;
            case 'V':
            case NULL:
            case ' ':
            case '*':   break;
            case '|':   refanf = TRUE;
                        ref2 = NULL; break;
            case 'E':   if (note==liste[gen])
                        {   ruecks();
                            puts("\nRepetition error!\n");
                            fehl=TRUE;  }
                        else ref2 = note; break;
            case ':':   if (ref2==NULL) note->naechsteref = ref1;
                        else
                        {   note->naechste = ref1;
                            ref2->naechsteref = ref2->naechste;
                            ref2->naechste = NULL;  }
                        refende = TRUE; break;
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':   sscanf(zeile, "%d %s %d", &lng, nme, &lautst);
                        note->naechste = malloc(groesse);
                        if ((refanf)||(ref1==NULL)) ref1 = note->naechste;
                        refanf = FALSE;
                        if ((refende)&&(ref2!=NULL))
                        {   ref2->naechste = note->naechste;
                            note->naechste = ref1;
                            note = ref2->naechste;  }
                        else note = note->naechste;
                        refende = FALSE;
                        note->dauer = lng;
                        note->laut = lautst;
                        note->naechste = NULL;
                        note->naechsteref = NULL;
                        for (i=0, j=-1; i<12; i++)
                            if (nme[0]==bez[i]) { j=i; break; }
                        i = ((int)nme[1])-48;
                        note->freq = frequenz[i][j];
                        break;
            default:    ruecks();
                        puts("\nData error!\n");
                        fehl=TRUE;  }   }
    fclose(datei);
    if (fehl) {  printf("Error in line %d.\n",akz); return FALSE; }
    else return TRUE;   }

 

That's all.

post-35000-0-45938100-1545482491.png

  • Like 3

Share this post


Link to post
Share on other sites

Mizapf, Thanks a lot for the information, it makes me think that I should study C and try to make something myself.

In Sweden, we were two Geneve owners in 1990 as far as I know, so there wasn't much activity so to speak.

 

Thanks again for the inspire!

Edited by Nick99

Share this post


Link to post
Share on other sites

I did some renaming and reformatting, and I added some comments so that interested people may better understand the XMAS player. (It still compiles. :-) ) You can now also use the name "B" for the note between A and C (which is "H" in German, our scale is C-D-E-F-G-A-H).

 

 

/* Christmas music -- Version 1.2       */
/* Michael Zapf, Dec 12, 1993           */
/* translated texts Dec 19, 1998        */
/* translated program code Dec 22, 2018 */
#include <stdio_h>
#include <video_h>
#define FALSE 0
#define TRUE 1
FILE disk;
char filename[20],buffer[130],s[30];
char *song[20];
int  rpz[3];
int  *value, *ptr, *ff, rhpos[9];
int  pal[3][16]={{0,0,0},{0,0,0},{1,6,1},{3,7,3},
                 {1,1,7},{2,3,7},{5,1,1},{2,6,7},
                 {7,1,1},{7,3,3},{6,6,1},{6,6,4},
                 {1,4,1},{6,2,5},{5,5,5},{7,7,7}};
int  time[3], flag[3], pass[3], k, l, lp, active[3];
int  refrain[3], piano[3], tempo, length, st, ende;
int  chk, stanzas;
int  drvsp;
char time1[10],time2[10];
char min[3],sek[3];
struct notetype
{
   int freq;
   int duration;
   int vol;
   struct notetype *next;
   struct notetype *nextref;
} *list[3], *note, dummy, *voice[3];
/* Taken from the E/A manual; 5 octaves, each from A to g         */
/* Lowercase letters are sharp.  */
/* Sequence: A a H(B) C c D d E F f G g                                 */
int  frequency[12][5] =
{ 
   {0x93F,0x03C,0xA38,0x735,0x732,0xA2F,0xF2C,0x72A,0x128,0xD25,0xB23,0xB21},
   {0xC1F,0x01E,0x51C,0xC1A,0x419,0xD17,0x816,0x315,0x014,0xE12,0xD11,0xD10},
   {0xE0F,0x00F,0x20E,0x60D,0xA0C,0xE0B,0x40B,0xA0A,0x00A,0x709,0xF08,0x708},
   {0xF07,0x807,0x107,0xB06,0x506,0xF05,0xA05,0x505,0x005,0xC04,0x704,0x304},
   {0x004,0xC03,0x903,0x503,0x203,0x003,0xD02,0xA02,0x802,0x602,0x402,0x202}
};
/* B will be replaced by H automatically. */
char notename[12] = { 'A', 'a', 'H', 'C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g'
} ;
main(argc, argv) int argc; char *argv[];
{  
    printf("\f");
    locate(10,10); printf("XMAS   ----  a Christmas music program");
    locate(12,10); printf("programmed in Clint Pulley's TIC V1.61");
    locate(13,10); printf("by Michael Zapf, December 1993");
    locate(17,10); printf("CANDLE by Michael Zapf");
    locate(20,10); printf("Do not modify the picture! (The program will not ");
    locate(21,10); printf("run anymore.)");
    locate(24,20); printf("Press any key.");
   
    while (!poll(0)) ;
    gettime(time1);
    if (!loadpict())
    {
        restoretxmode();
        puts("\nDidn't I tell you to leave the picture untouched?\n");
        exit(7);   
    }
    gettime(time2);
    /* Calculate the drive speed. This is for keeping
       the candle animated during loading. */
    drvsp = 23-gettime(time1,time2)/2;
    if (drvsp<2) drvsp=2;
    if (argc==2)
    { 
        if (chk=loadmusic(argv[1],drvsp)) play(); 
    }
    else
    {  
        l=getlist(song);
        chk=TRUE;
        while ((poll(0)!=0x1b)&&chk)
        {
            for (lp=0; ((lp<l)&&(poll(0)!=0x1b)&&chk); lp++)
            {  
                free(ff);
                if (chk=loadmusic(song[lp],drvsp))
                    play();  
            }
        }
    }
    if (chk) restoretxmode();
    freeall();
    exit(7);
}
/*  Subprograms  */
void restoretxmode()
{  
    int k;
    for (k=0; k<16; k++)
       palette(k+1,pal[k][0],pal[k][1],pal[k][2]);
    txtmode();
}
int gettime(zt1,zt2) char *zt1,*zt2;
{  
    int ztdr;
    strncpy(min,zt2+3,2);
    ztdr=atoi(min)*60;
    strncpy(min,zt1+3,2);
    ztdr-=atoi(min)*60;
    strncpy(sek,zt2+6,2);
    ztdr+=atoi(sek);
    strncpy(sek,zt1+6,2);
    ztdr-=atoi(sek);
    if (ztdr<0) ztdr+=3600;
    return ztdr;
}
int getlist(songs) char *songs[20];
{  
    int  count;
    char songname[21];
    count=0;
    disk=fopen("SONGS","r");
    if (disk==0)
    {
        restoretxmode();
        puts("\nSong list SONGS not found!");
        puts("\n\nYou can use XMAS <music file>.\n");
        exit(7);   
    }
    while ((fgets(songname,20,disk)!=NULL)&&(count<20))
    {
        songs[count] = malloc(22);
        strcpy(songs[count++], songname);
    }
    /* Not sure what this is used for. malloc bug remedy? */
    ff = malloc(2);
    fclose(disk);
    return count;   
}
void play()
{
    int gen, running,str;
    unsigned rh,rh1;
    char *soundaddr;
    for (str=0; str<stanzas; str++)
    {
        running = TRUE;
        rh=rh1=0;
        for (gen=0; gen<3; gen++)
        {
            time[gen] = 0;
            flag[gen] = FALSE;
            active[gen] = FALSE;
            voice[gen] = NULL;
            voice[gen] = list[gen];
            refrain[gen] = FALSE;  
        }
        /* Main loop */
        while (running)
        {
            for (gen=0; gen<3; gen++)
                if ((contsound(gen, &time[gen], voice[gen]->vol)==0)
                   &&(voice[gen]!=NULL))
                   flag[gen] = soundout(gen);
            /* Busy wait for the note length */
            for (k=0; k<tempo; k++) ;
            if (rh++>120)
            {
                /* Next frame (0..7) */
                rh=0;
                if (++rh1== rh1=0;
                bitlbc(220,rhpos[rh1],rpz[2],rhpos[8]+1,27,32,0,0);
            }
            running = flag[0]|flag[1]|flag[2];
            if (poll(0)) running=FALSE; 
        }
       
        /* Turn off sound. */
        soundaddr = 0xF120;
        *soundaddr = 0x9F;
        *soundaddr = 0xBF;
        *soundaddr = 0xDF;
        *soundaddr = 0xFF; 
    } 
}
int soundout(g) int g;
{  
    int  gencode,volume, freqcd;
    char *soundaddr, *byte;
    if (voice[g]->nextref!=NULL)
    {
        note = (refrain[g])? voice[g]->next : voice[g]->nextref;
        refrain[g] = !refrain[g];  
    }
    else note = voice[g]->next;
    if (note!=NULL)
    {
        voice[g] = note;
        freqcd = note->freq;
        volume = note->vol;
        time[g] = note->duration * tempo;
        soundaddr = 0xF120;                   /* sound generator */
        gencode = (g+4) << 13 ;
        freqcd = freqcd | gencode;
        byte = &freqcd;
        *soundaddr = *(byte++);
        *soundaddr = *byte;
        volume = (gencode+0x1000) | (volume<<;
        byte = &volume;
        *soundaddr = *byte;
        active[g] = TRUE;
        pass[g] = 0;
        return TRUE;   
    }
    else
    {
        active[g] = FALSE;
        return FALSE; 
    }  
}
/* Continue the started sound. Depends on the desired effect. */
int contsound(gn, duration, volumek) int gn, *duration, volumek;
{  
    int  gencode, volume, lw, fakt;
    char *soundaddr, *byte;
    if (active[gn])
    {
        gencode = (gn+4)<<13;
        soundaddr = 0xF120;
        pass[gn]++;
        lw = volumek+pass[gn]/length;
        if ((!piano[gn]) && (lw>volumek+3)) lw=volumek+3;
        if ((--(*duration)==0)||(lw>15)) lw = 15;
        volume = gencode+0x1000+(lw<<;
        byte = &volume;
        *soundaddr = *byte;
        return *duration;
   }
}
/*  Load the picture. Implements a Myarc format reader. */
int loadpict()
{  
    int  i,j,row,column,z1;
    int  length,reclen,rp,rp1,color;
    int  bottom;
    unsigned check;
    disk = fopen("CANDLE","R128");
    if (disk==0)
    {
        puts("\n\nOPEN error!"); return 0;
    }
    grfmode(6,1);
    bitclr();
    bithbc(0,0,212,0,43,512,0);
    check=0;
    reclen = fread(buffer,128,disk);
    value = buffer;
    for (i=1;i<17;i++)
    {
        j = value[i];
        check+=j;
        palette(i,(j>>12)&15,j&15,(j>>&15);  
    }
   
    i--;
    column=row=1;
    rp=0;
    rp1=0;
    bottom=FALSE;
    while ((row < 213)||bottom)
    {
        if (++i >= reclen/2)
        {
            reclen = fread(buffer,128,disk);
            if (reclen < 0)
            {
                txtmode();
                puts("\nREAD error!");
                return 0;
            }
            i = 0; 
        }
        color  = ((value[i]>>12)&15)+1;
        length = ((value[i]>>&15)*256+(value[i]&255);
        if (color==13) rhpos[rp++] = column;
        else
        {
            if (color==2)
            {
                rpz[rp1++] = row;
                if (rp1==1)
                {
                    bottom=TRUE;
                    z1=row;
                    row=220;
                    column=rhpos[0];
                }
                if (rp1==2)
                {
                    bottom=FALSE;
                    row=row-220+z1;
                    column=rhpos[0];
                }
                if ((rp1==3)&&(rp!=0))
                {  
                    rhpos[8]=column; rp=0; 
                }
            }
            else
                line(column,row,column+length-1,row,color);   
        }
        if ((column=column+length)>512)
        {
            row++;
            column=1;
        }
        check+=value[i];  
    }
    /* Check whether the picture was changed.
       If you remove the next line, well ... then it won't notice. */
    if (check!=27789) check=0;
    fclose(disk);
    return check; 
}
/*  Load a music file. Note that while the file is being loaded,
    the candle continues to burn.  */
int loadmusic(name,drv) int drv; char *name;
{  
    FILE mfile;
    char row[81];
    char nme[81];
    int  gen, lng, rsize, i, j, volume, refanf, refende;
    int  akz, error, rh, rh1;
    struct notetype *ref1, *ref2;
   
    if ((mfile = fopen(name,"r"))==NULL)
    {  
        restoretxmode();
        puts("\nerror on open!\n");
        return FALSE;  
    }
    gen = 0;
    rsize = sizeof(dummy);
    for (i=0; i<3; i++)
    {
        list[i] = malloc(rsize);
        piano[i] = FALSE;
        list[i]->next = NULL;
        list[i]->nextref = NULL;  
    }
    note = list[0];
    refanf = refende = FALSE;
    ref1 = ref2 = NULL;
    tempo  = 100;
    length = 100;
    stanzas = 1;
    akz = 0; rh=rh1=0;
    error=FALSE;
    /* Main load loop */
    while ((fgets(row, 81, mfile)!=NULL)&&!error)
    {  
        akz++;
        if (rh++>drv)
        {
            /* Enough time has passed to show the next candle frame. */
            rh=0;
            if (++rh1== rh1=0;
            bitlbc(220,rhpos[rh1],rpz[2],rhpos[8]+1,27,32,0,0);
        }
        switch(row[0])
        {
            case '=':  
               if (++gen==3)
               {
                   restoretxmode();
                   puts("\nToo many voices!\n");
                   error=TRUE; 
                   break; 
               }
               note = list[gen];
               ref1 = ref2 = NULL;
               break;
            case 'S':
               sscanf(row,"%s %d",nme,&stanzas); 
               break;
            case 'P':
               piano[gen] = TRUE;
               break;
            case 'O':
               piano[gen] = FALSE;
               break;
            case 'L':
               sscanf(row, "%s %d", nme, &length);
               if (length>500)
               {  
                   restoretxmode();
                   puts("\nNote length > 500!\n");
                   error=TRUE; 
               }
               break;
            case 'T':
               sscanf(row, "%s %d", nme, &tempo);
               if (tempo>1000)
               {
                   restoretxmode();
                   puts("\nTempo > 1000!\n");
                   error=TRUE; 
               }
               break;
            case 'V':
            case NULL:
            case ' ':
            case '*':
               break;
            case '|':
               refanf = TRUE;
               ref2 = NULL;
               break;
            case 'E':
               if (note==list[gen])
               {  
                   restoretxmode();
                   puts("\nRepetition error!\n");
                   error=TRUE; 
               }
               else
                   ref2 = note;
               break;
            case ':':
               if (ref2==NULL) note->nextref = ref1;
               else
               {
                   note->next = ref1;
                   ref2->nextref = ref2->next;
                   ref2->next = NULL; 
               }
               refende = TRUE;
               break;
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
               sscanf(row, "%d %s %d", &lng, nme, &volume);
               note->next = malloc(rsize);
               if ((refanf)||(ref1==NULL))
                   ref1 = note->next;
               refanf = FALSE;
               if ((refende)&&(ref2!=NULL))
               {
                   ref2->next = note->next;
                   note->next = ref1;
                   note = ref2->next; 
               }
               else note = note->next;
               refende = FALSE;
               note->duration = lng;
               note->vol = volume;
               note->next = NULL;
               note->nextref = NULL;
               for (i=0, j=-1; i<12; i++)
               {
                   /* Translate the B to H. */
                   if (nme[0]=='B') nme[0]='H';
                   if (nme[0]==notename[i])
                   {
                       j=i;
                       break;
                   }
               }
               i = ((int)nme[1])-48;
               note->freq = frequency[i][j];
               break;
            default:
               restoretxmode();
               puts("\nData error!\n");
               error=TRUE;
        }
    }
   
    fclose(mfile);
    if (error)
    { 
        printf("Error in line %d.\n",akz);
        return FALSE;
    }
    else return TRUE;  
}
  • Like 1

Share this post


Link to post
Share on other sites

Thanks so much, mizapf! I've added this to my aforelinked christmas demo roundup blog post. Such a rare thing, that little program on that little platform.

 

 

bp

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...