Jump to content

Photo

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


58 replies to this topic

#26 BuckoBrand OFFLINE  

BuckoBrand

    Chopper Commander

  • 191 posts
  • Sans
  • Location:Hustisford, WI

Posted Mon Dec 3, 2018 11:58 AM

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, Mon Dec 3, 2018 12:02 PM.


#27 Opry99er OFFLINE  

Opry99er

    Quadrunner

  • 10,607 posts
  • Location:Hustisford, WI

Posted Mon Dec 3, 2018 1:00 PM

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?

#28 sparkdrummer OFFLINE  

sparkdrummer

    Stargunner

  • 1,050 posts
  • Status? I don't need no stinkin' status!
  • Location:Phoenix,Arizona

Posted Mon Dec 3, 2018 2:57 PM

See YESTERDAYS NEWS post #93, 4 disks of Christmas Music.



#29 LASooner OFFLINE  

LASooner

    Moonsweeper

  • 373 posts

Posted Tue Dec 4, 2018 8:43 PM

I decided to try and get something done. Hopefully by Christmas. :-)



#30 LASooner OFFLINE  

LASooner

    Moonsweeper

  • 373 posts

Posted Fri Dec 7, 2018 1:05 AM

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!

Attached Files


Edited by LASooner, Fri Dec 7, 2018 1:14 AM.


#31 Opry99er OFFLINE  

Opry99er

    Quadrunner

  • 10,607 posts
  • Location:Hustisford, WI

Posted Fri Dec 7, 2018 1:43 AM

That's awesome!!!!

#32 ti99iuc OFFLINE  

ti99iuc

    Stargunner

  • 1,622 posts
  • Location:Italy

Posted Fri Dec 7, 2018 4:20 AM

really nice LASooner :) thanks for sharing it



#33 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,499 posts
  • HarmlessLion
  • Location:BUR

Posted Fri Dec 7, 2018 3:30 PM

Lots of pacing in that house, can't find the screwdriver to assemble Junior's gifts? ;) 

 

Really slick work :)



#34 LASooner OFFLINE  

LASooner

    Moonsweeper

  • 373 posts

Posted Fri Dec 7, 2018 4:00 PM

Excitedly looking out the window for Santa? 

Thieves cleaning it out?

Swing dancing?

 

I just wanted some activity going on in the windows. :-)



#35 geoanas OFFLINE  

geoanas

    Space Invader

  • 40 posts
  • Location:Greece

Posted Sat Dec 8, 2018 10:54 AM

Very nice! Thanks for sharing it!



#36 blakespot OFFLINE  

blakespot

    Chopper Commander

  • 189 posts
  • Location:Alexandria, VA (USA)

Posted Thu Dec 20, 2018 3:13 PM

Reminding of my contribution to Christmas music, as I already posted three weeks ago:
 
http://atariage.com/...orum/?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.bytecella...r-2018-edition/


bp

#37 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Thu Dec 20, 2018 4:51 PM

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



#38 blakespot OFFLINE  

blakespot

    Chopper Commander

  • 189 posts
  • Location:Alexandria, VA (USA)

Posted Thu Dec 20, 2018 5:30 PM

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



#39 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Thu Dec 20, 2018 5:43 PM

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.



#40 twoodland OFFLINE  

twoodland

    Chopper Commander

  • 196 posts
  • Location:Delaware, OH

Posted Fri Dec 21, 2018 5:54 AM

Thank you LASooner!  It is EPIC!



#41 --- Ω --- OFFLINE  

--- Ω ---

    Hexacorerunner

  • Topic Starter
  • 13,641 posts

Posted Fri Dec 21, 2018 6:45 AM

If you guys want a decent and affordable screen grabber, you might want to check << THIS ONE >> out.  It's what I use.

It's what I used to make that recent Dragon's Lair video if you want an example of it's output.



#42 blakespot OFFLINE  

blakespot

    Chopper Commander

  • 189 posts
  • Location:Alexandria, VA (USA)

Posted Fri Dec 21, 2018 11:55 AM

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



#43 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Fri Dec 21, 2018 4:13 PM

OK, here it is:

 



#44 Nick99 OFFLINE  

Nick99

    Star Raider

  • 66 posts

Posted Sat Dec 22, 2018 4:27 AM

mizapf, wonderful!

This is a "never seen before" on my Geneve.


Edited by Nick99, Sat Dec 22, 2018 4:28 AM.


#45 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Sat Dec 22, 2018 6:45 AM

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==8) 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<<8);
        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<<8);
        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>>8)&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]>>8)&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==8) 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.

Attached Files



#46 ewbray OFFLINE  

ewbray

    Space Invader

  • 23 posts
  • Ex-Helicopter Pilot

Posted Sat Dec 22, 2018 9:11 AM

There is an excellent collection of Christmas songs (including Snoopy's Christmas) on the Genial Travler diskazine #251!

 

http://ftp.whtech.com/genitrav/


Edited by ewbray, Sat Dec 22, 2018 9:15 AM.


#47 Nick99 OFFLINE  

Nick99

    Star Raider

  • 66 posts

Posted Sat Dec 22, 2018 9:20 AM

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, Sat Dec 22, 2018 9:21 AM.


#48 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Sun Dec 23, 2018 7:41 AM

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==8) 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<<8);
        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<<8);
        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>>8)&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]>>8)&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==8) 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;  
}


#49 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,506 posts
  • Location:Germany

Posted Sun Dec 23, 2018 7:44 AM

By the way, the AA formatter removes all empty lines... here is the text file for download.

Attached Files



#50 blakespot OFFLINE  

blakespot

    Chopper Commander

  • 189 posts
  • Location:Alexandria, VA (USA)

Posted Sun Dec 23, 2018 9:54 AM

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






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users