Gameboy Color Programming (GBDK)

I need a tutorial, I can't find one.

Page 1 of 1

8 Replies - 18376 Views - Last Post: 22 September 2007 - 06:26 PM Rate Topic: -----

#1 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 789
  • View blog
  • Posts: 7,623
  • Joined: 05-May 05

Gameboy Color Programming (GBDK)

Post icon  Posted 22 January 2006 - 10:06 AM

I have already programmed for the Gameboy Advance.

Now I want to go old-school style and program for the Gameboy Color using the GBDK compiler I already have.

What I need is a good tutorial to get myself started. I would also like to know where a good memory map (Every hardware address and what bits to set or read) is. (Where ROM/RAM is located and such). And if anybody can find a tutorial that shows you how to program for the battery-back up save file thing it would be cool.

(The language used for the compile is of course, C).

Please help me, I already went to google.

Is This A Good Question/Topic? 0
  • +

Replies To: Gameboy Color Programming (GBDK)

#2 sontek  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 8
  • View blog
  • Posts: 283
  • Joined: 13-September 01

Re: Gameboy Color Programming (GBDK)

Posted 23 January 2006 - 11:04 AM

I've never actually did any work with gameboys but some of my friends use this site as a reference: http://www.devrs.com/gb/ sorry if its not what you're looking for :crazy:
Was This Post Helpful? 0
  • +
  • -

#3 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 789
  • View blog
  • Posts: 7,623
  • Joined: 05-May 05

Re: Gameboy Color Programming (GBDK)

Post icon  Posted 23 January 2006 - 09:57 PM

Sorry, none of the links there for the good tutorials work.

Actually, a map of every hardware register and a quick info guide on how to program for the battery backup save system is all I need. A memory map of RAM and ROM will be useful. I've already got a sound register tutorial.

I can piece it together from there if ANYBODY can get me links to those things.
Was This Post Helpful? 0
  • +
  • -

#4 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 789
  • View blog
  • Posts: 7,623
  • Joined: 05-May 05

Re: Gameboy Color Programming (GBDK)

Post icon  Posted 28 January 2006 - 07:48 PM

After getting blown up, I dug these out of the dark corners of the google search engine.

I posted instead of linking some because the links to some of these things are probably dead by now becuse they do die fast!

Here are all the stuff so you don't have to do what I did:
:)

For anybody who wants to know some good documentation on the GB programming, here are some links those things:

GBDK with API documentation:

GBDK for Windows or Linux

A full memory map:
PanDocument

A sound table:
GameBoy Sound Table
Note	MIDI	GB	Hertz  Note	MIDI	GB	Hertz
C 0	0	-	8.176  E 5	64	1650	329.63
C# 0	1	-	8.662  F 5	65	1673	349.23
D 0	2	-	9.177  F# 5	66	1694	369.99
D# 0	3	-	9.723  G 5	67	1714	391.99
E 0	4	-	10.301  G# 5	68	1732	415.31
F 0	5	-	10.913  A 5	69	1750	440.00
F# 0	6	-	11.562  A# 5	70	1767	466.16
G 0	7	-	12.250  B 5	71	1783	493.88
G# 0	8	-	12.978  C 6	72	1798	523.25
A 0	9	-	13.750  C# 6	73	1812	554.37
A# 0	10	-	14.568  D 6	74	1825	587.33
B 0	11	-	15.434  D# 6	75	1837	622.25
C 1	12	-	16.352  E 6	76	1849	659.26
C# 1	13	-	17.324  F 6	77	1860	698.46
D 1	14	-	18.354  F# 6	78	1871	739.99
D# 1	15	-	19.445  G 6	79	1881	783.99
E 1	16	-	20.601  G# 6	80	1890	830.61
F 1	17	-	21.826  A 6	81	1899	880.00
F# 1	18	-	23.124  A# 6	82	1907	932.32
G 1	19	-	24.499  B 6	83	1915	987.77
G# 1	20	-	25.956  C 7	84	1923	1046.5
A 1	21	-	27.50  C# 7	85	1930	1108.7
A# 1	22	-	29.135  D 7	86	1936	1174.7
B 1	23	-	30.867  D# 7	87	1943	1244.5
C 2	24	-	32.703  E 7	88	1949	1318.5
C# 2	25	-	34.648  F 7	89	1954	1396.9
D 2	26	-	36.708  F# 7	90	1959	1480.0
D# 2	27	-	38.890  G 7	91	1964	1568.0
E 2	28	-	41.203  G# 7	92	1969	1661.2
F 2	29	-	43.653  A 7	93	1974	1760.0
F# 2	30	-	46.249  A# 7	94	1978	1864.7
G 2	31	-	48.999  B 7	95	1982	1975.5
G# 2	32	-	51.913  C 8	96	1985	2093.0
A 2	33	-	55.000  C# 8	97	1988	2217.5
A# 2	34	-	58.270  D 8	98	1992	2349.3
B 2	35	-	61.735  D# 8	99	1995	2489.0
C 3	36	44	65.406	E 8	100	1998	2637.0
C# 3	37	156	69.295	F 8	101	2001	2793.8
D 3	38	262	73.416	F# 8	102	2004	2960.0
D# 3	39	363	77.781	G 8	103	2006	3136.0
E 3	40	457	82.406  G# 8	104	2009	3322.4
F 3	41	547	87.307	A 8	105	2011	3520.0
F# 3	42	631	92.499	A# 8	106	2013	3729.3
G 3	43	710	97.998	B 8	107	2015	3951.1
G# 3	44	786	103.82	C 9	108	-	4186.0
A 3	45	854	110.00	C# 9	109	-	4434.9
A# 3	46	923	116.54	D 9	110	-	4698.6
B 3	47	986	123.47	D# 9	111	-	4978.0
C 4	48	1046	130.81	E 9	112	-	5274.0
C# 4	49	1102	138.59	F 9	113	-	5587.7
D 4	50	1155	146.83	F# 9	114	-	5919.9
D# 4	51	1205	155.56	G 9	115	-	6271.9
E 4	52	1253	164.81	G# 9	116	-	6644.9
F 4	53	1297	174.61	A 9	117	-	7040.0
F# 4	54	1339	184.99	A# 9	118	-	7458.6
G 4	55	1379	195.99	B 9	119	-	7902.1
G# 4	56	1417	207.65	C 10	120	-	8372.0
A 4	57	1452	220.00	C# 10	121	-	8869.8
A# 4	58	1486	233.08	D 10	122	-	9397.3
B 4	59	1517	246.94	D# 10	123	-	9956.1
C 5	60	1546	261.63	E 10	124	-	10548.1
C# 5	61	1575	277.18	F 10	125	-	11175.3
D 5	62	1602	293.66	F# 10	126	-	11839.8
D# 5	63	1627	311.13	G 10	127	-	12543.9

