8bitworkshop/presets/nes/aputest.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();
}
}
}