Repository URL to install this package:
Version:
3.0.0 ▾
|
(*
$Id$
------------------------------------------------------------------------------
Header file for libgba bios sound functions
Copyright (C) 2003-2005 by Dave Murphy.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
Please report all bugs and problems through the bug tracker at
"http://sourceforge.net/tracker/?group_id=114505&atid=668551".
------------------------------------------------------------------------------
Conversion by Legolas (http://itaprogaming.free.fr) for freepascal compiler
(http://www.freepascal.org)
Copyright (C) 2006 Francesco Lombardi
Check http://sourceforge.net/projects/libndsfpc for updates
------------------------------------------------------------------------------
$Log$
*)
{$ifdef GBA_INTERFACE}
type
WaveData = record
typ: u16;
stat: u16;
freq: u32;
loop: u32;
size: u32;
data: array [0..0] of s8;
end;
PWaveData = ^WaveData;
SoundChannel = record
Status: u8;
reserved1: u8;
RightVol: u8;
LeftVol: u8;
Attack: u8;
Decay: u8;
Sustain: u8;
Release: u8;
reserved2: array [0..23] of u8;
fr: u32;
wp: PWaveData;
reserved3: array [0..5] of u32;
end;
PSoundChannel = ^SoundChannel;
const
PCM_DMA_BUF = 1584;
MAX_DIRECTSOUND_CHANNELS = 12;
type
SoundArea = record
ident: u32;
DmaCount: u8;
reverb: u8;
maxchn: u8;
masvol: u8;
freq: u8;
mode: u8;
r2: array [0..5] of u8;
r3: array [0..15] of u32;
vchn: array [0..MAX_DIRECTSOUND_CHANNELS-1] of SoundChannel;
pcmbuf: array [0..PCM_DMA_BUF*2 - 1] of s8;
end;
PSoundArea = ^SoundArea;
(*---------------------------------------------------------------------------------
Control Registers
---------------------------------------------------------------------------------*)
const
SND1_R_ENABLE = (1 shl 8); // Enable left & right speakers for each sound channel
SND1_L_ENABLE = (1 shl 12);
SND2_R_ENABLE = (1 shl 9);
SND2_L_ENABLE = (1 shl 13);
SND3_R_ENABLE = (1 shl 10);
SND3_L_ENABLE = (1 shl 14);
SND4_R_ENABLE = (1 shl 11);
SND4_L_ENABLE = (1 shl 15);
SNDA_VOL_50 = (0 shl 2);
SNDA_VOL_100 = (1 shl 2);
SNDB_VOL_50 = (0 shl 3);
SNDB_VOL_100 = (1 shl 3);
SNDA_R_ENABLE = (1 shl 8);
SNDA_L_ENABLE = (1 shl 9);
SNDA_RESET_FIFO = (1 shl 11);
SNDB_R_ENABLE = (1 shl 12);
SNDB_L_ENABLE = (1 shl 13);
SNDB_RESET_FIFO = (1 shl 15);
REG_SOUNDCNT_L : pu16 = pointer(REG_BASE + $080);
REG_SOUNDCNT_H : pu16 = pointer(REG_BASE + $082);
REG_SOUNDCNT_X : pu16 = pointer(REG_BASE + $084);
REG_SOUND1CNT_L : pu16 = pointer(REG_BASE + $060);
REG_SOUND1CNT_H : pu16 = pointer(REG_BASE + $062);
REG_SOUND1CNT_X : pu16 = pointer(REG_BASE + $064);
REG_SOUND2CNT_L : pu16 = pointer(REG_BASE + $068);
REG_SOUND2CNT_H : pu16 = pointer(REG_BASE + $06C);
REG_SOUND3CNT_L : pu16 = pointer(REG_BASE + $070);
REG_SOUND3CNT_H : pu16 = pointer(REG_BASE + $072);
REG_SOUND3CNT_X : pu16 = pointer(REG_BASE + $074);
REG_SOUND4CNT_L : pu16 = pointer(REG_BASE + $078);
REG_SOUND4CNT_H : pu16 = pointer(REG_BASE + $07C);
REG_SOUNDBIAS : pu16 = pointer(REG_BASE + $088);
REG_FIFO_A : pu32 = pointer(REG_BASE + $0A0);
REG_FIFO_B : pu32 = pointer(REG_BASE + $0A4);
WAVE_RAM : pu16 = pointer(REG_BASE + $090);
SOUND3_STEP32 = (0 shl 5); // Use two banks of 32 steps each
SOUND3_STEP64 = (1 shl 5); // Use one bank of 64 steps
function SOUND3_SETBANK(n: integer): integer; inline;
const
SOUND3_PLAY = (1 shl 7); // Output sound
SOUND3_STOP = (0 shl 7); // Stop sound output
//---------------------------------------------------------------------------------
// pin8 compatible sound macros
//---------------------------------------------------------------------------------
(*---------------------------------------------------------------------------------
DMG Sound Control (0x04000080)
fedcba9876543210
|||||||| ||| |||
|||||||| ||| +++- DMG left volume
|||||||| +++----- DMG right volume
|||||||+--------- Enable sqr1 on left
||||||+---------- Enable sqr2 on left
|||||+----------- Enable triangle on left
||||+------------ Enable noise on left
|||+------------- Enable sqr1 on right
||+-------------- Enable sqr2 on right
|+--------------- Enable triangle on right
+----------------
---------------------------------------------------------------------------------*)
const
DMGSNDCTRL : pu16 = pointer($04000080);
function DMGSNDCTRL_LVOL(x: integer): integer; inline;
function DMGSNDCTRL_RVOL(x: integer): integer; inline;
const
DMGSNDCTRL_LSQR1 = $0100;
DMGSNDCTRL_LSQR2 = $0200;
DMGSNDCTRL_LTRI = $0400;
DMGSNTCTRL_LNOISE = $0800;
DMGSNDCTRL_RSQR1 = $1000;
DMGSNDCTRL_RSQR2 = $2000;
DMGSNDCTRL_RTRI = $4000;
DMGSNDCTRL_RNOISE = $8000;
(*---------------------------------------------------------------------------------
Direct Sound Control (0x04000082)
-----------------------------------------------------------------------------------
fedcba9876543210
|||||||| ||||
|||||||| ||++- DMG sound output volume
|||||||| || (00: 25%; 01: 50%; 10: 100%)
|||||||| |+--- DSound A output volume (0: 50%; 1: 100%)
|||||||| +---- DSound B output volume (0: 50%; 1: 100%)
|||||||+--------- Enable DSound A on right
||||||+---------- Enable DSound A on left
|||||+----------- DSound A sample timer (0 or 1)
||||+------------ DSound A FIFO reset
|||+------------- Enable DSound B on right
||+-------------- Enable DSound B on left
|+--------------- DSound B sample timer (0 or 1)
+---------------- DSound B FIFO reset
---------------------------------------------------------------------------------*)
const
DSOUNDCTRL : pu16 = pointer($04000082);
DSOUNDCTRL_DMG25 = $0000;
DSOUNDCTRL_DMG50 = $0001;
DSOUNDCTRL_DMG100 = $0002;
DSOUNDCTRL_A50 = $0000;
DSOUNDCTRL_A100 = $0004;
DSOUNDCTRL_B50 = $0000;
DSOUNDCTRL_B100 = $0008;
DSOUNDCTRL_AR = $0100;
DSOUNDCTRL_AL = $0200;
function DSOUNDCTRL_ATIMER(x: integer): integer; inline;
const
DSOUNDCTRL_ARESET = $0400;
DSOUNDCTRL_BR = $1000;
DSOUNDCTRL_BL = $2000;
function DSOUNDCTRL_BTIMER(x: integer): integer; inline;
const
DSOUNDCTRL_BRESET = $8000;
(*---------------------------------------------------------------------------------
Sound Status (0x04000084)
-----------------------------------------------------------------------------------
Note that unlike NES's $4014, bits 0 to 3 of this register are
read-only. They do not enable sound.
fedcba9876543210
| ||||
| |||+- Square 1 playing
| ||+-- Square 2 playing
| |+--- Triangle playing
| +---- Noise playing
+-------- 0: save 10% battery power by turning off ALL sound;
1: play sound
---------------------------------------------------------------------------------*)
const
SNDSTAT : pu16 = pointer($04000084);
SNDSTAT_SQR1 = $0001;
SNDSTAT_SQR2 = $0002;
SNDSTAT_TRI = $0004;
SNDSTAT_NOISE = $0008;
SNDSTAT_ENABLE = $0080;
(*---------------------------------------------------------------------------------
Sound Bias: will not be documented.
-----------------------------------------------------------------------------------
fedcba9876543210
|| ||||||||||
|| ++++++++++- PWM bias
++--------------- Amplitude resolution
00: 9-bit at 32768 Hz
01: 8-bit at 65536 Hz (most common)
10: 7-bit at 131072 Hz
11: 6-bit at 262144 Hz
Do NOT use SNDBIAS directly. To set the resolution, use
SETSNDRES(1);
---------------------------------------------------------------------------------*)
const
SNDBIAS : pu16 = pointer($04000088);
procedure SETSNDRES(x: integer); inline;
const
DSOUND_FIFOA : pu32 = pointer($040000a0);
DSOUND_FIFOB : pu32 = pointer($040000a4);
(*---------------------------------------------------------------------------------
Square 1 Sweep Register
---------------------------------------------------------------------------------
fedcba9876543210
|||||||
||||+++- Sweep shifts (1 fastest; 7 slowest)
|||+---- 0: Sweep up; 1: Sweep down
Write 0x0040 into this register to disable sweep.
---------------------------------------------------------------------------------*)
const
SQR1SWEEP : pu16 = pointer($04000060);
SQR1SWEEP_OFF = $0008;
(*---------------------------------------------------------------------------------
Square 1 Control Register
Square 2 Control Register
-----------------------------------------------------------------------------------
fedcba9876543210
||||||||||||||||
||||||||||++++++- Sound length (1 longest; 63: shortest)
||||||||++------- Duty cycle (00: 1/8; 01: 1/4; 10: 1/2; 11: 3/4)
|||||+++--------- Envelope step time (0: off; 1 fastest; 7 slowest)
||||+------------ Envelope direction (0: decrease; 1: increase)
++++------------- Volume
---------------------------------------------------------------------------------*)
const
SQR1CTRL : pu16 = pointer($04000062);
SQR2CTRL : pu16 = pointer($04000068);
function SQR_DUTY(n: integer): integer; inline;
function SQR_VOL(n: integer): integer; inline;
(*---------------------------------------------------------------------------------
Square 1 Frequency
Square 2 Frequency
Triangle Channel Frequency (0x04000074)
-----------------------------------------------------------------------------------
fedcba9876543210
|| |||||||||||
|| +++++++++++- frequency (131072 Hz/(2048-x)) (halved for tri channel)
|+--------------- 0: hold note; 1: use length
+---------------- 1: Reset channel
---------------------------------------------------------------------------------*)
const
SQR1FREQ : pu16 = pointer($04000064);
SQR2FREQ : pu16 = pointer($0400006c);
TRIFREQ : pu16 = pointer($04000074);
TRIFREQ_HOLD = $0000;
TRIFREQ_TIMED = $4000;
TRIFREQ_RESET = $8000;
(*---------------------------------------------------------------------------------
Triangle Channel Control Register
-----------------------------------------------------------------------------------
fedcba9876543210
|||
||+------ Bank mode (0: 2 banks of 32; 1: 1 bank of 64)
|+------- Play this bank (and write other bank)
+-------- Enable triangle channel
---------------------------------------------------------------------------------*)
const
TRICTRL : pu16 = pointer($04000070);
TRICTRL_2X32 = $0000;
TRICTRL_1X64 = $0020;
function TRICTRL_BANK(x: integer): integer; inline;
const
TRICTRL_ENABLE = $0080;
(*---------------------------------------------------------------------------------
Triangle Channel Length/Volume (0x04000072)
-----------------------------------------------------------------------------------
fedcba9876543210
||| ||||||||
||| ++++++++- Length ((256-x)/256 seconds)
+++-------------- Volume (000: mute; 001: 100%; 010: 50%;
011: 25%; 100: 75%)
---------------------------------------------------------------------------------*)
const
TRILENVOL :pu16 = pointer($04000072);
function TRILENVOL_LEN(x: integer): integer; inline;
const
TRILENVOL_MUTE = $0000;
TRILENVOL_25 = $6000;
TRILENVOL_50 = $4000;
TRILENVOL_75 = $8000;
TRILENVOL_100 = $2000;
TRIWAVERAM : pu32 = pointer($04000090);
//---------------------------------------------------------------------------------
// Bios sound functions
//---------------------------------------------------------------------------------
procedure SoundDriverMain(); assembler; inline;
procedure SoundDriverVsync(); assembler; inline;
procedure SoundChannelClear(); assembler; inline;
procedure SoundDriverVsyncOff(); assembler; inline;
procedure SoundDriverVsyncOn(); assembler; inline;
procedure SoundDriverInit(sa: PSoundArea); cdecl; external;
procedure SoundDriverMode(mode: u32); cdecl; external;
function MidiKey2Freq(wa: PWaveData; mk, fp: u8): u32; cdecl; external;
{$endif GBA_INTERFACE}
{$ifdef GBA_IMPLEMENTATION}
function SOUND3_SETBANK(n: integer): integer; inline;
begin
SOUND3_SETBANK := (n shl 6); // Bank to play 0 or 1 (non set bank is written to)
end;
function DMGSNDCTRL_LVOL(x: integer): integer; inline;
begin
DMGSNDCTRL_LVOL := (x);
end;
function DMGSNDCTRL_RVOL(x: integer): integer; inline;
begin
DMGSNDCTRL_RVOL := ((x) shl 4);
end;
function DSOUNDCTRL_ATIMER(x: integer): integer; inline;
begin
DSOUNDCTRL_ATIMER := ((x) shl 10);
end;
function DSOUNDCTRL_BTIMER(x: integer): integer; inline;
begin
DSOUNDCTRL_BTIMER := ((x) shl 14);
end;
procedure SETSNDRES(x: integer); inline;
begin
SNDBIAS^ := (SNDBIAS^ and $3fff) or (x shl 14);
end;
function SQR_DUTY(n: integer): integer; inline;
begin
SQR_DUTY := ((n) shl 6);
end;
function SQR_VOL(n: integer): integer; inline;
begin
SQR_VOL := ((n) shl 12);
end;
function TRICTRL_BANK(x: integer): integer; inline;
begin
TRICTRL_BANK := ((x) shl 6);
end;
function TRILENVOL_LEN(x: integer): integer; inline;
begin
TRILENVOL_LEN := (256 - (x));
end;
procedure SoundDriverMain(); assembler; inline;
asm
SWI SC_ARM_28
end;
procedure SoundDriverVsync(); assembler; inline;
asm
SWI SC_ARM_29
end;
procedure SoundChannelClear(); assembler; inline;
asm
SWI SC_ARM_30
end;
procedure SoundDriverVsyncOff(); assembler; inline;
asm
SWI SC_ARM_40
end;
procedure SoundDriverVsyncOn(); assembler; inline;
asm
SWI SC_ARM_41
end;
{$endif GBA_IMPLEMENTATION}