Files
2026-10-07 15:53:30 +02:00

214 lines
21 KiB
C

/*
Mockingboard music demo for the Apple ][.
A Mockingboard C plugs into a slot (slot 4 here, so it appears at $C400)
and carries two AY-3-8913 PSGs, each hidden behind a 6522 VIA. The AY is
not connected to the Apple bus -- you have to bit-bang it through the VIA:
put the AY register number or value on port A, then pulse BC1/BDIR on port
B to latch an address or write data. $C400 is the first VIA/AY and $C480
the second.
Port B bit 0 = BC1, bit 1 = BDIR, bit 2 = /RESET (must stay high). BC1/BDIR
is 11 to latch an address and 01 to write data; both are bracketed by 00
(inactive), because the AY only reacts while it is idle.
The same 6522 also runs its Timer 1 continuously at 60 Hz, setting the T1
flag in the interrupt flag register on each rollover. The main loop polls
that flag to step the music, so the tempo is derived from the CPU clock
(~1.0227 MHz) instead of a delay loop. The VIA IRQ line does reach the
Apple bus, but Timer 1 interrupts are left disabled, so the ROM's IRQ
handler (which would reset the machine) is never entered.
*/
#include <conio.h>
#define MB1 0xC400 /* slot 4, first VIA/AY */
#define MB2 0xC480 /* slot 4, second VIA/AY */
#define AY_OFF 0x04 /* inactive, /RESET high */
#define AY_WRITE 0x06
#define AY_LATCH 0x07
/* 6522 VIA registers, as offsets from a base address */
#define VIA_T1CL 0x04 /* timer 1 counter/latch, low */
#define VIA_T1CH 0x05 /* timer 1 counter/latch, high (starts timer) */
#define VIA_ACR 0x0b /* auxiliary control register */
#define VIA_IFR 0x0d /* interrupt flag register */
/* The VIA is clocked by the ~1.0227 MHz CPU clock: 1022727 / 60 = 17045 */
#define TIMER_60HZ 17045
/* pulse the VIA ports to move one byte to/from the AY */
void ay_set(unsigned base, unsigned char reg, unsigned char val)
{
volatile unsigned char *orb = (volatile unsigned char *)base;
volatile unsigned char *ora = orb + 1;
*orb = AY_OFF;
*ora = reg;
*orb = AY_LATCH; /* latch register number */
*orb = AY_OFF;
*ora = val;
*orb = AY_WRITE; /* write data */
*orb = AY_OFF;
}
void ay_init(unsigned base)
{
unsigned char r;
for (r = 0; r < 14; r++)
ay_set(base, r, 0);
ay_set(base, 7, 0x3f); /* start with every generator off */
}
/* start 6522 Timer 1 free-running at 60 Hz */
void timer_init(unsigned base)
{
volatile unsigned char *via = (volatile unsigned char *)base;
via[VIA_ACR] = 0x40; /* T1 continuous, PB7 stays an I/O */
via[VIA_T1CL] = TIMER_60HZ & 0xff;
via[VIA_T1CH] = TIMER_60HZ >> 8; /* load latch and start counting */
}
/* returns 1 once per 60 Hz rollover, clearing the T1 flag */
unsigned char timer_tick(unsigned base)
{
volatile unsigned char *via = (volatile unsigned char *)base;
if (via[VIA_IFR] & 0x40) { /* timer 1 rolled over */
via[VIA_IFR] = 0x40; /* clear the T1 flag */
return 1;
}
return 0;
}
void ay_set_tone(unsigned base, unsigned char ch, unsigned int period)
{
ay_set(base, ch * 2, period & 0xff);
ay_set(base, ch * 2 + 1, period >> 8);
}
void ay_set_vol(unsigned base, unsigned char ch, unsigned char vol)
{
ay_set(base, 8 + ch, vol & 0x0f);
}
typedef unsigned char byte;
typedef unsigned short word;
//
// MUSIC ROUTINES
//
// Namespace(length=64, upper=49, freq=63920.0, bias=0, maxbits=12)
// 437.3 4.28561873524777 49
const int note_table[64] = {
2478,2339,2207,2084,1967,1856,1752,1654,1561,1473,1391,1313,1239,1169,1104,1042,983,928,876,827,780,737,695,656,619,585,552,521,492,464,438,413,390,368,348,328,310,292,276,260,246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,103,98,92,87,82,77,73,69,65,};
struct {
byte volume;
} voice[3];
byte music_index = 0;
byte cur_duration = 0;
const byte music1[] = {
0x35,0x8a,0x37,0x8a,0x33,0x3f,0x8a,0x30,0x3c,0x94,0x3e,0x32,0x8a,0x3a,0x2e,0x94,0x35,0x29,0x8a,0x37,0x2b,0x8a,0x33,0x27,0x8a,0x30,0x24,0x94,0x32,0x26,0x8a,0x2e,0x22,0x94,0x29,0x1d,0x8a,0x2b,0x1f,0x8a,0x27,0x1b,0x8a,0x24,0x18,0x94,0x1a,0x26,0x8a,0x18,0x24,0x8a,0x17,0x23,0x8a,0x16,0x22,0xa8,0x3a,0x35,0x32,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x1f,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x39,0x36,0x8a,0x3a,0x37,0x16,0x8a,0x3f,0x37,0x33,0x8a,0x35,0x38,0x22,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x26,0x94,0x3f,0x33,0x37,0x94,0x1f,0x22,0x27,0x94,0x27,0x22,0x1f,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x1f,0x22,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x24,0x27,0x94,0x1f,0x13,0x94,0x3c,0x33,0x30,0x8a,0x3a,0x33,0x2e,0x8a,0x39,0x33,0x2d,0x8a,0x3c,0x30,0x8a,0x3f,0x33,0x1d,0x8a,0x37,0x8a,0x1d,0x8a,0x35,0x8a,0x3f,0x33,0x27,0x8a,0x3c,0x30,0x8a,0x35,0x38,0x26,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x22,0x1f,0x8a,0x2b,0x8a,0x33,0x16,0x22,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x13,0x1f,0x8a,0x3f,0x33,0x37,0x8a,0x38,0x35,0x27,0x8a,0x39,0x36,0x8a,0x37,0x3a,0x16,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x20,0x94,0x3f,0x37,0x33,0x94,0x27,0x22,0x1f,0x94,0x2b,0x27,0x22,0x94,0x3f,0x33,0x8a,0x35,0x8a,0x37,0x27,0x1b,0x8a,0x3f,0x33,0x8a,0x35,0x2b,0x22,0x8a,0x37,0x8a,0x25,0x19,0x8a,0x3f,0x33,0x8a,0x35,0x2b,0x27,0x8a,0x3f,0x33,0x8a,0x37,0x24,0x18,0x8a,0x3f,0x33,0x8a,0x35,0x2c,0x27,0x8a,0x37,0x8a,0x23,0x17,0x8a,0x3f,0x33,0x8a,0x35,0x2c,0x27,0x8a,0x3f,0x33,0x8a,0x3a,0x37,0x22,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x2b,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x32,0x35,0x8a,0x35,0x38,0x26,0x94,0x3f,0x33,0x37,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x22,0x1f,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x25,0x22,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x35,0x38,0x27,0x8a,0x39,0x36,0x8a,0x3a,0x37,0x16,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x35,0x38,0x20,0x94,0x37,0x33,0x3f,0x94,0x27,0x22,0x1f,0x94,0x27,0x22,0x1f,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x1f,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x94,0x3c,0x33,0x30,0x8a,0x3a,0x33,0x2e,0x8a,0x2d,0x33,0x39,0x8a,0x3c,0x30,0x8a,0x3f,0x33,0x27,0x8a,0x37,0x8a,0x1d,0x8a,0x35,0x8a,0x33,0x3f,0x27,0x8a,0x3c,0x30,0x8a,0x38,0x35,0x26,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x27,0x1f,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x24,0x27,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x36,0x39,0x8a,0x3a,0x37,0x16,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x37,0x3a,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x22,0x94,0x33,0x37,0x3f,0x94,0x27,0x22,0x1f,0x94,0x22,0x27,0x2b,0x94,0x3f,0x33,0x8a,0x35,0x8a,0x37,0x27,0x1b,0x8a,0x3f,0x33,0x8a,0x35,0x2b,0x27,0x8a,0x37,0x8a,0x25,0x19,0x8a,0x3f,0x33,0x8a,0x35,0x2b,0x22,0x8a,0x3f,0x33,0x8a,0x37,0x24,0x18,0x8a,0x33,0x3f,0x8a,0x35,0x2c,0x27,0x8a,0x37,0x8a,0x23,0x17,0x8a,0x3f,0x33,0x8a,0x35,0x2c,0x27,0x8a,0x3f,0x33,0x8a,0x3a,0x37,0x22,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x2b,0x8a,0x37,0x3a,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x22,0x94,0x33,0x37,0x3f,0x94,0x22,0x16,0x94,0x1b,0x0f,0x8a,0x37,0x2b,0x33,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x3a,0x2e,0x37,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x2c,0x38,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x16,0x8a,0x37,0x8a,0x33,0x27,0x2b,0x8a,0x2e,0x8a,0x30,0x14,0x8a,0x32,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x37,0x20,0x8a,0x35,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x2e,0x1f,0x8a,0x37,0x8a,0x38,0x2b,0x27,0x8a,0x3a,0x8a,0x3c,0x16,0x8a,0x3a,0x8a,0x37,0x22,0x2b,0x8a,0x38,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x30,0x37,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x1f,0x8a,0x3a,0x8a,0x3c,0x1e,0x8a,0x3d,0x8a,0x3e,0x3a,0x35,0x8a,0x3e,0x35,0x3a,0x8a,0x22,0x29,0x26,0x8a,0x3e,0x33,0x39,0x8a,0x1d,0x8a,0x3c,0x8a,0x39,0x33,0x29,0x8a,0x35,0x8a,0x3a,0x32,0x29,0x94,0x20,0x14,0x94,0x1f,0x13,0x8a,0x37,0x2b,0x33,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x2e,0x3a,0x37,0x94,0x3c,0x37,0x30,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x33,0x2b,0x37,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x30,0x37,0x3c,0x8a,0x3a,0x2e,0x37,0x8a,0x16,0x8a,0x37,0x8a,0x33,0x2b,0x27,0x8a,0x2e,0x8a,0x30,0x14,0x8a,0x32,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x37,0x20,0x8a,0x35,0x8a,0x33,0x23,0x2c,0x8a,0x35,0x8a,0x33,0x1f,0x94,0x2b,0x22,0x27,0x94,0x1b,0x8a,0x2e,0x8a,0x2d,0x2b,0x27,0x8a,0x2e,0x8a,0x33,0x2c,0x27,0x94,0x30,0x2c,0x27,0x8a,0x33,0x8a,0x21,0x24,0x2a,0x8a,0x30,0x8a,0x33,0x2a,0x27,0x8a,0x30,0x8a,0x2e,0x2b,0x27,0x8a,0x33,0x8a,0x37,0x2b,0x22,0x8a,0x3a,0x8a,0x2b,0x27,0x22,0x8a,0x37,0x8a,0x33,0x2b,0x27,0x8a,0x2e,0x8a,0x30,0x2d,0x1d,0x94,0x33,0x2d,0x24,0x94,0x37,0x2c,0x26,0x8a,0x35,0x2c,0x8a,0x26,0x22,0x8a,0x33,0x2b,0x8a,0x27,0x1b,0x94,0x22,0x16,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x8a,0x38,0x1d,0x11,0x8a,0x39,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x30,0x37,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x16,0x8a,0x37,0x8a,0x33,0x2b,0x27,0x8a,0x2e,0x8a,0x30,0x14,0x8a,0x32,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x37,0x20,0x8a,0x35,0x8a,0x33,0x23,0x27,0x8a,0x35,0x8a,0x2e,0x1f,0x8a,0x37,0x8a,0x38,0x27,0x2b,0x8a,0x3a,0x8a,0x3c,0x16,0x8a,0x3a,0x8a,0x37,0x2b,0x27,0x8a,0x38,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x30,0x37,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x1f,0x8a,0x3a,0x8a,0x3c,0x1e,0x8a,0x3d,0x8a,0x3e,0x3a,0x35,0x8a,0x3e,0x35,0x3a,0x8a,0x29,0x26,0x22,0x8a,0x3e,0x33,0x39,0x8a,0x1d,0x8a,0x3c,0x8a,0x39,0x33,0x27,0x8a,0x35,0x8a,0x3a,0x32,0x29,0x94,0x20,0x14,0x94,0x1f,0x13,0x8a,0x37,0x2b,0x33,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x2e,0x3a,0x37,0x94,0x3c,0x37,0x30,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x33,0x2b,0x37,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x30,0x3c,0x37,0x8a,0x37,0x2e,0x3a,0x8a,0x16,0x8a,0x37,0x8a,0x33,0x2b,0x27,0x8a,0x2e,0x8a,0x30,0x14,0x8a,0x32,0x8a,0x33,0x27,0x24,0x8a,0x35,0x8a,0x37,0x20,0x8a,0x35,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x33,0x1f,0x94,0x2b,0x27,0x22,0x94,0x1b,0x8a,0x2e,0x8a,0x2d,0x2b,0x27,0x8a,0x2e,0x8a,0x33,0x2c,0x27,0x94,0x30,0x2c,0x20,0x8a,0x33,0x8a,0x2a,0x27,0x24,0x8a,0x30,0x8a,0x33,0x2a,0x27,0x8a,0x30,0x8a,0x2e,0x2b,0x22,0x8a,0x33,0x8a,0x37,0x2b,0x27,0x8a,0x3a,0x8a,0x2b,0x27,0x22,0x8a,0x37,0x8a,0x33,0x2b,0x22,0x8a,0x2e,0x8a,0x30,0x2d,0x27,0x94,0x33,0x2d,0x24,0x94,0x37,0x2c,0x26,0x8a,0x35,0x2c,0x8a,0x26,0x22,0x8a,0x33,0x2b,0x8a,0x27,0x1b,0x94,0x22,0x16,0x94,0x1b,0x0f,0x94,0x29,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x1f,0x22,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x39,0x36,0x8a,0x3a,0x37,0x16,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x22,0x94,0x3f,0x37,0x33,0x94,0x27,0x22,0x1f,0x94,0x22,0x1f,0x27,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x22,0x1f,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x22,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x94,0x33,0x3c,0x30,0x8a,0x3a,0x33,0x2e,0x8a,0x39,0x33,0x2d,0x8a,0x3c,0x30,0x8a,0x3f,0x33,0x27,0x8a,0x37,0x8a,0x1d,0x8a,0x35,0x8a,0x3f,0x33,0x27,0x8a,0x3c,0x30,0x8a,0x35,0x38,0x26,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x1f,0x22,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x24,0x27,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x27,0x8a,0x39,0x36,0x8a,0x37,0x3a,0x16,0x8a,0x3f,0x33,0x37,0x8a,0x35,0x38,0x27,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x38,0x35,0x26,0x94,0x3f,0x37,0x33,0x94,0x27,0x22,0x1f,0x94,0x22,0x2b,0x27,0x94,0x3f,0x33,0x8a,0x35,0x8a,0x37,0x27,0x1b,0x8a,0x3f,0x33,0x8a,0x35,0x2b,0x27,0x8a,0x37,0x8a,0x25,0x19,0x8a,0x33,0x3f,0x8a,0x35,0x27,0x22,0x8a,0x3f,0x33,0x8a,0x37,0x24,0x18,0x8a,0x3f,0x33,0x8a,0x35,0x2c,0x27,0x8a,0x37,0x8a,0x23,0x17,0x8a,0x3f,0x33,0x8a,0x35,0x23,0x27,0x8a,0x3f,0x33,0x8a,0x3a,0x37,0x16,0x8a,0x33,0x37,0x3f,0x8a,0x38,0x35,0x2b,0x8a,0x3a,0x37,0x8a,0x16,0x8a,0x32,0x35,0x3e,0x8a,0x38,0x35,0x26,0x94,0x3f,0x37,0x33,0x94,0x22,0x16,0x94,0x3f,0x37,0x33,0xa8,0x38,0x3c,0x14,0x8a,0x3b,0x8a,0x3c,0x38,0x24,0x94,0x1b,0x94,0x3f,0x3c,0x38,0x94,0x38,0x3d,0x19,0x94,0x31,0x2c,0x29,0x8a,0x30,0x8a,0x31,0x20,0x8a,0x33,0x8a,0x35,0x2c,0x25,0x94,0x38,0x35,0x11,0x8a,0x37,0x8a,0x38,0x35,0x2c,0x94,0x18,0x94,0x3c,0x38,0x35,0x94,0x35,0x3a,0x3d,0x94,0x2e,0x25,0x29,0x8a,0x2d,0x8a,0x2e,0x1d,0x8a,0x30,0x8a,0x31,0x29,0x25,0x8a,0x3a,0x8a,0x35,0x25,0x19,0x94,0x3a,0x25,0x29,0x8a,0x35,0x8a,0x22,0x16,0x8a,0x3a,0x8a,0x35,0x23,0x17,0x94,0x33,0x24,0x18,0x94,0x24,0x27,0x2c,0x94,0x38,0x1d,0x94,0x2c,0x29,0x24,0x94,0x37,0x1f,0x8a,0x3b,0x8a,0x3e,0x26,0x29,0x8a,0x8a,0x23,0x8a,0x8a,0x3e,0x2b,0x29,0x8a,0x3f,0x8a,0x3c,0x2b,0x27,0xa8,0x3d,0x22,0x27,0x94,0x1b,0x94,0x3c,0x38,0x14,0x8a,0x3b,0x8a,0x38,0x3c,0x2c,0x94,0x1b,0x94,0x3f,0x3c,0x38,0x94,0x3d,0x38,0x19,0x94,0x31,0x2c,0x25,0x8a,0x30,0x8a,0x31,0x20,0x8a,0x33,0x8a,0x35,0x2c,0x29,0x94,0x38,0x35,0x11,0x8a,0x37,0x8a,0x38,0x35,0x2c,0x94,0x18,0x94,0x35,0x3c,0x38,0x94,0x3d,0x3a,0x35,0x94,0x2e,0x29,0x25,0x8a,0x2d,0x8a,0x2e,0x1d,0x8a,0x30,0x8a,0x31,0x29,0x25,0x8a,0x3a,0x8a,0x35,0x25,0x19,0x94,0x3a,0x29,0x25,0x8a,0x35,0x8a,0x16,0x22,0x8a,0x3a,0x8a,0x35,0x23,0x17,0x94,0x33,0x24,0x18,0x8a,0x20,0x14,0x8a,0x1f,0x13,0x8a,0x11,0x1d,0x8a,0x38,0x32,0x2f,0x9e,0x38,0x8a,0x3c,0x33,0x30,0x8a,0x3f,0x33,0x8a,0x2c,0x27,0x24,0x8a,0x3a,0x31,0x8a,0x27,0x1b,0x8a,0x33,0x8a,0x35,0x31,0x1b,0x8a,0x37,0x8a,0x38,0x30,0x20,0x94,0x32,0x8a,0x33,0x8a,0x35,0x8a,0x37,0x8a,0x38,0x8a,0x3a,0x8a,0x3c,0x38,0x14,0x8a,0x3b,0x8a,0x38,0x3c,0x2c,0x94,0x1b,0x94,0x3f,0x3c,0x38,0x94,0x3d,0x38,0x19,0x94,0x31,0x2c,0x29,0x8a,0x30,0x8a,0x31,0x20,0x8a,0x33,0x8a,0x35,0x29,0x2c,0x94,0x38,0x35,0x11,0x8a,0x37,0x8a,0x38,0x35,0x2c,0x94,0x18,0x94,0x3c,0x35,0x38,0x94,0x35,0x3d,0x3a,0x94,0x2e,0x29,0x25,0x8a,0x2d,0x8a,0x2e,0x1d,0x8a,0x30,0x8a,0x31,0x29,0x25,0x8a,0x3a,0x8a,0x35,0x25,0x19,0x94,0x3a,0x29,0x25,0x8a,0x35,0x8a,0x22,0x16,0x8a,0x3a,0x8a,0x35,0x23,0x17,0x94,0x33,0x24,0x18,0x94,0x2c,0x27,0x24,0x94,0x38,0x1d,0x94,0x2c,0x29,0x24,0x94,0x37,0x1f,0x8a,0x3b,0x8a,0x3e,0x26,0x2b,0x8a,0x8a,0x23,0x8a,0x8a,0x3e,0x2b,0x29,0x8a,0x3f,0x8a,0x3c,0x2b,0x27,0xa8,0x3d,0x2b,0x27,0x94,0x1b,0x94,0x3c,0x38,0x14,0x8a,0x3b,0x8a,0x38,0x3c,0x24,0x94,0x1b,0x94,0x3f,0x3c,0x38,0x94,0x3d,0x38,0x19,0x94,0x31,0x2c,0x29,0x8a,0x30,0x8a,0x31,0x20,0x8a,0x33,0x8a,0x35,0x2c,0x29,0x94,0x35,0x38,0x11,0x8a,0x37,0x8a,0x38,0x35,0x2c,0x94,0x18,0x94,0x3c,0x38,0x35,0x94,0x3d,0x3a,0x35,0x94,0x2e,0x25,0x29,0x8a,0x2d,0x8a,0x2e,0x1d,0x8a,0x30,0x8a,0x31,0x29,0x25,0x8a,0x3a,0x8a,0x35,0x25,0x19,0x94,0x3a,0x29,0x25,0x8a,0x35,0x8a,0x22,0x16,0x8a,0x3a,0x8a,0x35,0x23,0x17,0x94,0x33,0x24,0x18,0x8a,0x20,0x14,0x8a,0x1f,0x13,0x8a,0x1d,0x11,0x8a,0x38,0x32,0x2f,0x9e,0x38,0x8a,0x30,0x33,0x3c,0x8a,0x3f,0x33,0x8a,0x2c,0x27,0x24,0x8a,0x3a,0x31,0x8a,0x27,0x1b,0x8a,0x33,0x8a,0x35,0x31,0x1b,0x8a,0x37,0x8a,0x30,0x38,0x20,0xa8,0x3f,0x3c,0x38,0xa8,0x33,0x20,0x27,0x94,0x30,0x2c,0x27,0x8a,0x33,0x8a,0x2a,0x27,0x24,0x8a,0x30,0x8a,0x33,0x2a,0x21,0x8a,0x30,0x8a,0x2e,0x2b,0x27,0x8a,0x33,0x8a,0x37,0x22,0x27,0x8a,0x3a,0x8a,0x2b,0x27,0x22,0x8a,0x37,0x8a,0x33,0x2b,0x27,0x8a,0x2e,0x8a,0x30,0x2d,0x27,0x94,0x33,0x2d,0x24,0x94,0x37,0x2c,0x26,0x8a,0x35,0x2c,0x8a,0x26,0x22,0x8a,0x33,0x2b,0x8a,0x27,0x1b,0xa8,0x33,0x37,0x3a,0xa8,0x2c,0x29,0x14,0x94,0x2b,0x28,0x20,0x8a,0x2c,0x29,0x8a,0x18,0x8a,0x2b,0x28,0x8a,0x29,0x2c,0x24,0x94,0x14,0x8a,0x30,0x8a,0x2c,0x35,0x24,0x8a,0x30,0x8a,0x33,0x18,0x8a,0x35,0x8a,0x33,0x24,0x20,0x8a,0x30,0x8a,0x2e,0x2b,0x1b,0x94,0x2d,0x2a,0x27,0x8a,0x2e,0x2b,0x8a,0x16,0x8a,0x2d,0x2a,0x8a,0x2e,0x2b,0x1f,0x94,0x1b,0x8a,0x33,0x8a,0x37,0x2e,0x27,0x8a,0x33,0x8a,0x35,0x16,0x8a,0x37,0x8a,0x35,0x1f,0x22,0x8a,0x33,0x8a,0x35,0x32,0x16,0x94,0x34,0x31,0x26,0x8a,0x35,0x32,0x8a,0x1a,0x8a,0x34,0x31,0x8a,0x32,0x35,0x26,0x94,0x16,0x8a,0x38,0x8a,0x3c,0x32,0x22,0x8a,0x38,0x8a,0x3a,0x1d,0x8a,0x3c,0x8a,0x3a,0x26,0x22,0x8a,0x38,0x8a,0x3f,0x33,0x27,0x8a,0x3f,0x33,0x8a,0x3f,0x33,0x27,0xa8,0x3c,0x33,0x27,0x94,0x3a,0x33,0x1f,0x94,0x2e,0x2b,0x8a,0x2e,0x2b,0x8a,0x2e,0x2b,0x94,0x2b,0x2e,0x94,0x2c,0x29,0x14,0x94,0x2b,0x28,0x24,0x8a,0x2c,0x29,0x8a,0x18,0x8a,0x2b,0x28,0x8a,0x2c,0x29,0x24,0x94,0x14,0x8a,0x30,0x8a,0x35,0x2c,0x20,0x8a,0x30,0x8a,0x33,0x18,0x8a,0x35,0x8a,0x33,0x24,0x20,0x8a,0x30,0x8a,0x2e,0x2b,0x1b,0x94,0x2a,0x2d,0x27,0x8a,0x2e,0x2b,0x8a,0x16,0x8a,0x2d,0x2a,0x8a,0x2e,0x2b,0x1f,0x94,0x1b,0x8a,0x33,0x8a,0x37,0x2e,0x27,0x8a,0x33,0x8a,0x35,0x16,0x8a,0x37,0x8a,0x35,0x27,0x22,0x8a,0x33,0x8a,0x30,0x20,0x14,0x8a,0x2f,0x8a,0x30,0x1d,0x11,0x8a,0x3a,0x30,0x8a,0x1f,0x13,0x8a,0x38,0x30,0x8a,0x20,0x14,0x8a,0x33,0x30,0x8a,0x37,0x2e,0x22,0x8a,0x36,0x8a,0x37,0x22,0x2b,0x8a,0x3c,0x8a,0x2a,0x27,0x21,0x8a,0x3f,0x8a,0x3a,0x2b,0x27,0x8a,0x37,0x8a,0x33,0x2d,0x18,0x94,0x33,0x2d,0x1d,0x94,0x37,0x2c,0x32,0x8a,0x35,0x32,0x2c,0x8a,0x26,0x1a,0x8a,0x33,0x2e,0x2b,0x8a,0x27,0x1b,0x94,0x2b,0x2e,0x8a,0x2e,0x2b,0x8a,0x2e,0x2b,0x94,0x2e,0x2b,0x94,0x2c,0x29,0x14,0x94,0x2b,0x28,0x20,0x8a,0x29,0x2c,0x8a,0x18,0x8a,0x2b,0x28,0x8a,0x2c,0x29,0x24,0x94,0x14,0x8a,0x30,0x8a,0x35,0x2c,0x24,0x8a,0x30,0x8a,0x33,0x18,0x8a,0x35,0x8a,0x33,0x24,0x20,0x8a,0x30,0x8a,0x2e,0x2b,0x1b,0x94,0x2d,0x2a,0x27,0x8a,0x2e,0x2b,0x8a,0x16,0x8a,0x2d,0x2a,0x8a,0x2e,0x2b,0x1f,0x94,0x1b,0x8a,0x33,0x8a,0x37,0x2e,0x27,0x8a,0x33,0x8a,0x35,0x16,0x8a,0x37,0x8a,0x35,0x27,0x22,0x8a,0x33,0x8a,0x35,0x32,0x16,0x94,0x31,0x34,0x26,0x8a,0x35,0x32,0x8a,0x1a,0x8a,0x34,0x31,0x8a,0x35,0x32,0x26,0x94,0x16,0x8a,0x38,0x8a,0x3c,0x32,0x20,0x8a,0x38,0x8a,0x3a,0x1d,0x8a,0x3c,0x8a,0x3a,0x26,0x22,0x8a,0x38,0x8a,0x33,0x3f,0x27,0x8a,0x3f,0x33,0x8a,0x3f,0x33,0x1e,0xa8,0x3c,0x33,0x27,0x94,0x3a,0x33,0x27,0x94,0x2b,0x2e,0x8a,0x2e,0x2b,0x8a,0x2e,0x2b,0x94,0x2e,0x2b,0x94,0x2c,0x29,0x14,0x94,0x2b,0x28,0x20,0x8a,0x2c,0x29,0x8a,0x18,0x8a,0x2b,0x28,0x8a,0x2c,0x29,0x24,0x94,0x14,0x8a,0x30,0x8a,0x35,0x2c,0x24,0x8a,0x30,0x8a,0x33,0x18,0x8a,0x35,0x8a,0x33,0x24,0x20,0x8a,0x30,0x8a,0x2e,0x2b,0x1b,0x94,0x2d,0x2a,0x27,0x8a,0x2e,0x2b,0x8a,0x16,0x8a,0x2a,0x2d,0x8a,0x2e,0x2b,0x27,0x94,0x1b,0x8a,0x33,0x8a,0x37,0x2e,0x27,0x8a,0x33,0x8a,0x35,0x16,0x8a,0x37,0x8a,0x35,0x22,0x1f,0x8a,0x33,0x8a,0x30,0x20,0x14,0x8a,0x2f,0x8a,0x30,0x1d,0x11,0x8a,0x3a,0x30,0x8a,0x1f,0x13,0x8a,0x38,0x30,0x8a,0x20,0x14,0x8a,0x33,0x30,0x8a,0x37,0x2e,0x22,0x8a,0x36,0x8a,0x37,0x2b,0x27,0x8a,0x3c,0x8a,0x21,0x27,0x2a,0x8a,0x3f,0x8a,0x3a,0x2b,0x27,0x8a,0x37,0x8a,0x33,0x2d,0x24,0x94,0x33,0x2d,0x1d,0x94,0x37,0x32,0x2c,0x8a,0x35,0x2c,0x32,0x8a,0x26,0x1a,0x8a,0x33,0x2e,0x2b,0x8a,0x27,0x1b,0x94,0x22,0x16,0x94,0x3f,0x3a,0x37,0xff
};
static const byte* music_ptr = 0;
static const byte* music_rts = 0;
static byte music_runlen = 0;
// decode next music byte, handling compression
byte next_music_byte(void) {
byte ch = *music_ptr++;
if (music_runlen) {
// we are in a backreference, count down
if (--music_runlen == 0) {
music_ptr = music_rts;
music_rts = 0;
}
} else if (ch == 0xfe) {
// back-reference: 0xfe <offset> <length>
byte offset = *music_ptr++;
music_runlen = *music_ptr++;
music_rts = music_ptr;
music_ptr -= offset + 3;
return next_music_byte();
}
return ch;
}
void play_music() {
byte ch;
byte enable = 0;
byte freech = 0;
byte chmask = 1;
for (ch=0; ch<3; ch++) {
if (voice[ch].volume) {
ay_set_vol(MB1, ch, voice[ch].volume--);
enable |= chmask;
} else {
freech = ch;
}
chmask <<= 1;
}
//ay_set(MB1, 7, ~enable);
if (music_ptr) {
ch = freech;
while (cur_duration == 0) {
byte note = next_music_byte();
if ((note & 0x80) == 0) {
int period = note_table[note & 63];
ay_set_tone(MB1, ch, period);
voice[ch].volume = 15;
ch = ch ? ch-1 : 2;
} else {
if (note == 0xff)
music_ptr = NULL;
cur_duration = note & 63;
}
}
cur_duration--;
}
}
void start_music(const byte* music) {
music_ptr = music;
music_rts = 0;
music_runlen = 0;
cur_duration = 0;
}
#ifdef __MAIN__
void main(void)
{
clrscr();
gotoxy(8, 4);
cputs("MOCKINGBOARD DEMO");
gotoxy(8, 8);
cputs("AY-3-8913 x2 IN SLOT 4");
gotoxy(8, 12);
cputs("ESC TO STOP");
ay_init(MB1);
ay_init(MB2);
ay_set(MB1, 7, 0x38); /* tone A/B/C on, noise off */
//ay_set(MB2, 7, 0x37); /* noise A only */
timer_init(MB1); /* 60 Hz clock to drive the music */
for (;;) {
if (!music_ptr) start_music(music1);
play_music();
while (!timer_tick(MB1))
; /* wait for the next 60 Hz tick */
if (kbhit() && cgetc() == 27)
break;
}
ay_set(MB1, 7, 0);
}
#endif