/*
- * "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525
- *
- * First version in 1987 by
- * Joachim von Bassewitz (joachim@von-bassewitz.de) and
- * Ullrich von Bassewitz (ullrich@von-bassewitz.de).
- *
- * C conversion in 1998 by
- * Ullrich von Bassewitz (ullrich@von-bassewitz.de)
- *
- */
+** "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525
+**
+** First version in 1987 by
+** Joachim von Bassewitz (joachim@von-bassewitz.de) and
+** Ullrich von Bassewitz (ullrich@von-bassewitz.de).
+**
+** C conversion in 1998 by
+** Ullrich von Bassewitz (ullrich@von-bassewitz.de)
+**
+*/
#include <stdio.h>
+#include <string.h>
#include <time.h>
#include <conio.h>
#include <cbm.h>
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Tables with voice data.
- *
- * Bit Description
- * -------------------------------------------
- * 15 Pause bit.
- * 12-14 Octave
- * 8-11 Tone (index into frequency table)
- * 7 Unused. Was thought as a control bit in the original version to
- * change SID parameters, but this was never implemented.
- * 0-6 Length of the tone in ticks.
- *
- */
+**
+** Bit Description
+** -------------------------------------------
+** 15 Pause bit.
+** 12-14 Octave
+** 8-11 Tone (index into frequency table)
+** 7 Unused. Was thought as a control bit in the original version to
+** change SID parameters, but this was never implemented.
+** 0-6 Length of the tone in ticks.
+**
+*/
-static int Voice1 [] = {
+static unsigned Voice1 [] = {
0x5708,0x8004,0x5204,0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,
0x6208,0x8008,0x6008,0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,
0x5604,0x5904,0x5208,0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,
0x0000
};
-static int Voice2 [] = {
+static unsigned Voice2 [] = {
0x4708,0x8004,0x4204,0x4708,0x8004,0x4204,0x4704,0x4204,0x4704,0x4B04,
0x5208,0x8008,0x5008,0x8004,0x4904,0x5008,0x8004,0x4904,0x5004,0x4904,
0x4604,0x4904,0x4208,0x8008,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,
0x0000
};
-static int Voice3 [] = {
+static unsigned Voice3 [] = {
0x3708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704,0x3B04,
0x3208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004,0x3904,
0x3604,0x4904,0x4208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,
-/* Screen sizes */
-#ifdef __CBM610__
-# define MAX_X 80
-#else
-# define MAX_X 40
-#endif
-
-
-
#if defined(__C64__) || defined(__CBM510__)
static unsigned long FreqTab [12] = {
#ifndef NTSC
typedef struct {
- unsigned char DoneMask; /* Set this if we're done */
- unsigned char Trigger; /* Trigger value */
- unsigned char Ticks; /* Ticks for this tone */
- unsigned Freq; /* Actual frequency value */
- int* Data; /* Pointer to data */
- struct __sid_voice* Voice; /* Pointer to sid registers */
+ unsigned char DoneMask; /* Set this if we're done */
+ unsigned char Trigger; /* Trigger value */
+ unsigned char Ticks; /* Ticks for this tone */
+ unsigned Freq; /* Actual frequency value */
+ unsigned* Data; /* Pointer to data */
+ struct __sid_voice* Voice; /* Pointer to sid registers */
} VoiceCtrl;
/* Control structs for all three voices */
&V1, &V2, &V3
};
+/* Screen dimensions */
+static unsigned char XSize, YSize;
+
/* Variable that contains the time of the next clock tick to play a note */
static unsigned char NextClock;
static clock_t StartTime;
/* Number of ticks for each tone */
-#define TICKS_PER_TONE 4
+#define TICKS_PER_TONE 4
/* Done flag. Contains one bit for each voice. Will contain 0x07 if all
- * voices have finished playing.
- */
+** voices have finished playing.
+*/
static unsigned char Done;
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
/* Make a divider line */
{
cputcxy (0, Y, CH_LTEE);
- chline (MAX_X - 2);
+ chline (XSize - 2);
cputc (CH_RTEE);
}
/* Make a nice screen */
{
typedef struct {
- unsigned char X;
- unsigned char Y;
- char* Msg;
+ unsigned char Y;
+ char* Msg;
} TextDesc;
static TextDesc Text [] = {
- { (MAX_X / 2) - 11, 2, "Wolfgang Amadeus Mozart" },
- { (MAX_X / 2) - 12, 4, "\"Eine kleine Nachtmusik\"" },
- { (MAX_X / 2) - 4, 5, "(KV 525)" },
- { (MAX_X / 2) - 14, 9, "Ported to the SID in 1987 by" },
- { (MAX_X / 2) - 10, 11, "Joachim von Bassewitz" },
- { (MAX_X / 2) - 13, 12, "(joachim@von-bassewitz.de)" },
- { (MAX_X / 2) - 1, 13, "and" },
- { (MAX_X / 2) - 10, 14, "Ullrich von Bassewitz" },
- { (MAX_X / 2) - 13, 15, "(ullrich@von-bassewitz.de)" },
- { (MAX_X / 2) - 9, 18, "C Implementation by" },
- { (MAX_X / 2) - 10, 19, "Ullrich von Bassewitz" },
- { (MAX_X / 2) - 11, 23, "Press any key to quit..." },
+ { 2, "Wolfgang Amadeus Mozart" },
+ { 4, "\"Eine kleine Nachtmusik\"" },
+ { 5, "(KV 525)" },
+ { 9, "Ported to the SID in 1987 by" },
+ { 11, "Joachim von Bassewitz" },
+ { 12, "(joachim@von-bassewitz.de)" },
+ { 13, "and" },
+ { 14, "Ullrich von Bassewitz" },
+ { 15, "(ullrich@von-bassewitz.de)" },
+ { 18, "C Implementation by" },
+ { 19, "Ullrich von Bassewitz" },
+ { 23, "Press any key to quit..." },
};
- TextDesc* T;
+ register const TextDesc* T;
unsigned char I;
+ unsigned char X;
/* Clear the screen hide the cursor, set colors */
#ifdef __CBM610__
/* Top line */
cputcxy (0, 0, CH_ULCORNER);
- chline (MAX_X - 2);
+ chline (XSize - 2);
cputc (CH_URCORNER);
/* Left line */
/* Bottom line */
cputc (CH_LLCORNER);
- chline (MAX_X - 2);
+ chline (XSize - 2);
cputc (CH_LRCORNER);
/* Right line */
- cvlinexy (MAX_X - 1, 1, 23);
+ cvlinexy (XSize - 1, 1, 23);
/* Several divider lines */
MakeTeeLine (7);
/* Write something into the frame */
for (I = 0, T = Text; I < sizeof (Text) / sizeof (Text [0]); ++I) {
- cputsxy (T->X, T->Y, T->Msg);
- ++T;
+ X = (XSize - strlen (T->Msg)) / 2;
+ cputsxy (X, T->Y, T->Msg);
+ ++T;
}
}
static unsigned char Clock;
do {
- Clock = clock ();
+ Clock = clock ();
} while (Clock != NextClock);
NextClock = Clock + TICKS_PER_TONE;
}
/* On the 510/610, the SID is in another bank (the system bank), so we cannot
- * just write to the memory space.
- */
+** just write to the memory space.
+*/
#if defined(__CBM510__) || defined(__CBM610__)
-# define outb(addr,val) pokebsys ((unsigned)(addr), val)
-# define outw(addr,val) pokewsys ((unsigned)(addr), val)
+# define outb(addr,val) pokebsys ((unsigned)(addr), val)
+# define outw(addr,val) pokewsys ((unsigned)(addr), val)
#else
-# define outb(addr,val) (*(addr)) = (val)
-# define outw(addr,val) (*(addr)) = (val)
+# define outb(addr,val) (*(addr)) = (val)
+# define outw(addr,val) (*(addr)) = (val)
#endif
unsigned char I;
unsigned char Tone;
unsigned char Octave;
- unsigned Val;
- struct __sid_voice* Voice;
- VoiceCtrl* VC;
+ unsigned Val;
+ struct __sid_voice* Voice;
+ register VoiceCtrl* VC;
/* Initialize the debugger */
DbgInit (0);
+ /* Get the screen dimensions */
+ screensize (&XSize, &YSize);
+
/* Make a nice screen */
MakeNiceScreen ();
/* Play each voice until all three are done */
while (Done != 0x07) {
- /* Display the time in the lower left corner */
- DisplayTime ();
-
- /* Wait for the next run */
- TimeSync ();
-
- /* Check for a key */
- if (kbhit ()) {
- if (cgetc () == 'd') {
- /* Start the debugger */
- BREAK ();
- } else {
- /* Stop playing music */
- break;
- }
- }
-
- /* Play all three voices */
- for (I = 0; I < 3; ++I) {
-
- /* Get a pointer to this voice */
- VC = V [I];
- Voice = VC->Voice;
-
- /* Is this voice done? */
- if (Done & VC->DoneMask) {
- /* Voice already done */
- continue;
- }
-
- /* Do we have any more ticks to play? */
- if (VC->Ticks == 0) {
- /* We need new data */
- if ((Val = *VC->Data) == 0) {
- /* End of data. Mark the voice as done */
- Done |= VC->DoneMask;
- continue;
- }
- ++VC->Data;
-
- /* Get the ticks from the data */
- VC->Ticks = (Val & 0x7F) - 1;
-
- /* Check if this is a tone or a pause */
- if (Val & 0x8000) {
- /* This is a pause. Remember it and shut off the SID */
- outb (&Voice->ctrl, VC->Trigger & 0xFE);
- } else {
- /* This is a tone. Extract the attributes. */
- Tone = (Val >> 8) & 0x0F;
- Octave = ((Val >> 12) & 0x07) ^ 0x07;
- /* Calculate the frequency */
- VC->Freq = FreqTab [Tone] >> Octave;
- /* Set the frequency */
- outw (&Voice->freq, VC->Freq);
- /* Start the tone */
- outb (&Voice->ctrl, VC->Trigger);
- }
- } else {
- /* Decrement the ticks. If this is the last tick of a tone,
- * reset bit 0 of the trigger value and write it back to the
- * SID to start the release phase.
- */
- if (--(VC->Ticks) == 0) {
- outb (&Voice->ctrl, VC->Trigger & 0xFE);
- }
- }
- }
+ /* Display the time in the lower left corner */
+ DisplayTime ();
+
+ /* Wait for the next run */
+ TimeSync ();
+
+ /* Check for a key */
+ if (kbhit ()) {
+ if (cgetc () == 'd') {
+ /* Start the debugger */
+ BREAK ();
+ } else {
+ /* Stop playing music */
+ break;
+ }
+ }
+
+ /* Play all three voices */
+ for (I = 0; I < 3; ++I) {
+
+ /* Get a pointer to this voice */
+ VC = V [I];
+ Voice = VC->Voice;
+
+ /* Is this voice done? */
+ if (Done & VC->DoneMask) {
+ /* Voice already done */
+ continue;
+ }
+
+ /* Do we have any more ticks to play? */
+ if (VC->Ticks == 0) {
+ /* We need new data */
+ if ((Val = *VC->Data) == 0) {
+ /* End of data. Mark the voice as done */
+ Done |= VC->DoneMask;
+ continue;
+ }
+ ++VC->Data;
+
+ /* Get the ticks from the data */
+ VC->Ticks = (Val & 0x7F) - 1;
+
+ /* Check if this is a tone or a pause */
+ if (Val & 0x8000) {
+ /* This is a pause. Remember it and shut off the SID */
+ outb (&Voice->ctrl, VC->Trigger & 0xFE);
+ } else {
+ /* This is a tone. Extract the attributes. */
+ Tone = (Val >> 8) & 0x0F;
+ Octave = ((Val >> 12) & 0x07) ^ 0x07;
+ /* Calculate the frequency */
+ VC->Freq = FreqTab [Tone] >> Octave;
+ /* Set the frequency */
+ outw (&Voice->freq, VC->Freq);
+ /* Start the tone */
+ outb (&Voice->ctrl, VC->Trigger);
+ }
+ } else {
+ /* Decrement the ticks. If this is the last tick of a tone,
+ ** reset bit 0 of the trigger value and write it back to the
+ ** SID to start the release phase.
+ */
+ if (--(VC->Ticks) == 0) {
+ outb (&Voice->ctrl, VC->Trigger & 0xFE);
+ }
+ }
+ }
}
/* Reset the SID */
/* If we have a character, remove it from the buffer */
if (kbhit ()) {
- cgetc ();
+ cgetc ();
}
/* Done */