Middle C = 261.63Hz = C5

NOTE:
  The GB values above are the closest match to the shown
 perfect Hertz frequencies. The higher the frequencies
 the GB values attempt to recreate the more the percentage
 of error increases.



And a sound programming FAQ, the URL doesn't work anymore so I have to post it:
[code]
<div class="moz-text-flowed" style="font-family: -moz-fixed">Nintendo(TM) Gameboy sound system (PAPU) guide, v0.99.20 (1/01/2004)
Written by Jonathan Gevaryahu, with help from many, many others.
lord_nightmare at users d0t sourceforge d0t net
I can also be found on Freenode #gnuboy or EFnet #gameboy and #gbdev
(This document is written in the same style/context as Brad Taylor's very
useful NESSOUND.txt; If you found NESSOUND.txt useful for NES work, I hope
you
find this just as useful for Gameboy work)

The latest version of this document can (hopefully) always be obtained from:
http://www.netaxs.com/~gevaryah/GBSOUND.txt
and from Joshua's mirror at:
http://www.joshuawise.com/~nightmare/GBSOUND.txt
and sometime soon, from the devrs.com mirror at:
http://www.devrs.com/gb/files/GBSOUND.txt

All results were obtained by studying prior information available, mainly
the
(in)famous Pan Docs, additional info added to the pan docs by Martin Korth
of
NO$GMB fame, info from some of Jeff Frohwein's various tests, and from
information derived from my own experimentation.
Anything UNVERIFIED is an educated guess based on prior knowledge.

also, as Brad Taylor said so well:
"A special thanks goes out to Matthew Conte, for his expertise on
pseudo-random number generation (amoung other things), which allowed for the
full reverse engineering of the NES's noise channel to take place. Without
his help, I would still be trying to find a needle in a haystack, as far as
the noise's method of pseudo-random number generation goes..."
This applies here as well, since the Gameboy's PRNG is very similar to the
NES'

ANYHOW...


/------------------\
< **Introduction** >
\------------------/

The DMG-CPU/GBC-CPU/SGB-CPU (sometimes referred to as the GB-Z80 due to it's
similarity with the Z80 microprocessor) has, internally, 4 semi-analog sound
channels. These can be output in a conditional (on or off) fashion to one or
both of the Gameboy's output terminals, achieving a pseudo-stereo effect.
The sound sometimes referred to as a PAPU, or Pseudo-Audio-Processing-Unit,
Pseudo because it isn't actually a separate unit. However, from a
programming
standpoint, for all intents and purposes it is a separate circuit from the
main
processor.
I'll go into as deep detail as I can when explaining the inner workings of
this
PAPU.



/---------------------\
< **Channel Details** >
\---------------------/
Each one of the four channels is different in it's own way:

Channel 1 is a Square wave channel with volume envelope and frequency sweep
functions.

Channel 2 is a Square wave channel with volume envelope functions only.

Channel 3 is a programmable wave channel with 32 4-bit programmable samples,
played in sequence.

Channel 4 is a 'white noise' channel with volume envelope functions.

Channels 1-3 can produce frequencies of 64hz-131072hz
Channel 4 can produce bit-frequencies of 2hz-1048576hz.

NOTE:
On the SGB-CPU, due to video sync issues, the processor runs approximately
2.4%
faster than the handheld units, and, respectively, sounds are played at a
2.4%
higher frequency.



/------------------------\
< **Register Addresses** >
\------------------------/

The addresses through which the sound channels can be accessed are:
$Addresses: (Description), (Register shorthand)
$FF10 -- $FF14: Channel 1, Referred to as NR10-NR14
$FF15 is unused, was probably going to be a sweep reg for channel 2
originally
$FF16 -- $FF19: Channel 2, Referred to as NR21-NR24
$FF1A -- $FF1E: Channel 3, Referred to as NR30-NR34
$FF1F is unused, was probably going to be a sweep reg for channel 4
originally
$FF20 -- $FF23: Channel 4, Referred to as NR41-NR44
$FF24 controls the Vin status and volume, Referred to as NR50
$FF25 selects which output each channel goes to, Referred to as NR51
$FF26 is the status register, and also controls the sound circuit's power.
Referred to as NR52
$FF27 -- $FF2F are unused.
$FF30 -- $FF3F is the load register space for the 4-bit samples for channel
3

PARTIALLY VERIFIED: All registers are read/writable except for the
initialize
flags for each channel, and $FF30-$FF3F, which is read/writable, but is
scrambled slightly once channel 3 is played with new data written there.
The low 4 bits of $FF26 have no effect whatsoever if written to, as they are
status flags.

Writing a 0 to bit position 7 in register $FF26(NR52) disables the power to
the
audio processing unit, which can give a 15-20% increase in battery life if
used
properly. see note on power consumption for details.

PARTIALLY VERIFIED: Any writes to any register while the audio processing
unit
is OFF have NO EFFECT WHATSOEVER, with the exception of the $FF30-$FF3F
range.

PARTIALLY VERIFIED: Any writes to any unused bits in any register are
RETAINED
as long as the APU isn't powered off, so they can be theoretically used for
temporary storage by programs. I have yet to see a program which DOES this,
but
it is quite doable!

My writing a test ROM to dump the entire audio range's initial state to SRAM
memory revealed a few mistakes in versions prior to 99.20 of this document,
so
CHECK EVERYTHING AGAIN CAREFULLY!

Each channel has 5 registers associated with it, and, like the NES, they are
in
sets:

/-------\
< Set 1 >
\-------/
Master on/off and Sweep Register

Channel 1 - $FF10(NR10)[sq1]
---------------------------------------------
7 Unused
6-4 Sweep time(update rate) (if 0, sweeping is off)
3 Sweep Direction (1: decrease, 0: increase)
2-0 Sweep RtShift amount (if 0, sweeping is off)

Channel 3 - $FF1A(NR30)[wave]
---------------------------------------------
7 Channel 3 Master on/off
6-0 Unused

Channels 2,4 - $FF15(NR20)[sq2], $FF1F(NR40)[noise]
---------------------------------------------
7-0 Unused


/-------\
< Set 2 >
\-------/
Wave pattern duty and Sound length Register

Channels 1,2,4 - $FF11(NR11)[sq1], $FF16(NR21)[sq2], $FF20(NR41)[noise]
---------------------------------------------
7-6 Wave pattern duty (only on channels 1 and 2)
5-0 Length counter load register

Channel 3 - $FF1B(NR31)[wave]
---------------------------------------------
7-0 Length counter load register


/-------\
< Set 3 >
\-------/
Volume Envelope Control register

Channels 1,2,4 - $FF12(NR12)[sq1], $FF17(NR22)[sq2], $FF21(NR42)[noise]
---------------------------------------------
7-4 (Initial) Channel Volume
3 Volume sweep direction (0: down; 1: up)
2-0 Length of each step in sweep (if 0, sweeping is off)
NOTE: each step is n/64 seconds long, where n is 1-7

Channel 3 - $FF1C(NR32)[wave]
---------------------------------------------
7 Unused
6-5 Volume Level (0: Mute; 1: 100%; 2: 50% [rtshift 1]; 3: 25% [rtshift 2])
4-0 Unused


/-------\
< Set 4 >
\-------/
Frequency LSbs and Noise options

Channels 1,2,3 - $FF13(NR13)[sq1], $FF18(NR23)[sq2], $FF1D(NR33)[wave]
---------------------------------------------
7-0 8 Least Significant bits of frequency (3 MSbs are in set 5)

Channel 4 - $FF22(NR43)[noise]
---------------------------------------------
7-4 Shift clock frequency (s)
3 Shift Register width (0: 15 bits; 1: 7 bits)
2-0 Dividing Ratio of frequency (r)
Frequency = 524288 Hz / r / 2^(s+1)   ;For r=0 use r=0.5 instead


/-------\
< Set 5 >
\-------/
Playback flags and frequency MSbs

Channels 1,2,3,4 - $FF14(NR14)[sq1], $FF19(NR24)[sq2], $FF1E(NR34)[wave],
$FF23(NR44)[noise]
---------------------------------------------
7 Initialize (trigger channel start, AKA channel INIT)  (Write only)
6 Consecutive select/length counter enable              (Read/Write)
5-3 Unused
2-0 3 Most Significant bits of frequency (channels 1,2,3) (Read?/Write)


/-------------\
< Control Set >
\-------------/

$FF24(NR50) - Vin (input line on cart connector) / Main Output Volume
Control
---------------------------------------------
7 Output Vin to Main SO2 output level control (1: on; 0: off)
6-4 SO2 (Left) Main Output level (volume)
3 Output Vin to Main SO1 output level control (1: on; 0: off)
2-0 SO1 (Right) Main Output level (volume)

$FF25(NR51) - Sound Output terminal select (1: enabled; 0: disabled)
---------------------------------------------
7 Channel 4 to Main SO2 output level control (Left)
6 Channel 3 to Main SO2 output level control (Left)
5 Channel 2 to Main SO2 output level control (Left)
4 Channel 1 to Main SO2 output level control (Left)
3 Channel 4 to Main SO1 output level control (Right)
2 Channel 3 to Main SO1 output level control (Right)
1 Channel 2 to Main SO1 output level control (Right)
0 Channel 1 to Main SO1 output level control (Right)

$FF26(NR52) - Master control and status flags
---------------------------------------------
7 Master sound circuitry power control (read/write)
6-4 unused
3 Channel 4 status flag (Read-only)
2 Channel 3 status flag (Read-only)
1 Channel 2 status flag (Read-only)
0 Channel 1 status flag (Read-only)

IMPORTANT NOTE ON POWER CONSUMPTION!!!
Writing a 0 to bit position 7 in register $FF26(NR52) disables the power to
the
audio processing unit, which can give a 15-20% increase in battery life if
used
properly. When the PAPU is disabled, all registers in the range $FF10-$FF2F
are
unreadable and unwritable except for register $FF26(NR52). When the power is
disabled, all register values, hidden or accessible, are lost, except for
both
the hidden internal and regular $FF30-FF3F wave pattern memory area. Reading
from $FF26(NR52) while the audio processing unit is disabled will yield the
values last written into the unused bits (0x70), all other bits are 0.
A good way to use this in your game is to disable the audio unit during any
time where there will be no sound playing for an extended period (when
paused
for instance), or where there will be long gaps between any sounds played.
Note that turning on or off the audio unit results in an audible CLICK noise
over the SOx output lines (AKA the stereo channels). The volume of the click
can be reduced considerably by turning both of the output master volume
controls to zero before turning off the sound core, but practically all
games
don't bother doing this, as the click is almost unnoticable among other
sounds.

/-------------------------\
< Initial Register Values >
\-------------------------/
Upon a sound core power-cycle, the registers will be loaded with the
following
values:
$FF10(NR10) - 0x80
$FF11(NR11) - 0xBF
$FF12(NR12) - 0xF3
$FF13(NR13) - No Change
$FF14(NR14) - 0xBF
$FF15(NR20) - No Change
$FF16(NR21) - 0x3F
$FF17(NR22) - 0x00
$FF18(NR23) - No Change
$FF19(NR24) - 0xBF
$FF1A(NR30) - 0x7F
$FF1B(NR31) - 0xFF
$FF1C(NR32) - 0x9F
$FF1D(NR33) - No Change
$FF1E(NR34) - 0xBF
$FF1F(NR40) - No Change
$FF20(NR41) - 0xFF
$FF21(NR42) - 0x00
$FF22(NR43) - 0x00
$FF23(NR44) - 0xBF
$FF24(NR50) - 0x77
$FF25(NR51) - 0xF3
$FF26(NR52) - SEE BELOW

VERIFIED on DMG, SGB, and CGB: Values marked 'No Change' are reset to 0xFF
upon
a system reset or power-cycle.

On the DMG/GBP/CGB, the value of $FF26(NR52) is 0xF_1_ due to the fact that
channel 1 is on-but-faded-out, due to the two-toned 'Gameboy startup sound'.
On the SGB/SGB2, however, there IS no internally-created startup noise, and
so
the initial value is 0xF_0_, and channel 1 is off.

For initial values of $FF30-$FF3F, see section 'Wave pattern memory' below.



/--------------------------\
< **Channel Architecture** >
\--------------------------/
Here, I will try to describe the inner workings of the channels in as much
detail as I can manage. Please note that a few of the points are not
completely
tested and/or understood (particularly the zombie state increment stuff, see
'volume/envelope control unit')

IMPORTANT NOTE!: Lacking an oscilloscope, I'm making a LOT of guesses about
the
specifics (counters, etc), somewhat based on the fact that the NES and
Gameboy
sound units are very very similar, and somewhat by experimental results.
I can pretty much promise that by version 1.0 of this doc, if I ever get
that
far, I will have 100% completely verified info.

Device                        Square1  Square2  Waveform  Noise
------                        -------  -------  --------  -----
programmable timer                  X        X         X
configurable timer                                            X
length counter                      X        X         X      X
unified length clock                <<COMMON FOR ALL CHANNELS>>
4-bit DAC                           X        X         X      X
volume/envelope control unit        X        X                X
master output control switch        *        *         X      *
frequency sweep unit                X
duty cycle generator                X        X
PseudoRandom Number Generator                                 X
wave pattern memory                                    X
wave pattern playback/volume shift unit                X
SO1/SO2 Control unit                *        *         *      *

/--------------------\
< Programmable timer >
\--------------------/
The programmable timer is an 11-bit presettable down counter, with
reloading-
upon-0. It is found in the two squarewave channels and the voluntary wave
channel. Some permutation of it may exist on the noise channel also, but for
all intents and purposes it doesn't exist there.

Channels 1,2,3 - $FF13(NR13)[sq1], $FF18(NR23)[sq2], $FF1D(NR33)[wave]
---------------------------------------------
7-0 8 Least Significant bits of frequency, bits 7-0

Channels 1,2,3 - $FF14(NR14)[sq1], $FF19(NR24)[sq2], $FF1E(NR34)[wave]
---------------------------------------------
2-0 3 Most Significant bits of frequency, bits A-8

The 11-bit frequency value, upon either part being written, is
binary-inverted
(NOT), and the resulting number plus one is placed into the 11-bit counter.
Another possibility is that the 11-bit frequency is subtracted from 2048,
the
result being written into the counter. (either way, the result is the same)

