Skip to content

Instantly share code, notes, and snippets.

@rniwase
Last active May 4, 2022 20:55
Show Gist options
  • Save rniwase/299481f89302e898d98cac485520ed3d to your computer and use it in GitHub Desktop.
Save rniwase/299481f89302e898d98cac485520ed3d to your computer and use it in GitHub Desktop.
サイレンマシーンforGB proto
/* use gbdk-2020 4.0.6 */
/* <path-to-gbdk-env>/bin/lcc -Wa-l -Wl-m -Wl-j -o sirenmachine.gb sirenmachine.c */
#include <gb/gb.h>
#include <stdio.h>
#include <gbdk/console.h>
UBYTE previous_keys;
BYTE keys;
#define UPDATE_KEYS() previous_keys = keys; keys = joypad()
#define KEY_ISPRESS(K) (keys & (K))
#define KEY_PUSHED(K) ((keys & (K)) && !(previous_keys & (K)))
#define KEY_RELEASED(K) (!(keys & (K)) && (previous_keys & (K)))
#define KEY_ANY_EVENT(K) (keys & (K)) ^ (previous_keys & (K))
UWORD lfo_count_max;
UWORD lfo_count_up;
UBYTE lfo_dir;
UBYTE lfo_waveform;
UBYTE osc_pw;
UBYTE osc_freq;
UBYTE lfo_rate;
const UBYTE lfo_period = 6U;
const UWORD freq_base [3] = {1407U, 1729U, 1887U};
char lfo_waveform_name[4][8] = {
"Square ",
"Up ",
"Down ",
"Up-Down"
};
void print_bar(UBYTE val) {
UBYTE i;
printf("[");
for (i = 0; i < 18; i++){
if (i < val) {
printf("-");
} else if (i == val) {
printf("*");
} else {
printf(" ");
}
}
printf("]");
}
void tim() {
__critical {
if (lfo_count_up < lfo_count_max) {
lfo_count_up += 1U << lfo_rate;
} else {
lfo_count_up = 0U;
lfo_dir = ~lfo_dir;
}
}
}
void print_osc_pw() {
gotoxy(0, 12);
switch (osc_pw) {
case 0 : printf("[--________________]"); break;
case 1 : printf("[-----_____________]"); break;
case 2 : printf("[---------_________]"); break;
}
}
void print_lfo_event() {
if (KEY_ANY_EVENT(J_DOWN | J_UP)) {
gotoxy(0, 6);
switch (lfo_rate) {
case 0: print_bar(0); break;
case 1: print_bar(9); break;
case 2: print_bar(17); break;
}
}
if (KEY_ANY_EVENT(J_LEFT | J_RIGHT)) {
gotoxy(0, 9);
switch (osc_freq) {
case 0: print_bar(0); break;
case 1: print_bar(9); break;
case 2: print_bar(17); break;
}
}
}
void main() {
__critical {
lfo_count_max = 376U;
lfo_count_up = 0U;
lfo_dir = 0U;
lfo_waveform = 0U;
osc_pw = 2U;
osc_freq = 1U;
lfo_rate = 1U;
add_TIM(tim);
}
UWORD freq = 0U;
NR52_REG = 0x80U; // Enable sound
/* Sound channel 1 */
// NR10_REG = 0x17U;
// NR11_REG = 0x9FU;
// NR12_REG = 0xF0U;
// NR13_REG = 0x00FFU & freq_2;
// NR14_REG = 0x40 | (freq_2 >> 8);
/* Sound channel 2*/
NR21_REG = (osc_pw & 0x03) << 6;
NR22_REG = 0xF0U;
/* Sound channel 3 */
// NR30_REG = 0x00U;
// NR31_REG = 0x00U;
// NR32_REG = 0x20U;
// NR33_REG = 0xD6U;
// NR34_REG = 0x46U;
NR50_REG = 0x77U; // Set master volume
NR51_REG = 0xFFU;
gotoxy(0, 0);
printf("Siren Machine for GB");
gotoxy(1, 2);
printf("LFO Waveform");
gotoxy(1, 3);
printf("- Square");
gotoxy(1, 5);
printf("LFO Rate");
gotoxy(0, 6);
print_bar(9);
gotoxy(1, 8);
printf("OSC Freq. Offset");
gotoxy(0, 9);
print_bar(9);
gotoxy(1, 11);
printf("OSC Pulse Width");
print_osc_pw();
gotoxy(1, 14);
printf("OSC Sound Off/On");
gotoxy(1, 15);
printf("- Off");
TMA_REG = 0xFFU - lfo_period; // Interrupt rate : 5641.3 Hz
TAC_REG = 0x07U; // Timer enable, Clock at 16384 Hz
set_interrupts(TIM_IFLAG);
while (1) {
if (KEY_PUSHED(J_A)) {
NR22_REG = 0xF0U; // max volume
NR24_REG = 0x80U; // restart sound
}
if (KEY_ISPRESS(J_A)) {
gotoxy(3, 15);
printf("On ");
}
if (KEY_RELEASED(J_A)) {
NR22_REG = 0x00U; // min volume, stop sound
gotoxy(3, 15);
printf("Off");
}
__critical {
if (lfo_waveform == 0U) {
if (lfo_dir) {
freq = 0U;
} else {
freq = lfo_count_max;
}
} else if (lfo_waveform == 1U) {
freq = lfo_count_up;
} else if (lfo_waveform == 2U) {
freq = lfo_count_max - lfo_count_up;
} else {
if (lfo_dir) {
freq = lfo_count_up;
} else {
freq = lfo_count_max - lfo_count_up;
}
}
if (KEY_PUSHED(J_LEFT) && osc_freq > 0U) {
osc_freq--;
} else if (KEY_PUSHED(J_RIGHT) && osc_freq < 2U) {
osc_freq++;
}
}
freq = freq_base[osc_freq] + (freq >> osc_freq);
NR23_REG = 0x00FFU & freq;
NR24_REG = (freq >> 8);
if (KEY_PUSHED(J_B)) {
if (lfo_waveform < 3) {
lfo_waveform++;
} else {
lfo_waveform = 0U;
}
gotoxy(3, 3);
printf("%s", lfo_waveform_name[lfo_waveform]);
}
if (KEY_PUSHED(J_SELECT)) {
if (osc_pw < 2) {
osc_pw++;
} else {
osc_pw = 0U;
}
NR21_REG = (osc_pw & 0x03) << 6;
print_osc_pw();
}
__critical {
if (KEY_PUSHED(J_DOWN) && lfo_rate > 0U) {
lfo_rate--;
} else if (KEY_PUSHED(J_UP) && lfo_rate < 2U) {
lfo_rate++;
}
}
print_lfo_event();
UPDATE_KEYS();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment