mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-23 06:32:11 +00:00
126 lines
2.8 KiB
C
126 lines
2.8 KiB
C
|
|
/*
|
|
Generates random sounds in the APU, printing the parameters
|
|
to the screen. Also shows an asterisk while each channel is
|
|
playing, i.e. while its length counter is active.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "neslib.h"
|
|
|
|
#include "apu.h"
|
|
//#link "apu.c"
|
|
|
|
#include "vrambuf.h"
|
|
//#link "vrambuf.c"
|
|
|
|
// link the pattern table into CHR ROM
|
|
//#link "chr_generic.s"
|
|
|
|
typedef struct APUParam {
|
|
byte chmask;
|
|
const char* name;
|
|
word valmask;
|
|
} APUParam;
|
|
|
|
#define APU_DEFCOUNT 20
|
|
|
|
const APUParam APU_DEFS[APU_DEFCOUNT] = {
|
|
{0x01, "Pulse1 Period", 0x7ff },
|
|
{0x01, "Pulse1 Duty", 0xc0 },
|
|
{0x01, "Pulse1 Decay", 0x0f },
|
|
{0x01, "Pulse1 Length", 0x0f },
|
|
{0x01, "Pulse1 Sweep Period", 0x07 },
|
|
{0x01, "Pulse1 Sweep Rate", 0x07 },
|
|
{0x01, "Pulse1 Sweep Up?", 0x01 },
|
|
{0x02, "Pulse2 Period", 0x7ff },
|
|
{0x02, "Pulse2 Duty", 0xc0 },
|
|
{0x02, "Pulse2 Decay", 0x0f },
|
|
{0x02, "Pulse2 Length", 0x0f },
|
|
{0x02, "Pulse2 Sweep Period", 0x07 },
|
|
{0x02, "Pulse2 Sweep Rate", 0x07 },
|
|
{0x02, "Pulse2 Sweep Up?", 0x01 },
|
|
{0x04, "Triangle Period", 0x7ff },
|
|
{0x04, "Triangle Length", 0x0f },
|
|
{0x08, "Noise Period", 0x0f },
|
|
{0x08, "Noise Decay", 0x0f },
|
|
{0x08, "Noise Length", 0x0f },
|
|
{0x08, "Noise Buzz", NOISE_PERIOD_BUZZ },
|
|
};
|
|
|
|
word enmask;
|
|
word vals[APU_DEFCOUNT];
|
|
|
|
void random_sound() {
|
|
byte i;
|
|
|
|
do {
|
|
enmask = rand() & 15; // all except DMC
|
|
} while (enmask == 0);
|
|
|
|
for (i=0; i<APU_DEFCOUNT; i++) {
|
|
vals[i] = rand() & APU_DEFS[i].valmask;
|
|
}
|
|
}
|
|
|
|
void print_sound() {
|
|
byte i;
|
|
char buf[32];
|
|
for (i=0; i<APU_DEFCOUNT; i++) {
|
|
memset(buf, 0, sizeof(buf));
|
|
if (enmask & APU_DEFS[i].chmask) {
|
|
sprintf(buf, "%2d %19s %5d", i, APU_DEFS[i].name, vals[i]);
|
|
}
|
|
vram_adr(NTADR_A(1,i+1));
|
|
vram_write(buf, 32);
|
|
}
|
|
}
|
|
|
|
void play_sound() {
|
|
APU_ENABLE(enmask);
|
|
APU_PULSE_DECAY(0, vals[0], vals[1], vals[2], vals[3]);
|
|
APU_PULSE_SWEEP(0, vals[4], vals[5], vals[6]);
|
|
APU_PULSE_DECAY(1, vals[7], vals[8], vals[9], vals[10]);
|
|
APU_PULSE_SWEEP(1, vals[11], vals[12], vals[13]);
|
|
APU_TRIANGLE_LENGTH(vals[14], vals[15]);
|
|
APU_NOISE_DECAY(vals[16]|vals[19], vals[17], vals[18]);
|
|
}
|
|
|
|
void print_status() {
|
|
byte i;
|
|
vrambuf_clear();
|
|
for (i=0; i<APU_DEFCOUNT; i++) {
|
|
char ch = APU.status & APU_DEFS[i].chmask ? '*' : ' ';
|
|
vrambuf_put(NTADR_A(29,i+1), &ch, 1);
|
|
}
|
|
}
|
|
|
|
|
|
void main(void)
|
|
{
|
|
pal_col(1,0x04);
|
|
pal_col(2,0x20);
|
|
pal_col(3,0x30);
|
|
vram_adr(NTADR_A(0,26));
|
|
vram_write(" Space=New Sound, Enter=Replay ", 32);
|
|
apu_init();
|
|
while(1) {
|
|
ppu_off();
|
|
if (!(pad_state(0) & PAD_START)) {
|
|
random_sound();
|
|
}
|
|
print_sound();
|
|
play_sound();
|
|
vrambuf_clear();
|
|
set_vram_update(updbuf);
|
|
ppu_on_all();
|
|
// wait for key
|
|
while (!pad_trigger(0)) {
|
|
ppu_wait_nmi();
|
|
print_status();
|
|
}
|
|
}
|
|
}
|