Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
So, I figured gbt_player is great for background music, but for simple sound effects using just the registers is enough.
I've found some really handy snippets that break up the sound channels into something a human can understand and use.
I'm using this snippets to make some python preprocessor that spits out the final hex values so I don't use memory during the game.
There's more over here: http://justinkent.com/gbblocks/index.html
// channel 1/2
sweeptime = 7; /* 0-7 */
sweepmode = 1; /* 0-1 */
sweepshifts = 1; /* 0 - 7 */
patternduty = 1; /* 0-3 */
soundlength = 0; /* 0 - 63 */
envinit = 15; /* 0 - 15 */
envmode = 0; /* 0-1 */
envsteps = 2; /* 0 - 7 */
freql = 000;
freqh = 5;
consecutive = 0;
initialflag = 1;
NR10_REG = (sweepshifts + (sweepmode * 8) + (sweeptime * 16));
NR11_REG = (soundlength + (patternduty * 32));
NR12_REG = (envsteps + (envmode * 8) + (envinit * 16));
NR13_REG = freql;
NR14_REG = (freqh + (consecutive * 64) + (initialflag * 128));
Last edited by andreai (2014-10-20 08:18:18)
Offline
I made a thing that's a bit longer than that, but simplifies it a lot more.
#include <gb\gb.h>
#include <stdio.h>
int length = 250;
void E(){
NR12_REG = 0xF0;
NR13_REG = 0x00;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void F(){
NR12_REG = 0xF0;
NR13_REG = 0x28;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void G(){
NR12_REG = 0xF0;
NR13_REG = 0x50;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void A(){
NR12_REG = 0xF0;
NR13_REG = 0x78;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void B(){
NR12_REG = 0xF0;
NR13_REG = 0xA0;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void C(){
NR12_REG = 0xF0;
NR13_REG = 0xC8;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void D(){
NR12_REG = 0xF0;
NR13_REG = 0xF0;
NR14_REG = 0x86;
delay(length);
NR12_REG = 0x00;
delay(50);
}
void rest(){
delay(length);
}
void Song(){
while(1){
length = 500;
G();
length = 1000;
G();
length = 500;
E();
A();
length = 1000;
G();
length = 500;
E();
E();
length = 1000;
G();
length = 500;
E();
A();
length = 1000;
G();
E();
length = 500;
G();
G();
E();
length = 250;
E();
A();
length = 500;
G();
G();
E();
length = 250;
E();
A();
G();
G();
length = 500;
G();
E();
length = 250;
E();
A();
length = 1000;
G();
length = 500;
E();
length = 2000;
rest();
}
}
void main(){
printf(" \n\n\n\n\n\n\n #SpaceKittyGames");
NR52_REG = 0x80;
NR51_REG = 0x11;
NR50_REG = 0x77;
NR10_REG = 0x00;
NR11_REG = 0x80;
NR12_REG = 0x00;
NR14_REG = 0x87;
Song();
}
Last edited by Crona (2014-10-21 16:04:28)
Offline
If you REALLY want to do it that way... Here's a table of the values the GB needs to play each note (page 3 I think): http://www.otakunozoku.com/nintendo-gameboy-cribsheet/
Offline
Crona, if you are familiar with a scripting language like python, c# or whatever, I suggest you do that same thing with an offline script that lets you play with the values and prints the final hex registers, so your code won't suffer performance.
Offline
Yea I changed my the functions to defines, so basically you can just copy and paste mml into the song (as long as it doesn't have length or octave changes)
int length = 250;
#define c \
NR12_REG = 0xF0;\
NR13_REG = 0x00;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define d \
NR12_REG = 0xF0;\
NR13_REG = 0x28;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define e \
NR12_REG = 0xF0;\
NR13_REG = 0x50;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define f \
NR12_REG = 0xF0;\
NR13_REG = 0x78;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define g \
NR12_REG = 0xF0;\
NR13_REG = 0xA0;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define a \
NR12_REG = 0xF0;\
NR13_REG = 0xC8;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define b \
NR12_REG = 0xF0;\
NR13_REG = 0xF0;\
NR14_REG = 0x86;\
delay(length);\
NR12_REG = 0x00;\
delay(50);
#define r \
delay(length);
void Song(){
while(1){
e
}
}
void main(){
printf(" \n\n\n\n\n\n\n #SpaceKittyGames");
NR52_REG = 0x80;
NR51_REG = 0x11;
NR50_REG = 0x77;
NR10_REG = 0x00;
NR11_REG = 0x80;
NR12_REG = 0x00;
NR14_REG = 0x87;
Song();
}
Offline
To play a sampled sound on the gameboy is pretty simple. It's the same technique we used on the Commodore 64 back in the day.
Convert your sample (.wav file) to 4 bit at the rate you want to replay it at i.e. something the Gameboy can actually achieve.
Pass the 4 bit sample data to the volume register (which I think is 0-15, e.g. 4 bit) at the rate the sample was converted to.
Boom! You will be playing your converted wav file. Simples.
The Commodore 64/16/Plus 4 also had a mechanism in the cassette driver to detect 1s and 0s on the tape effectively giving you 1 bit samples. Very compact but very poor quality.
Offline
Guys, the converter isnt gone, just use wayback here https://web.archive.org/web/20120321205 … m/lemon26/
Offline