Attempting to read the contents of these registers will yield a null result
(either all 0's or all 1's, I haven't checked yet)

The counter has 'syncronous reloading upon terminal count', meaning that it
will count for N clock cycles before arriving at 0 (the 'terminal count', at
which the counter's TC line is raised), and then be reloaded, taking an
additional cycle, and resume counting). This counter is clocked by the
output
of a 5-bit count-0-to-31-and-loop timer/divider, which itself is clocked by
the
gameboy's standard CPU clock input, 4.194304mhz.
[the pitch doesn't double when in the CGB's doublespeed mode, because
doublespeed mode only makes the *processor* clock on both the rising and
falling edges of the clock signal, which stays constant at 4.194304mhz.]

This makes the output frequency work like this as compared to the 11-bit
freq:

Hz = 4194304 / ((2048 - (11-bit-freq)) << 5)
which could also be written like:
Hz = 4194304 / ((~11-bit-freq + 1) << 5)
or also like:
Hz = 131072 / (~11-bit-freq + 1)

The Terminal Count line is also connected to either the duty cycle
generator,
the wave pattern playback unit, or the pseudorandom number generator's
trigger,
depending on the channel.

NOTE: Channel 1's sweep unit will scramble its counter's contents during a
sweep, and will necessitate a fresh write of the frequency values. (see
sweep
unit)


/--------------------\
< Configurable Timer >
\--------------------/
The configurable timer is the noise channel (channel 4)'s equivalent of a
programmable frequency timer. It is controlled by register $FF22(NR43), and
consists of a customized 3-bit down counter, a 16-bit long down counter with
reload-on-0 and only 1 initially-settable bit. The 3-bit down counter's
initial/reload setting is determined by the setting of the frequency divide
ratio.

Channel 4 - $FF22(NR43)[noise]
---------------------------------------------
2-0 Frequency divide ratio

The down counter is clocked at 2097152 hz, divided from the processor's
4.194304Mhz frequency. The counter counts down until 0, and spends 1 clock
cycle reloading the initial value from the freq divide ratio. When it
reloads,
it inverts the status of its output line.

clock freq:  \\\\\\\\\\\\\\\\\\\\\\\\\\\\ 2097152 hz
ratio of:  0 _-_-_-_-_-_-_-_-_-_-_-_-_-_- 1048576 hz
   1 __--__--__--__--__--__--__--  524288 hz
   2 ___---___---___---___---___- ~370727.6 hz
   3 ____----____----____----____  262144 hz
   4 _____-----_____-----_____--- ~220435.95 hz
   5 ______------______------____ ~185363.8 hz
   6 _______-------_______------- ~155871.75 hz
   7 ________--------________----  131072 hz

The terminal count/output of the counter is the clock input to the shift
clock.

The shift clock is a 16-bit long down counter which can have any single bit
in
it set as the initial/reload value, the position of that bit being read from
the shift clock frequency register.
UNVERIFIED: Reloading of the value is instantaneous.

Channel 4 - $FF22(NR43)[noise]
---------------------------------------------
7-4 Shift clock frequency

The terminal count of the shift clock is the input clock signal of the
Pseudo-Random Number Generator.

PRNG Frequency = (1048576 Hz / (ratio + 1)) / (2 ^ (shiftclockfreq + 1))
(by '^' I mean 'raised to the power of', NOT 'XOR')

/----------------\
< Length Counter >
\----------------/
The Gameboy's audio channels each feature a length counter, a conditionally
clocked down counter. There are two types of length counters used in the
Gameboy's PAPU: the 5-bit ones used on channels 1, 2, and 4, and the 8-bit
one
used on channel 3. The clock source for each counter is described below.

Values can be loaded into the length counters for each channel using the
following registers:

Channels 1,2,4 - $FF11(NR11)[sq1], $FF16(NR21)[sq2], $FF20(NR41)[noise]
---------------------------------------------
5-0 Length counter load register

The 5-bit value is binary-inverted (NOT) upon a register write, 1 is added
to
the result, and the resulting value is written to the counter. Another
possibility is that the 5-bit length value is subtracted from 64, the result
being written to the counter. (either way, the result is the same)

These length counters are clocked at a rate of 1 count every 1/256th of a
second, taken directly from the unified length clock (256hz, see below).
Therefore: length in seconds = (64 - [length]) * (1/256)

NOTE: In versions of this document prior to 99.18, I had the length counter
clock for channels 1,2,4 being clocked once every 1/64th of a second.
Subsequent testing proved that this was incorrect. Thanks to beware for
asking
me to check it.

Channel 3 - $FF1B(NR31)[wave]
---------------------------------------------
7-0 Length counter load register

The 8-bit value is binary-inverted (NOT) upon a register write, 1 is added
to
the result, and the resulting value is written to the counter. Another
possibility is that the 8-bit length value is subtracted from 256, the
result
being written to the counter. (either way, the result is the same)

This length counter is also clocked at a rate of 1 count every 1/256th of a
second, taken directly from the unified length clock (256hz, see below).
Therefore: length in seconds = (256 - [length]) * (1/256)

Writing a value to a length counter will IMMEDIATELY start the counter
counting
down, regardless of the channel's current on/off state! This will happen ANY
time that the length counter enable bit is on during a write. Several games,
notably 'Mega Man 2' and 'Balloon Kid' prove this.

NOTE: The length counters are NEVER reloaded to their last written value!
They
must be reloaded by hand EVERY TIME, as the values written are destroyed
during
the countdown itself! However, Initializing the channel (setting bit 7 of
$FF14, $FF19, $FF1E, $FF23) when the counter is already at zero will cause a
maximum-length-possible-for-the-channel playback! Be careful!

VERIFIED: If the counter is written to while the length counter enable bit
(see
below) is OFF, the value will remain intact until the enable bit is turned
on.
This is regardless of whether the channel is INITed then, although I'm
fairly
sure it was intended that one would start the counter and the channel during
the same PAPU write.

The clocking of the counter is enabled or disabled depending on the status
of
the 'length counter enable register' (AKA the 'consecutive' bit) in register
set 5, a 1 enabling the counter, a 0 disabling it.

Channels 1,2,3,4 - $FF14(NR14)[sq1], $FF19(NR24)[sq2], $FF1E(NR34)[wave],
$FF23(NR44)[noise]
---------------------------------------------
6 Consecutive select/length counter enable              (Read/Write)

The real-time status for the length counter of a given channel can be
attained
by reading register $FF26(NR52). a 1 indicates that the length counter is
non-0, or that the consecutive/length counter enable bit is 0; 0 indicates
that
the length counter is 0, and subsequently that channel is off.

$FF26(NR52) - Master control and status flags
---------------------------------------------
3 Channel 4 status flag (Read-only)
2 Channel 3 status flag (Read-only)
1 Channel 2 status flag (Read-only)
0 Channel 1 status flag (Read-only)


/----------------------\
< Unified Length Clock >
\----------------------/
This is a recent discovery, pointed out to me by beware(of bgb fame). It is
a
single clock, running at 256hz, probably divided directly from the GB
processor's clock (4.194304Mhz). It is used to clock the length counters of
each channel, when the length counter enable bit (see above) for that
particular channel is on. It is common to all channels, so when it clocks
for
one channel it clocks all of them.

UNVERIFIED: It may also be used, after being divided by 2, to clock the
128hz
sweep clock. The last test I did was inconclusive, probably due to some
mistake
I made during testing.


/-----------\
< 4-bit DAC >
\-----------/
This is a plain-old vanilla linear 4-bit DAC, 16 steps of output voltage.
All
of the sound channels use them for output.


/--------------------------------\
< Volume / Envelope Control unit >
\--------------------------------/

The Volume/Envelope control unit is a simple volume control which can also
do
fade-ins and fade-outs at a configurable rate. The channel volume level is
controlled by a 4-bit delta counter (which can be incremented or decremented
by
1) with an overflow/underflow line. The 1-bit input from the duty cycle
generator or PRNG is multiplied by 15, and binary AND'ed against the volume
control (effectively multiplied by the volume control). Modifications to the
volume control take effect upon the next channel INIT, and if the channel
was
on (length counter status was non-0, and master volume control switch was
on;
see below), then it will trigger a 'zombie mode' volume change (see below).

Channels 1,2,4 - $FF12(NR12)[sq1], $FF17(NR22)[sq2], $FF21(NR42)[noise]
---------------------------------------------
7-4 (Initial) Channel Volume

The volume sweep section consists of a 3-bit down counter(hereafter referred
to
as the 'step length counter') with switchable reload-upon-0, whose initial
value is loaded from the sweep rate value on channel INIT.

Channels 1,2,4 - $FF12(NR12)[sq1], $FF17(NR22)[sq2], $FF21(NR42)[noise]
---------------------------------------------
2-0 Length of each step in sweep

The terminal count (value=0) line of this counter is output to a 1-of-2
selector. This 1-of-2 selector is used to select an upward or downward
volume
sweep, getting the direction from the Volume/envelope register on channel
INIT.

Channels 1,2,4 - $FF12(NR12)[sq1], $FF17(NR22)[sq2], $FF21(NR42)[noise]
---------------------------------------------
3 Volume sweep direction (0: down; 1: up)

if the direction is 0, the counter outputs its signal through the selector
into
the decrease (-) delta terminal of the volume counter. If the direction is
1,
the counter outputs its signal through the selector into the increase (+)
delta
terminal of the volume counter.

SPECULATION: The volume counter itself has an overflow/underflow line, which
is
connected to a switch that prevents the step length counter from reloading
its
original value when it reaches 0. When this occurs, the terminal count line
of
the step length counter is ON steadily, and unless the channel's length
counter
is enabled (and will shut the channel off), the channel enters 'zombie
mode'.

ZOMBIE MODE: UNDEAD CHANNELS!
The channel's volume is now whatever it was set to, or 0/15 if a sweep
occured,
and will sustain that volume indefinitely unless the length counter halts
the
channel. If any envelope register bits are now changed, the volume of the
channel will increase by 1 or 2, looping around to 0 if necessary. (1 if the
channel was INIT-ed with the sweep step number set to 0, 2 if otherwise;
also 2 if the step number has been changed to a non-zero value since the
INIT,
even if it currently is 0)

If the volume sweep direction bit is changed, however, the volume of the
channel will increase by 4 instead of 2, for that write only. Direction of
the
change(1->0 or 0->1) is apparently irrelevant. While in zombie mode, if the
step length register is set to 0, it will have no immediate effect other
than
increasing the volume by 2 (or 4 if the direction was also changed). (but it
WILL change the step size to 1 if the channel is then re-INITed, see above)
Setting the (Initial) Volume to 0 will disable the channel's master channel
control switch, and silence the channel (see below, 'master channel control
switch').

Re-INITing the channel will pull it out of zombie mode: it will turn
envelope
sweeping back on, unless the volume is 0, in which case the master volume
control switch will be off.


/-------------------------------\
< Master Channel Control Switch >
\-------------------------------/
The master channel control switch, which appears at first glance to be
unique
to channel 3, is actually not exclusive to that channel. It is present in
all
of the channels, but is embedded within the Initial Volume control, on the
channels which have an Envelope Control unit (channels 1, 2, and 4).

As mentioned above in the 'Volume/Envelope Control Unit' section, when a
downward envelope sweep occurs, the channel is NOT shut off when the volume
reaches 0. HOWEVER, writing a 0 to the (Initial) Volume section of the
envelope
register will cause that channel's 'hidden' master channel control switch to
be
turned off. This ONLY occurs if 0 is *WRITTEN* to the register, and only if
the
master channel control switch is not already off(it can't be turned off
twice!)
If the switch is off, it can be turned back on by writing any non-0 value to
the (Initial) Volume section of the register.

UNVERIFIED, PLEASE TAKE WITH A GRAIN OF SALT: When the switch for a channel
is
off, it's length counter status flag will be 0. In fact, this may very well
be
the switch turned off by the length counter too.

The switch causes a slight residual DC voltage to be output to the SOx
switches, even if the channel's DAC output is at 0. It makes an audible
click
noise on the speaker/headphones when switched.

At system startup, channel 1's switch is on (turned on by the bootstrap
rom),
all other channels are off.


/----------------------\
< Frequency Sweep Unit >
\----------------------/
The sweep unit is exclusive to channel 1. The controlling register for the
sweep unit is $FF10(NR10). The sweep unit, on channel INIT, grabs the the 11
bits of channel 1's frequency register, and stores them into a hidden,
internal
register. any writes to the frequency registers during the sweep, will take
effect until the sweep unit makes its next write to those registers,
continuing
the original sweep. IT WILL NOT SWEEP FROM THE NEW FREQUENCY! The sweep unit
has the aforementioned hidden frequency register (an 11-bit accumulator), an
adder, a 3-bit down counter with reload-on-0, a selector switch, and an
up-to-3-bit rightshifter.

The 3-bit down counter controls the frequency of sweep updates. It's initial
(and reload) value is taken from the sweep time register. The value-reload
takes 1 clock cycle.

Channel 1 - $FF10(NR10)[sq1]
---------------------------------------------
6-4 Sweep time(update rate)

The counter is clocked at 128hz, divided from the unified sound clock
(256hz),
so the frequency-of-sweep-update will be:
freq(hz) = 128 / (sweep time + 1)

NOTE: Writing 0 to the sweep time register disables the clock, and therefore
disables sweeping.

The frequency in the accumulator is first rightshifted by up to 7 bits,
controllable by the Sweep RtShift amount register:

Channel 1 - $FF10(NR10)[sq1]
---------------------------------------------
2-0 Sweep RtShift amount

NOTE: Writing 0 to the Sweep RtShift amount disables sweeping. While the
RtShift amount is 0, the sweep time register becomes sort of a length
counter,
and the channel will automatically terminate on it clocking.

NOTE2: When set to sweep upward, the channel will do absolutely nothing on
INIT
unless the current frequency is below the 'sweep threshhold' for that
particular rightshift amount.

The reason for this is because otherwise the channel's NEXT step would
IMMEDIATELY overflow the 11-bit frequency counter.
(frequencies immediately below the threshholds will only play one note,
since
the second step wouldn't overflow, but the third step would, and so only the
first step is played. The sweep unit always works one step ahead of the
current
output, and on the next step outputs that result and calculates the next,
etc.)

The threshholds are:
0: 0x7ff(no threshhold, since sweeping is disabled)
1: 0x556
2: 0x667
3: 0x71d
4: 0x788
5: 0x7c2
6: 0x7e1
7: 0x7f1

The above table is actually unnecessary, I'm just leaving it in as a
reference.

The game 'Metroid 2' runs into this issue in a few places, apparently the
programmers didn't know about the above info. Also, the knife-throwing
monsters
in 'Wario Land: Super Mario Land 3' run into the issue, but there it is
intentionally used to prevent their 'voices' from going too high.

Upon reaching the terminal count (value=0), the counter sends a signal to a
selector, which controls what direction the sweep will be by controlling the
sign bit of the accumulator.

Channel 1 - $FF10(NR10)[sq1]
---------------------------------------------
3 Sweep Direction (1: decrease, 0: increase)

The adder then takes the accumulator, and adds that value to the 11-bit
frequency value stored in registers $FF13 and $FF14. Therefore, because the
registers are modified, the frequency must be rewritten in-between sweeps.


/----------------------\
< Duty Cycle Generator >
\----------------------/
The duty cycle generator is a 3-bit (down?) counter which produces output
depending on the result of some binary operations against the bits of the
counter, the operations selectable by changing the duty cycle bits in
register.

Channels 1,2 - $FF11(NR11)[sq1], $FF16(NR21)[sq2]
---------------------------------------------
7-6 Wave pattern duty

The resulting waves are:

Bits  Cyc%   0 1 2 3 4 5 6 7
00  : 12.5%  ________==______
01  : 25%    ________====____
10  : 50%    ____========____
11  : 75%    ========____====

= is High
_ is Low

Note that 75% is just a binary NOT against 25%, and that the two are almost
indistinguishable to the human ear.

The duty cycle generator is clocked by the output of the frequency counter
for
channels 1 and 2.

Upon the channel INIT trigger bit being set for either channel 1
or 2, the wave position's incrementing will be delayed by 1/12 of a full
cycle.
IT WILL *NOT* BE RESET TO 0 BY A CHANNEL INIT. 'Gauntlet II' does a very
slick
job of timing? itself around this fact.

Upon system reset, channel 1 will be set to the 50% duty cycle wave, channel
2
to the 12.5% duty cycle wave. (see initial register values)

COMPLETELY UNVERIFIED: In a recent update to NESSOUND.txt, Brad Taylor
demonstrated that the way to reset the position of the two squarewave
channels
on the NES to position 0 is by resetting the timer register. The equivalent
register on the gameboy is PROBABLY the $FF04 (DIV) register, though it
could
also be $FF05 - $FF07 (Timer stuff). This may turn out to be the mysterious
'slick' way that Gauntlet II can 'reset' the position of the squarewave
channels.

PARTIALLY VERIFIED:
The CGB has channels 1 and 2 output in such a way (normal phase reversed on
channel 2 from channel 1) that the two squarewave channels can cancel each
other out completely instead of adding to each other, as on the DMG, MGB,
and
SGB.
I think that one of the reasons Nintendo did this on the CGB was to mess up
the
startup theme of the Galoob 'Game Genie', which is practically inaudible on
the
CGB for this reason! Another, more likely reason could be that they used
some
silicon-saving technique on the duty cycle generators which necessitated
opposite phase on the two squarewave channels.
This is noticible in quite a few official Nintendo-approved games, but the
game
which demonstrates it particularly vividly is "Lock n' Chase". It sounds
absoluetly HORRIBLE on a CGB!


/-------------------------------\
< PseudoRandom Number Generator >
\-------------------------------/
The noise channel has a 1-bit pseudo-random number generator, or PRNG. This
particular type of PRNG is called an LFSR, a Linear Feedback Shift Register.
It's based on a 15 or 7-bit shift register, and an exclusive OR gate (XOR).
The
mode is selectable by the Shift register width selector.

Channel 4 - $FF22(NR43)[noise]
---------------------------------------------
3 Shift Register width (0: 15 bits; 1: 7 bits)

The following diagram shows where the XOR taps are taken off the shift
register to produce the 1-bit pseudo-random number sequences for each mode.

mode        <-----
----   FEDCBA9876543210
32K    %*.............R
512    XXXXXXXX%*.....R

X- N/A
%- output and XOR tap
*- XOR tap
R- result of XOR, to be shifted in

The current result of the XOR will be transferred into bit position 0 of the
shift register upon the next shift cycle. The 1-bit 'random' output is taken
from the output, is inverted, then is sent to the volume/envelope hardware
for
the noise channel.

VERIFIED: Upon the channel INIT trigger bit being set for this channel (4),
the PRNG will be reloaded with a value of 0xFF. (Kirby 2)
NOTE: There will be a 16-clock delay before the PRNG outputs any non-0 data
after an INIT. This means the value loaded on channel INIT isn't 0x01 as
previously written here, but is 0xFF. this will cause the channel to have a
value of 0x01 16 clocks later. Again, thanks to beware for pointing this
out.

On system reset, this shift register is loaded with a value of 1.


/---------------------\
< Wave Pattern Memory >
\---------------------/
This is the 16-byte long 'hidden' internal memory area (hereafter referred
to
as 'wave pattern memory'), containing the 32 4-bit samples for channel 3. It
can be written to by writing the 16-byte sample data into the wave pattern
load
register.

Channel 3 - Wave pattern load register - $FF30-$FF3F
----------------------------------------------
FOR EACH BYTE IN $FF30-$FF3F:
7-4 Sample 0
3-0 Sample 1

Setting the 'init' bit [bit 7] in $FF1E to 1 will slightly scramble the
contents at location $FF30-$FF3F, but the wave pattern memory will retain
the
proper values.
This area cannot be written to while channel 3's master control switch is
on.
UNVERIFIED: If it IS written to when the control is on, the written values
will
be ignored.
Sample playback is possible using this register, by turning off the switch
and
writing the next 16 4-bit samples, and turning it back on. However, doing
this
will create some click-distortion from the switch itself (especially on
DMGs),
and the first sample immediately after the switch is turned back on will be
replaced (due to capacitance somewhere or possibly a pointer pointing
somewhere
unexpected) by the last COMPLETELY played back (partially played doesn't
count)
sample before the switch was shut off. (Thanks Jeff Frohwein for a nice
image
demonstrating this)

UNVERIFIED: The 1-sample error is carried over to successive loops of the
wave pattern data.

On system power-on of the CGB, this internal area is loaded with:
(all hex)
00 FF 00 FF  00 FF 00 FF  00 FF 00 FF  00 FF 00 FF

On system power-on of the SGB (and SGB2?) this internal area is loaded with:
00 FF 00 FB  00 FF 00 FF  00 FF 00 FF  00 FF 00 FF

On system power-on of the DMG (and MGB???), the internal area isn't loaded
with any particular value, however due to some unusual properties of the
memory
in question, the values present will almost always be roughly the same.
The game "R-Type", due to a programming error, doesn't load this area with
anything, and therefore the initial value is played. When "R-Type" was
re-released for the GBC in "R-Type DX", Irem made a very good approximation
of
the DMG's initial Wave pattern memory values. Those values are:
0xac, 0xdd, 0xda, 0x48, 0x36, 0x02, 0xcf, 0x16,
0x2c, 0x04, 0xe5, 0x2c, 0xac, 0xdd, 0xda, 0x48

However on actual DMG hardware, the values are pretty much completely
random,
in a pattern unique to each Gameboy unit. By this I mean that, on a
particular
Gameboy, bits which start as 1 almost always start as 1, and bits which
start
as 0 almost always start as 0. There IS some variation, but the values are
roughly the same every time. It is sort of a 'Gameboy fingerprint'.

I dumped them 4 times from my DMG-005, the dumps are:
84 40 43 AA  2D 78 92 3C  60 59 59 B0  34 B8 2E DA
04 CA 02 EA  2D 7E 92 3C  60 59 59 BA  24 B8 2E DA
04 CA 42 AA  2D 78 92 3C  60 59 59 BA  34 B8 2E DA
15 CD 01 AA  0D 7F 92 BC  60 CB 19 BA  A0 BC 2E FE

I also dumped them 4 times from my DMG-006:
8C BC 04 73  0B 8E 35 F8  C9 B7 68 19  80 73 CC 88
8C BC 00 73  0B 8E 35 F8  C9 B7 68 19  80 73 C4 88
12 36 00 BB  08 CE 91 FE  01 BF 38 BB  88 F7 24 BB
8C B4 04 7B  0B 8E 25 FC  C9 B7 78 19  80 73 C4 88

One can easily see that though no two dumps are the same, they follow a
general
pattern, which seems to be unique to each Gameboy unit.


/--------------------------------------\
< Wave Pattern Playback / Shifter Unit >
\--------------------------------------/
This is effectively a 5-bit counter, which acts as a pointer to the current
4-bit sample in the 16-byte, 32-sample wave pattern memory. Every clock from
the programmable timer will cause a 4-bit sample (the wavepattern's
[high-4-bits-of-counter]st byte's high or low 4 bits [depending on whether
the
counter's low bit is 0 or 1, respectively]) to be sent to the volume shifter
unit. The volume shifter unit, depending on it's register, will output
either
0, the 4-bit sample, or the sample rightshifted by 1 or 2. This 4-bit result
is
then sent to the DAC.

Channel 3 - $FF1C(NR32)[wave]

This post has been edited by WolfCoder: 28 January 2006 - 07:51 PM

Was This Post Helpful? 1

#5 dec1pher  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 116
  • Joined: 27-January 06

Re: Gameboy Color Programming (GBDK)

Posted 29 January 2006 - 01:38 AM

nice work wolf. i'll (maybe) give a try to GB programming :). Retro and OldSkool rules!
Was This Post Helpful? 0
  • +
  • -

#6 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 789
  • View blog
  • Posts: 7,623
  • Joined: 05-May 05

Re: Gameboy Color Programming (GBDK)

Post icon  Posted 31 January 2006 - 08:27 PM

dec1pher, on 29 Jan, 2006 - 02:35 AM, said:

nice work wolf. i'll (maybe) give a try to GB programming :). Retro and OldSkool rules!

It's extremly direct programming. Forget DirectX and OpenGL, you simply write to registers to make stuff happen :) Now that it direct!
Was This Post Helpful? 0
  • +
  • -

#7 Julien1138  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 20-September 07

Re: Gameboy Color Programming (GBDK)

Posted 20 September 2007 - 05:18 AM

Hi !

I'm trying to compile with GBDK but it doesn't.
I'm working on Windows XP. Is that why it doesn't work ?

Thanks.
Was This Post Helpful? 0
  • +
  • -

#8 no2pencil  Icon User is online

  • Admiral Fancy Pants
  • member icon

Reputation: 5412
  • View blog
  • Posts: 27,429
  • Joined: 10-May 07

Re: Gameboy Color Programming (GBDK)

Posted 20 September 2007 - 06:50 AM

View PostWolfCoder, on 22 Jan, 2006 - 10:06 AM, said:

I have already programmed for the Gameboy Advance.

Would you mind sharing any documentation for Gameboy Advance?

This post has been edited by no2pencil: 20 September 2007 - 06:50 AM

Was This Post Helpful? 0
  • +
  • -

#9 Deadrose  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 22-August 07

Re: Gameboy Color Programming (GBDK)

Posted 22 September 2007 - 06:26 PM

Hey are u saying that u would teach meh C++ for free and on a online chat??? becasue if thats what ur saying i would love to learn C++. and if not it wont matter... So plz

E-mail me at lhumenik@zoominterbet.net

or i can make a AIM or MSN.... so just first e-mail meh if ur doing what i said above... Thank You Before hand
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1