diff options
author | Karl Kurbjun <kkurbjun@gmail.com> | 2007-07-21 04:00:58 +0000 |
---|---|---|
committer | Karl Kurbjun <kkurbjun@gmail.com> | 2007-07-21 04:00:58 +0000 |
commit | fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413 (patch) | |
tree | 6f7a0f73c8bf25ced6286614e01af7983b59070a | |
parent | e9c09d4d0e1170c6c81991c2660608854d960a77 (diff) | |
download | rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.tar.gz rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.zip |
Commit FS #7379 - This patch fixes most of the sound problems from the previous version. This is a complete rewrite of VisualBoyAdvance's sound code from C++ to C. This patch also eliminates the need for some large tables giving more room in IRAM and the plugin buffer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13947 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/rockboy/mem.c | 7 | ||||
-rw-r--r-- | apps/plugins/rockboy/mem.h | 1 | ||||
-rw-r--r-- | apps/plugins/rockboy/rbsound.c | 13 | ||||
-rw-r--r-- | apps/plugins/rockboy/rockmacros.h | 1 | ||||
-rw-r--r-- | apps/plugins/rockboy/save.c | 22 | ||||
-rw-r--r-- | apps/plugins/rockboy/sound.c | 954 | ||||
-rw-r--r-- | apps/plugins/rockboy/sound.h | 36 |
7 files changed, 688 insertions, 346 deletions
diff --git a/apps/plugins/rockboy/mem.c b/apps/plugins/rockboy/mem.c index 8c0bea0b83..6811fd5f81 100644 --- a/apps/plugins/rockboy/mem.c +++ b/apps/plugins/rockboy/mem.c | |||
@@ -562,10 +562,3 @@ void mbc_reset(void) | |||
562 | mbc.enableram = 0; | 562 | mbc.enableram = 0; |
563 | mem_updatemap(); | 563 | mem_updatemap(); |
564 | } | 564 | } |
565 | |||
566 | |||
567 | |||
568 | |||
569 | |||
570 | |||
571 | |||
diff --git a/apps/plugins/rockboy/mem.h b/apps/plugins/rockboy/mem.h index 005c495f31..338fd98bf0 100644 --- a/apps/plugins/rockboy/mem.h +++ b/apps/plugins/rockboy/mem.h | |||
@@ -41,7 +41,6 @@ struct ram | |||
41 | int loaded; | 41 | int loaded; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | |||
45 | extern struct mbc mbc; | 44 | extern struct mbc mbc; |
46 | extern struct rom rom; | 45 | extern struct rom rom; |
47 | extern struct ram ram; | 46 | extern struct ram ram; |
diff --git a/apps/plugins/rockboy/rbsound.c b/apps/plugins/rockboy/rbsound.c index fe2c27af67..b5cfc96fa4 100644 --- a/apps/plugins/rockboy/rbsound.c +++ b/apps/plugins/rockboy/rbsound.c | |||
@@ -12,13 +12,14 @@ struct pcm pcm IBSS_ATTR; | |||
12 | bool doneplay=1; | 12 | bool doneplay=1; |
13 | bool bufnum=0; | 13 | bool bufnum=0; |
14 | 14 | ||
15 | static unsigned short *buf=0; | 15 | static unsigned short *buf=0, *hwbuf=0; |
16 | 16 | ||
17 | static bool newly_started; | 17 | static bool newly_started; |
18 | 18 | ||
19 | void get_more(unsigned char** start, size_t* size) | 19 | void get_more(unsigned char** start, size_t* size) |
20 | { | 20 | { |
21 | *start = (unsigned char*)(&buf[pcm.len*doneplay]); | 21 | memcpy(hwbuf, &buf[pcm.len*doneplay], BUF_SIZE*sizeof(short)); |
22 | *start = (unsigned char*)(hwbuf); | ||
22 | *size = BUF_SIZE*sizeof(short); | 23 | *size = BUF_SIZE*sizeof(short); |
23 | doneplay=1; | 24 | doneplay=1; |
24 | } | 25 | } |
@@ -29,14 +30,20 @@ void pcm_init(void) | |||
29 | return; | 30 | return; |
30 | 31 | ||
31 | newly_started = true; | 32 | newly_started = true; |
32 | 33 | ||
34 | #if defined(HW_HAVE_11) && !defined(TOSHIBA_GIGABEAT_F) | ||
35 | pcm.hz = SAMPR_11; | ||
36 | #else | ||
33 | pcm.hz = SAMPR_44; | 37 | pcm.hz = SAMPR_44; |
38 | #endif | ||
39 | |||
34 | pcm.stereo = 1; | 40 | pcm.stereo = 1; |
35 | 41 | ||
36 | pcm.len = BUF_SIZE; | 42 | pcm.len = BUF_SIZE; |
37 | if(!buf) | 43 | if(!buf) |
38 | { | 44 | { |
39 | buf = my_malloc(pcm.len * N_BUFS *sizeof(short)); | 45 | buf = my_malloc(pcm.len * N_BUFS *sizeof(short)); |
46 | hwbuf = my_malloc(pcm.len *sizeof(short)); | ||
40 | 47 | ||
41 | pcm.buf = buf; | 48 | pcm.buf = buf; |
42 | pcm.pos = 0; | 49 | pcm.pos = 0; |
diff --git a/apps/plugins/rockboy/rockmacros.h b/apps/plugins/rockboy/rockmacros.h index 5d60d3f3e3..f5223b01df 100644 --- a/apps/plugins/rockboy/rockmacros.h +++ b/apps/plugins/rockboy/rockmacros.h | |||
@@ -35,7 +35,6 @@ void *sys_timer(void); | |||
35 | int sys_elapsed(long *oldtick); | 35 | int sys_elapsed(long *oldtick); |
36 | int pcm_submit(void); | 36 | int pcm_submit(void); |
37 | void pcm_init(void); | 37 | void pcm_init(void); |
38 | void sound_dirty(void); | ||
39 | void doevents(void) ICODE_ATTR; | 38 | void doevents(void) ICODE_ATTR; |
40 | void ev_poll(void); | 39 | void ev_poll(void); |
41 | int do_user_menu(void); | 40 | int do_user_menu(void); |
diff --git a/apps/plugins/rockboy/save.c b/apps/plugins/rockboy/save.c index 794579d8fa..3f6c179beb 100644 --- a/apps/plugins/rockboy/save.c +++ b/apps/plugins/rockboy/save.c | |||
@@ -89,24 +89,24 @@ struct svar svars[] = | |||
89 | 89 | ||
90 | I4("S1on", &snd.ch[0].on), | 90 | I4("S1on", &snd.ch[0].on), |
91 | I4("S1p ", &snd.ch[0].pos), | 91 | I4("S1p ", &snd.ch[0].pos), |
92 | I4("S1c ", &snd.ch[0].cnt), | 92 | I4("S1c ", &snd.ch[0].len), |
93 | I4("S1ec", &snd.ch[0].encnt), | 93 | I4("S1ec", &snd.ch[0].enlen), |
94 | I4("S1sc", &snd.ch[0].swcnt), | 94 | I4("S1sc", &snd.ch[0].swlen), |
95 | 95 | ||
96 | I4("S2on", &snd.ch[1].on), | 96 | I4("S2on", &snd.ch[1].on), |
97 | I4("S2p ", &snd.ch[1].pos), | 97 | I4("S2p ", &snd.ch[1].pos), |
98 | I4("S2c ", &snd.ch[1].cnt), | 98 | I4("S2c ", &snd.ch[1].len), |
99 | I4("S2ec", &snd.ch[1].encnt), | 99 | I4("S2ec", &snd.ch[1].enlen), |
100 | 100 | ||
101 | I4("S3on", &snd.ch[2].on), | 101 | I4("S3on", &snd.ch[2].on), |
102 | I4("S3p ", &snd.ch[2].pos), | 102 | I4("S3p ", &snd.ch[2].pos), |
103 | I4("S3c ", &snd.ch[2].cnt), | 103 | I4("S3c ", &snd.ch[2].len), |
104 | 104 | ||
105 | I4("S4on", &snd.ch[3].on), | 105 | I4("S4on", &snd.ch[3].on), |
106 | I4("S4p ", &snd.ch[3].pos), | 106 | I4("S4p ", &snd.ch[3].pos), |
107 | I4("S4c ", &snd.ch[3].cnt), | 107 | I4("S4c ", &snd.ch[3].len), |
108 | I4("S4ec", &snd.ch[3].encnt), | 108 | I4("S4ec", &snd.ch[3].enlen), |
109 | 109 | ||
110 | I4("hdma", &hw.hdma), | 110 | I4("hdma", &hw.hdma), |
111 | 111 | ||
112 | I4("sram", &sramblock), | 112 | I4("sram", &sramblock), |
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c index aba7f924b4..036a05a058 100644 --- a/apps/plugins/rockboy/sound.c +++ b/apps/plugins/rockboy/sound.c | |||
@@ -1,3 +1,30 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * The following code is rewrite of the C++ code provided in VisualBoyAdvance. | ||
11 | * There are also portions of the original GNUboy code. | ||
12 | * Copyright (C) 2001 the GNUboy development team | ||
13 | * | ||
14 | * VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. | ||
15 | * Copyright (C) 1999-2003 Forgotten | ||
16 | * Copyright (C) 2004 Forgotten and the VBA development team | ||
17 | * | ||
18 | * VisualBoyAdvance conversion from C++ to C by Karl Kurbjun July, 2007 | ||
19 | * | ||
20 | * All files in this archive are subject to the GNU General Public License. | ||
21 | * See the file COPYING in the source tree root for full license agreement. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | */ | ||
27 | |||
1 | #include "rockmacros.h" | 28 | #include "rockmacros.h" |
2 | #include "defs.h" | 29 | #include "defs.h" |
3 | #include "pcm.h" | 30 | #include "pcm.h" |
@@ -5,31 +32,71 @@ | |||
5 | #include "cpu-gb.h" | 32 | #include "cpu-gb.h" |
6 | #include "hw.h" | 33 | #include "hw.h" |
7 | #include "regs.h" | 34 | #include "regs.h" |
8 | #include "noise.h" | ||
9 | |||
10 | static const byte dmgwave[16] = | ||
11 | { | ||
12 | 0xac, 0xdd, 0xda, 0x48, | ||
13 | 0x36, 0x02, 0xcf, 0x16, | ||
14 | 0x2c, 0x04, 0xe5, 0x2c, | ||
15 | 0xac, 0xdd, 0xda, 0x48 | ||
16 | }; | ||
17 | 35 | ||
18 | static const byte cgbwave[16] = | 36 | static const byte soundWavePattern[4][32] = { |
19 | { | 37 | {0x01,0x01,0x01,0x01, |
20 | 0x00, 0xff, 0x00, 0xff, | 38 | 0xff,0xff,0xff,0xff, |
21 | 0x00, 0xff, 0x00, 0xff, | 39 | 0xff,0xff,0xff,0xff, |
22 | 0x00, 0xff, 0x00, 0xff, | 40 | 0xff,0xff,0xff,0xff, |
23 | 0x00, 0xff, 0x00, 0xff, | 41 | 0xff,0xff,0xff,0xff, |
24 | }; | 42 | 0xff,0xff,0xff,0xff, |
25 | 43 | 0xff,0xff,0xff,0xff, | |
26 | static const byte sqwave[4][8] = | 44 | 0xff,0xff,0xff,0xff}, |
27 | { | 45 | {0x01,0x01,0x01,0x01, |
28 | { 0, 0,-1, 0, 0, 0, 0, 0 }, | 46 | 0x01,0x01,0x01,0x01, |
29 | { 0,-1,-1, 0, 0, 0, 0, 0 }, | 47 | 0xff,0xff,0xff,0xff, |
30 | { -1,-1,-1,-1, 0, 0, 0, 0 }, | 48 | 0xff,0xff,0xff,0xff, |
31 | { -1, 0, 0,-1,-1,-1,-1,-1 } | 49 | 0xff,0xff,0xff,0xff, |
32 | }; | 50 | 0xff,0xff,0xff,0xff, |
51 | 0xff,0xff,0xff,0xff, | ||
52 | 0xff,0xff,0xff,0xff}, | ||
53 | {0x01,0x01,0x01,0x01, | ||
54 | 0x01,0x01,0x01,0x01, | ||
55 | 0x01,0x01,0x01,0x01, | ||
56 | 0x01,0x01,0x01,0x01, | ||
57 | 0xff,0xff,0xff,0xff, | ||
58 | 0xff,0xff,0xff,0xff, | ||
59 | 0xff,0xff,0xff,0xff, | ||
60 | 0xff,0xff,0xff,0xff}, | ||
61 | {0x01,0x01,0x01,0x01, | ||
62 | 0x01,0x01,0x01,0x01, | ||
63 | 0x01,0x01,0x01,0x01, | ||
64 | 0x01,0x01,0x01,0x01, | ||
65 | 0x01,0x01,0x01,0x01, | ||
66 | 0x01,0x01,0x01,0x01, | ||
67 | 0xff,0xff,0xff,0xff, | ||
68 | 0xff,0xff,0xff,0xff} | ||
69 | } ICONST_ATTR; | ||
70 | |||
71 | int soundFreqRatio[8] = { | ||
72 | 1048576, // 0 | ||
73 | 524288, // 1 | ||
74 | 262144, // 2 | ||
75 | 174763, // 3 | ||
76 | 131072, // 4 | ||
77 | 104858, // 5 | ||
78 | 87381, // 6 | ||
79 | 74898 // 7 | ||
80 | } ICONST_ATTR; | ||
81 | |||
82 | int soundShiftClock[16]= { | ||
83 | 2, // 0 | ||
84 | 4, // 1 | ||
85 | 8, // 2 | ||
86 | 16, // 3 | ||
87 | 32, // 4 | ||
88 | 64, // 5 | ||
89 | 128, // 6 | ||
90 | 256, // 7 | ||
91 | 512, // 8 | ||
92 | 1024, // 9 | ||
93 | 2048, // 10 | ||
94 | 4096, // 11 | ||
95 | 8192, // 12 | ||
96 | 16384, // 13 | ||
97 | 1, // 14 | ||
98 | 1 // 15 | ||
99 | } ICONST_ATTR; | ||
33 | 100 | ||
34 | static const int freqtab[8] = | 101 | static const int freqtab[8] = |
35 | { | 102 | { |
@@ -41,7 +108,7 @@ static const int freqtab[8] = | |||
41 | (1<<14)/5, | 108 | (1<<14)/5, |
42 | (1<<14)/6, | 109 | (1<<14)/6, |
43 | (1<<14)/7 | 110 | (1<<14)/7 |
44 | }; | 111 | } ICONST_ATTR; |
45 | 112 | ||
46 | struct snd snd IBSS_ATTR; | 113 | struct snd snd IBSS_ATTR; |
47 | 114 | ||
@@ -52,209 +119,315 @@ struct snd snd IBSS_ATTR; | |||
52 | #define S3 (snd.ch[2]) | 119 | #define S3 (snd.ch[2]) |
53 | #define S4 (snd.ch[3]) | 120 | #define S4 (snd.ch[3]) |
54 | 121 | ||
55 | static void s1_freq_d(int d) | 122 | #define SOUND_MAGIC 0x60000000 |
56 | { | 123 | #define SOUND_MAGIC_2 0x30000000 |
57 | if (RATE > (d<<4)) S1.freq = 0; | 124 | #define NOISE_MAGIC 5 |
58 | else S1.freq = (RATE << 17)/d; | ||
59 | } | ||
60 | |||
61 | static void s1_freq(void) | ||
62 | { | ||
63 | s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13)); | ||
64 | } | ||
65 | |||
66 | static void s2_freq(void) | ||
67 | { | ||
68 | int d = 2048 - (((R_NR24&7)<<8) + R_NR23); | ||
69 | if (RATE > (d<<4)) S2.freq = 0; | ||
70 | else S2.freq = (RATE << 17)/d; | ||
71 | } | ||
72 | |||
73 | static void s3_freq(void) | ||
74 | { | ||
75 | int d = 2048 - (((R_NR34&7)<<8) + R_NR33); | ||
76 | if (RATE > (d<<3)) S3.freq = 0; | ||
77 | else S3.freq = (RATE << 21)/d; | ||
78 | } | ||
79 | 125 | ||
80 | static void s4_freq(void) | 126 | static void gbSoundChannel1(int *r, int *l) |
81 | { | 127 | { |
82 | S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE; | 128 | int vol = S1.envol; |
83 | if (S4.freq >> 18) S4.freq = 1<<18; | ||
84 | } | ||
85 | 129 | ||
86 | void sound_dirty(void) | 130 | int freq = 0; |
87 | { | ||
88 | S1.swlen = ((R_NR10>>4) & 7) << 14; | ||
89 | S1.len = (64-(R_NR11&63)) << 13; | ||
90 | S1.envol = R_NR12 >> 4; | ||
91 | S1.endir = (R_NR12>>3) & 1; | ||
92 | S1.endir |= S1.endir - 1; | ||
93 | S1.enlen = (R_NR12 & 7) << 15; | ||
94 | s1_freq(); | ||
95 | S2.len = (64-(R_NR21&63)) << 13; | ||
96 | S2.envol = R_NR22 >> 4; | ||
97 | S2.endir = (R_NR22>>3) & 1; | ||
98 | S2.endir |= S2.endir - 1; | ||
99 | S2.enlen = (R_NR22 & 7) << 15; | ||
100 | s2_freq(); | ||
101 | S3.len = (256-R_NR31) << 20; | ||
102 | s3_freq(); | ||
103 | S4.len = (64-(R_NR41&63)) << 13; | ||
104 | S4.envol = R_NR42 >> 4; | ||
105 | S4.endir = (R_NR42>>3) & 1; | ||
106 | S4.endir |= S4.endir - 1; | ||
107 | S4.enlen = (R_NR42 & 7) << 15; | ||
108 | s4_freq(); | ||
109 | } | ||
110 | 131 | ||
111 | void sound_off(void) | 132 | int value = 0; |
112 | { | ||
113 | memset(&snd, 0, sizeof snd); | ||
114 | if (pcm.hz) snd.rate = (1<<21) / pcm.hz; | ||
115 | else snd.rate = 0; | ||
116 | R_NR10 = 0x80; | ||
117 | R_NR11 = 0xBF; | ||
118 | R_NR12 = 0xF3; | ||
119 | R_NR14 = 0xBF; | ||
120 | R_NR21 = 0x3F; | ||
121 | R_NR22 = 0x00; | ||
122 | R_NR24 = 0xBF; | ||
123 | R_NR30 = 0x7F; | ||
124 | R_NR31 = 0xFF; | ||
125 | R_NR32 = 0x9F; | ||
126 | R_NR34 = 0xBF; | ||
127 | R_NR41 = 0xFF; | ||
128 | R_NR42 = 0x00; | ||
129 | R_NR43 = 0x00; | ||
130 | R_NR44 = 0xBF; | ||
131 | R_NR50 = 0x77; | ||
132 | R_NR51 = 0xF3; | ||
133 | R_NR52 = 0x70; | ||
134 | // for (i = 0; i < 16; i++) WAVE[i] = -(i&1); | ||
135 | sound_dirty(); | ||
136 | } | ||
137 | 133 | ||
138 | void sound_reset() | 134 | if(S1.on && (S1.len || !S1.cont)) |
139 | { | 135 | { |
140 | memset(&snd, 0, sizeof snd); | 136 | S1.pos += snd.quality*S1.skip; |
141 | if (pcm.hz) snd.rate = (1<<21) / pcm.hz; | 137 | S1.pos &= 0x1fffffff; |
142 | else snd.rate = 0; | ||
143 | memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16); | ||
144 | memcpy(ram.hi+0x30, WAVE, 16); | ||
145 | sound_off(); | ||
146 | R_NR52 = 0xF1; | ||
147 | } | ||
148 | 138 | ||
149 | void sound_mix(void) | 139 | value = ((signed char)S1.wave[S1.pos>>24]) * vol; |
150 | { | 140 | } |
151 | int s, l, r, f, n; | ||
152 | 141 | ||
153 | if (!RATE || cpu.snd < RATE) return; | 142 | if (snd.balance & 1) *r += value; |
143 | if (snd.balance & 16) *l += value; | ||
154 | 144 | ||
155 | for (; cpu.snd >= RATE; cpu.snd -= RATE) | 145 | if(S1.on) |
156 | { | 146 | { |
157 | l = r = 0; | 147 | if(S1.len) |
158 | |||
159 | if (S1.on) | ||
160 | { | 148 | { |
161 | s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol; | 149 | S1.len-=snd.quality; |
162 | S1.pos += S1.freq; | 150 | |
163 | if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len)) | 151 | if(S1.len <=0 && S1.cont) |
152 | { | ||
153 | R_NR52 &= 0xfe; | ||
164 | S1.on = 0; | 154 | S1.on = 0; |
165 | if (S1.enlen && (S1.encnt += RATE) >= S1.enlen) | 155 | } |
156 | } | ||
157 | |||
158 | if(S1.enlen) | ||
159 | { | ||
160 | S1.enlen-=snd.quality; | ||
161 | |||
162 | if(S1.enlen<=0) | ||
166 | { | 163 | { |
167 | S1.encnt -= S1.enlen; | 164 | if(S1.endir) |
168 | S1.envol += S1.endir; | 165 | { |
169 | if (S1.envol < 0) S1.envol = 0; | 166 | if(S1.envol < 15) |
170 | if (S1.envol > 15) S1.envol = 15; | 167 | S1.envol++; |
168 | } | ||
169 | else | ||
170 | { | ||
171 | if(S1.envol) | ||
172 | S1.envol--; | ||
173 | } | ||
174 | |||
175 | S1.enlen += S1.enlenreload; | ||
171 | } | 176 | } |
172 | if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen) | 177 | } |
178 | |||
179 | if(S1.swlen) | ||
180 | { | ||
181 | S1.swlen-=snd.quality; | ||
182 | |||
183 | if(S1.swlen<=0) | ||
173 | { | 184 | { |
174 | S1.swcnt -= S1.swlen; | 185 | freq = (((int)(R_NR14&7) << 8) | R_NR13); |
175 | f = S1.swfreq; | 186 | |
176 | n = (R_NR10 & 7); | 187 | int updown = 1; |
177 | if (R_NR10 & 8) f -= (f >> n); | 188 | |
178 | else f += (f >> n); | 189 | if(S1.swdir) |
179 | if (f > 2047) | 190 | updown = -1; |
180 | S1.on = 0; | 191 | |
192 | int newfreq = 0; | ||
193 | if(S1.swsteps) | ||
194 | { | ||
195 | newfreq = freq + updown * freq / (1 << S1.swsteps); | ||
196 | if(newfreq == freq) | ||
197 | newfreq = 0; | ||
198 | } | ||
181 | else | 199 | else |
200 | newfreq = freq; | ||
201 | |||
202 | if(newfreq < 0) | ||
182 | { | 203 | { |
183 | S1.swfreq = f; | 204 | S1.swlen += S1.swlenreload; |
184 | R_NR13 = f; | 205 | } |
185 | R_NR14 = (R_NR14 & 0xF8) | (f>>8); | 206 | else if(newfreq > 2047) |
186 | s1_freq_d(2048 - f); | 207 | { |
208 | S1.swlen = 0; | ||
209 | S1.on = 0; | ||
210 | R_NR52 &= 0xfe; | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | S1.swlen += S1.swlenreload; | ||
215 | S1.skip = SOUND_MAGIC/(2048 - newfreq); | ||
216 | |||
217 | R_NR13 = newfreq & 0xff; | ||
218 | R_NR14 = (R_NR14 & 0xf8) |((newfreq >> 8) & 7); | ||
187 | } | 219 | } |
188 | } | 220 | } |
189 | s <<= 2; | ||
190 | if (R_NR51 & 1) r += s; | ||
191 | if (R_NR51 & 16) l += s; | ||
192 | } | 221 | } |
222 | } | ||
223 | } | ||
193 | 224 | ||
194 | if (S2.on) | 225 | static void gbSoundChannel2(int *r, int *l) |
195 | { | 226 | { |
196 | s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol; | 227 | int vol = S2.envol; |
197 | S2.pos += S2.freq; | 228 | |
198 | if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len)) | 229 | int value = 0; |
230 | |||
231 | if(S2.on && (S2.len || !S2.cont)) | ||
232 | { | ||
233 | S2.pos += snd.quality*S2.skip; | ||
234 | S2.pos &= 0x1fffffff; | ||
235 | |||
236 | value = ((signed char)S2.wave[S2.pos>>24]) * vol; | ||
237 | } | ||
238 | |||
239 | if (snd.balance & 2) *r += value; | ||
240 | if (snd.balance & 32) *l += value; | ||
241 | |||
242 | if(S2.on) { | ||
243 | if(S2.len) { | ||
244 | S2.len-=snd.quality; | ||
245 | |||
246 | if(S2.len <= 0 && S2.cont) { | ||
247 | R_NR52 &= 0xfd; | ||
199 | S2.on = 0; | 248 | S2.on = 0; |
200 | if (S2.enlen && (S2.encnt += RATE) >= S2.enlen) | ||
201 | { | ||
202 | S2.encnt -= S2.enlen; | ||
203 | S2.envol += S2.endir; | ||
204 | if (S2.envol < 0) S2.envol = 0; | ||
205 | if (S2.envol > 15) S2.envol = 15; | ||
206 | } | 249 | } |
207 | s <<= 2; | ||
208 | if (R_NR51 & 2) r += s; | ||
209 | if (R_NR51 & 32) l += s; | ||
210 | } | 250 | } |
251 | |||
252 | if(S2.enlen) { | ||
253 | S2.enlen-=snd.quality; | ||
254 | |||
255 | if(S2.enlen <= 0) { | ||
256 | if(S2.endir) { | ||
257 | if(S2.envol < 15) | ||
258 | S2.envol++; | ||
259 | } else { | ||
260 | if(S2.envol) | ||
261 | S2.envol--; | ||
262 | } | ||
263 | S2.enlen += S2.enlenreload; | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | |||
269 | static void gbSoundChannel3(int *r, int *l) | ||
270 | { | ||
271 | int s; | ||
272 | if (S3.on && (S3.len || !S3.cont)) | ||
273 | { | ||
274 | S3.pos += S3.skip*snd.quality; | ||
275 | S3.pos &= 0x1fffffff; | ||
276 | s=ram.hi[0x30 + (S3.pos>>25)]; | ||
277 | if (S3.pos & 0x01000000) | ||
278 | s &= 0x0f; | ||
279 | else | ||
280 | s >>= 4; | ||
281 | |||
282 | s -= 8; | ||
211 | 283 | ||
212 | if (S3.on) | 284 | switch(S3.outputlevel) |
213 | { | 285 | { |
214 | s = WAVE[(S3.pos>>22) & 15]; | 286 | case 0: |
215 | if (S3.pos & (1<<21)) s &= 15; | 287 | s=0; |
216 | else s >>= 4; | 288 | break; |
217 | s -= 8; | 289 | case 1: |
218 | S3.pos += S3.freq; | 290 | break; |
219 | if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len)) | 291 | case 2: |
220 | S3.on = 0; | 292 | s=s>>1; |
221 | if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3)); | 293 | break; |
222 | else s = 0; | 294 | case 3: |
223 | if (R_NR51 & 4) r += s; | 295 | s=s>>2; |
224 | if (R_NR51 & 64) l += s; | 296 | break; |
225 | } | 297 | } |
226 | 298 | ||
227 | if (S4.on) | 299 | if (snd.balance & 4) *r += s; |
300 | if (snd.balance & 64) *l += s; | ||
301 | } | ||
302 | |||
303 | if(S3.on) | ||
304 | { | ||
305 | if(S3.len) | ||
228 | { | 306 | { |
229 | if (R_NR43 & 8) s = 1 & (noise7[ | 307 | S3.len-=snd.quality; |
230 | (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7))); | 308 | if(S3.len<=0 && S3.cont) |
231 | else s = 1 & (noise15[ | 309 | { |
232 | (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7))); | 310 | R_NR52 &= 0xFB; |
233 | s = (-s) & S4.envol; | 311 | S3.on=0; |
234 | S4.pos += S4.freq; | 312 | } |
235 | if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len)) | 313 | } |
314 | } | ||
315 | } | ||
316 | |||
317 | void gbSoundChannel4(int *r, int *l) | ||
318 | { | ||
319 | int vol = S4.envol; | ||
320 | |||
321 | int value = 0; | ||
322 | |||
323 | if(S4.clock <= 0x0c) | ||
324 | { | ||
325 | if(S4.on && (S4.len || !S4.cont)) | ||
326 | { | ||
327 | S4.pos += snd.quality*S4.skip; | ||
328 | S4.shiftpos += snd.quality*S4.shiftskip; | ||
329 | |||
330 | if(S4.nsteps) | ||
331 | { | ||
332 | while(S4.shiftpos > 0x1fffff) { | ||
333 | S4.shiftright = (((S4.shiftright << 6) ^ | ||
334 | (S4.shiftright << 5)) & 0x40) | (S4.shiftright >> 1); | ||
335 | S4.shiftpos -= 0x200000; | ||
336 | } | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | while(S4.shiftpos > 0x1fffff) | ||
341 | { | ||
342 | S4.shiftright = (((S4.shiftright << 14) ^ | ||
343 | (S4.shiftright << 13)) & 0x4000) | (S4.shiftright >> 1); | ||
344 | S4.shiftpos -= 0x200000; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | S4.pos &= 0x1fffff; | ||
349 | S4.shiftpos &= 0x1fffff; | ||
350 | |||
351 | value = ((S4.shiftright & 1)*2-1) * vol; | ||
352 | } | ||
353 | else | ||
354 | { | ||
355 | value = 0; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | if (snd.balance & 8) *r += value; | ||
360 | if (snd.balance & 128) *l += value; | ||
361 | |||
362 | if(S4.on) { | ||
363 | if(S4.len) { | ||
364 | S4.len-=snd.quality; | ||
365 | |||
366 | if(S4.len <= 0 && S4.cont) { | ||
367 | R_NR52 &= 0xfd; | ||
236 | S4.on = 0; | 368 | S4.on = 0; |
237 | if (S4.enlen && (S4.encnt += RATE) >= S4.enlen) | 369 | } |
370 | } | ||
371 | |||
372 | if(S4.enlen) { | ||
373 | S4.enlen-=snd.quality; | ||
374 | |||
375 | if(S4.enlen <= 0) | ||
238 | { | 376 | { |
239 | S4.encnt -= S4.enlen; | 377 | if(S4.endir) |
240 | S4.envol += S4.endir; | 378 | { |
241 | if (S4.envol < 0) S4.envol = 0; | 379 | if(S4.envol < 15) |
242 | if (S4.envol > 15) S4.envol = 15; | 380 | S4.envol++; |
381 | } | ||
382 | else | ||
383 | { | ||
384 | if(S4.envol) | ||
385 | S4.envol--; | ||
386 | } | ||
387 | S4.enlen += S4.enlenreload; | ||
243 | } | 388 | } |
244 | s += s << 1; | ||
245 | if (R_NR51 & 8) r += s; | ||
246 | if (R_NR51 & 128) l += s; | ||
247 | } | 389 | } |
390 | } | ||
391 | } | ||
392 | |||
393 | void sound_mix(void) | ||
394 | { | ||
395 | int l, r; | ||
396 | |||
397 | if (!RATE || cpu.snd < RATE) return; | ||
398 | |||
399 | for (; cpu.snd >= RATE; cpu.snd -= RATE) | ||
400 | { | ||
401 | l = r = 0; | ||
248 | 402 | ||
249 | l *= (R_NR50 & 0x07); | 403 | gbSoundChannel1(&r,&l); |
250 | r *= ((R_NR50 & 0x70)>>4); | ||
251 | l >>= 4; | ||
252 | r >>= 4; | ||
253 | 404 | ||
254 | if (l > 127) l = 127; | 405 | gbSoundChannel2(&r,&l); |
255 | else if (l < -128) l = -128; | 406 | |
256 | if (r > 127) r = 127; | 407 | gbSoundChannel3(&r,&l); |
257 | else if (r < -128) r = -128; | 408 | |
409 | gbSoundChannel4(&r,&l); | ||
410 | |||
411 | if(snd.gbDigitalSound) | ||
412 | { | ||
413 | l = snd.level1<<8; | ||
414 | r = snd.level2<<8; | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | l *= snd.level1*60; | ||
419 | r *= snd.level2*60; | ||
420 | } | ||
421 | |||
422 | if(l > 32767) | ||
423 | l = 32767; | ||
424 | if(l < -32768) | ||
425 | l = -32768; | ||
426 | |||
427 | if(r > 32767) | ||
428 | r = 32767; | ||
429 | if(r < -32768) | ||
430 | r = -32768; | ||
258 | 431 | ||
259 | if (pcm.buf) | 432 | if (pcm.buf) |
260 | { | 433 | { |
@@ -262,17 +435,15 @@ void sound_mix(void) | |||
262 | pcm_submit(); | 435 | pcm_submit(); |
263 | if (pcm.stereo) | 436 | if (pcm.stereo) |
264 | { | 437 | { |
265 | pcm.buf[pcm.pos++] = ((signed char)(l))<<7; | 438 | pcm.buf[pcm.pos++] = l; |
266 | pcm.buf[pcm.pos++] = ((signed char)(r))<<7; | 439 | pcm.buf[pcm.pos++] = r; |
267 | } | 440 | } |
268 | else pcm.buf[pcm.pos++] = ((signed char)((l+r)>>1))<<7; | 441 | else pcm.buf[pcm.pos++] = ((l+r)>>1); |
269 | } | 442 | } |
270 | } | 443 | } |
271 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); | 444 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); |
272 | } | 445 | } |
273 | 446 | ||
274 | |||
275 | |||
276 | byte sound_read(byte r) | 447 | byte sound_read(byte r) |
277 | { | 448 | { |
278 | if(!options.sound) return 0; | 449 | if(!options.sound) return 0; |
@@ -281,166 +452,327 @@ byte sound_read(byte r) | |||
281 | return REG(r); | 452 | return REG(r); |
282 | } | 453 | } |
283 | 454 | ||
284 | void s1_init(void) | ||
285 | { | ||
286 | S1.swcnt = 0; | ||
287 | S1.swfreq = ((R_NR14&7)<<8) + R_NR13; | ||
288 | S1.envol = R_NR12 >> 4; | ||
289 | S1.endir = (R_NR12>>3) & 1; | ||
290 | S1.endir |= S1.endir - 1; | ||
291 | S1.enlen = (R_NR12 & 7) << 15; | ||
292 | if (!S1.on) S1.pos = 0; | ||
293 | S1.on = 1; | ||
294 | S1.cnt = 0; | ||
295 | S1.encnt = 0; | ||
296 | } | ||
297 | |||
298 | void s2_init(void) | ||
299 | { | ||
300 | S2.envol = R_NR22 >> 4; | ||
301 | S2.endir = (R_NR22>>3) & 1; | ||
302 | S2.endir |= S2.endir - 1; | ||
303 | S2.enlen = (R_NR22 & 7) << 15; | ||
304 | if (!S2.on) S2.pos = 0; | ||
305 | S2.on = 1; | ||
306 | S2.cnt = 0; | ||
307 | S2.encnt = 0; | ||
308 | } | ||
309 | |||
310 | void s3_init(void) | ||
311 | { | ||
312 | int i; | ||
313 | if (!S3.on) S3.pos = 0; | ||
314 | S3.cnt = 0; | ||
315 | S3.on = R_NR30 >> 7; | ||
316 | if (S3.on) for (i = 0; i < 16; i++) | ||
317 | ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31]; | ||
318 | } | ||
319 | |||
320 | void s4_init(void) | ||
321 | { | ||
322 | S4.envol = R_NR42 >> 4; | ||
323 | S4.endir = (R_NR42>>3) & 1; | ||
324 | S4.endir |= S4.endir - 1; | ||
325 | S4.enlen = (R_NR42 & 7) << 15; | ||
326 | S4.on = 1; | ||
327 | S4.pos = 0; | ||
328 | S4.cnt = 0; | ||
329 | S4.encnt = 0; | ||
330 | } | ||
331 | |||
332 | |||
333 | void sound_write(byte r, byte b) | 455 | void sound_write(byte r, byte b) |
334 | { | 456 | { |
335 | if(!options.sound) return; | 457 | int freq=0; |
458 | ram.hi[r]=b; | ||
336 | 459 | ||
337 | if (!(R_NR52 & 128) && r != RI_NR52) return; | 460 | if(!options.sound) |
338 | if ((r & 0xF0) == 0x30) | ||
339 | { | ||
340 | if (S3.on) sound_mix(); | ||
341 | if (!S3.on) | ||
342 | WAVE[r-0x30] = ram.hi[r] = b; | ||
343 | return; | 461 | return; |
344 | } | 462 | |
345 | sound_mix(); | 463 | sound_mix(); |
464 | |||
346 | switch (r) | 465 | switch (r) |
347 | { | 466 | { |
348 | case RI_NR10: | 467 | case RI_NR10: |
349 | R_NR10 = b; | 468 | S1.swlen = S1.swlenreload = 344 * ((b >> 4) & 7); |
350 | S1.swlen = ((R_NR10>>4) & 7) << 14; | 469 | S1.swsteps = b & 7; |
351 | S1.swfreq = ((R_NR14&7)<<8) + R_NR13; | 470 | S1.swdir = b & 0x08; |
471 | S1.swstep = 0; | ||
352 | break; | 472 | break; |
353 | case RI_NR11: | 473 | case RI_NR11: |
354 | R_NR11 = b; | 474 | S1.len = 172 * (64 - (b & 0x3f)); |
355 | S1.len = (64-(R_NR11&63)) << 13; | 475 | S1.wave = soundWavePattern[b >> 6]; |
356 | break; | 476 | break; |
357 | case RI_NR12: | 477 | case RI_NR12: |
358 | R_NR12 = b; | 478 | S1.envol = b >> 4; |
359 | S1.envol = R_NR12 >> 4; | 479 | S1.endir = b & 0x08; |
360 | S1.endir = (R_NR12>>3) & 1; | 480 | S1.enlenreload = S1.enlen = 689 * (b & 7); |
361 | S1.endir |= S1.endir - 1; | ||
362 | S1.enlen = (R_NR12 & 7) << 15; | ||
363 | break; | 481 | break; |
364 | case RI_NR13: | 482 | case RI_NR13: |
365 | R_NR13 = b; | 483 | freq = (((int)(R_NR14 & 7)) << 8) | b; |
366 | s1_freq(); | 484 | S1.len = 172 * (64 - (R_NR11 & 0x3f)); |
485 | freq = 2048 - freq; | ||
486 | if(freq) | ||
487 | { | ||
488 | S1.skip = SOUND_MAGIC / freq; | ||
489 | } | ||
490 | else | ||
491 | { | ||
492 | S1.skip = 0; | ||
493 | } | ||
367 | break; | 494 | break; |
368 | case RI_NR14: | 495 | case RI_NR14: |
369 | R_NR14 = b; | 496 | freq = (((int)(b&7) << 8) | R_NR13); |
370 | s1_freq(); | 497 | freq = 2048 - freq; |
371 | if (b & 128) s1_init(); | 498 | S1.len = 172 * (64 - (R_NR11 & 0x3f)); |
499 | S1.cont = b & 0x40; | ||
500 | if(freq) | ||
501 | { | ||
502 | S1.skip = SOUND_MAGIC / freq; | ||
503 | } | ||
504 | else | ||
505 | { | ||
506 | S1.skip = 0; | ||
507 | } | ||
508 | if(b & 0x80) | ||
509 | { | ||
510 | R_NR52 |= 1; | ||
511 | S1.envol = R_NR12 >> 4; | ||
512 | S1.endir = R_NR12 & 0x08; | ||
513 | S1.len = 172 * (64 - (R_NR11 & 0x3f)); | ||
514 | S1.enlenreload = S1.enlen = 689 * (R_NR12 & 7); | ||
515 | S1.swlen = S1.swlenreload = 344 * ((R_NR10 >> 4) & 7); | ||
516 | S1.swsteps = R_NR10 & 7; | ||
517 | S1.swdir = R_NR10 & 0x08; | ||
518 | S1.swstep = 0; | ||
519 | |||
520 | S1.pos = 0; | ||
521 | S1.on = 1; | ||
522 | } | ||
372 | break; | 523 | break; |
373 | case RI_NR21: | 524 | case RI_NR21: |
374 | R_NR21 = b; | 525 | S2.wave = soundWavePattern[b >> 6]; |
375 | S2.len = (64-(R_NR21&63)) << 13; | 526 | S2.len = 172 * (64 - (b & 0x3f)); |
376 | break; | 527 | break; |
377 | case RI_NR22: | 528 | case RI_NR22: |
378 | R_NR22 = b; | 529 | S2.envol = b >> 4; |
379 | S2.envol = R_NR22 >> 4; | 530 | S2.endir = b & 0x08; |
380 | S2.endir = (R_NR22>>3) & 1; | 531 | S2.enlenreload = S2.enlen = 689 * (b & 7); |
381 | S2.endir |= S2.endir - 1; | ||
382 | S2.enlen = (R_NR22 & 7) << 15; | ||
383 | break; | 532 | break; |
384 | case RI_NR23: | 533 | case RI_NR23: |
385 | R_NR23 = b; | 534 | freq = (((int)(R_NR24 & 7)) << 8) | b; |
386 | s2_freq(); | 535 | S2.len = 172 * (64 - (R_NR21 & 0x3f)); |
536 | freq = 2048 - freq; | ||
537 | if(freq) | ||
538 | { | ||
539 | S2.skip = SOUND_MAGIC / freq; | ||
540 | } | ||
541 | else | ||
542 | { | ||
543 | S2.skip = 0; | ||
544 | } | ||
387 | break; | 545 | break; |
388 | case RI_NR24: | 546 | case RI_NR24: |
389 | R_NR24 = b; | 547 | freq = (((int)(b&7) << 8) | R_NR23); |
390 | s2_freq(); | 548 | freq = 2048 - freq; |
391 | if (b & 128) s2_init(); | 549 | S2.len = 172 * (64 - (R_NR21 & 0x3f)); |
550 | S2.cont = b & 0x40; | ||
551 | if(freq) { | ||
552 | S2.skip = SOUND_MAGIC / freq; | ||
553 | } else | ||
554 | S2.skip = 0; | ||
555 | if(b & 0x80) { | ||
556 | R_NR52 |= 2; | ||
557 | S2.envol = R_NR22 >> 4; | ||
558 | S2.endir = R_NR22 & 0x08; | ||
559 | S2.len = 172 * (64 - (R_NR21 & 0x3f)); | ||
560 | S2.enlenreload = S2.enlen = 689 * (R_NR22 & 7); | ||
561 | |||
562 | S2.pos = 0; | ||
563 | S2.on = 1; | ||
564 | } | ||
392 | break; | 565 | break; |
393 | case RI_NR30: | 566 | case RI_NR30: |
394 | R_NR30 = b; | 567 | if (!(b & 0x80)){ |
395 | if (!(b & 128)) S3.on = 0; | 568 | R_NR52 &= 0xfb; |
569 | S3.on = 0; | ||
570 | } | ||
396 | break; | 571 | break; |
397 | case RI_NR31: | 572 | case RI_NR31: |
398 | R_NR31 = b; | 573 | S3.len = (256-R_NR31) * 172; |
399 | S3.len = (256-R_NR31) << 13; | ||
400 | break; | 574 | break; |
401 | case RI_NR32: | 575 | case RI_NR32: |
402 | R_NR32 = b; | 576 | S3.outputlevel = (b >> 5) & 3; |
403 | break; | 577 | break; |
404 | case RI_NR33: | 578 | case RI_NR33: |
405 | R_NR33 = b; | 579 | freq = 2048 - (((int)(R_NR34&7) << 8) | b); |
406 | s3_freq(); | 580 | if(freq) |
581 | S3.skip = SOUND_MAGIC_2 / freq; | ||
582 | else | ||
583 | S3.skip = 0; | ||
407 | break; | 584 | break; |
408 | case RI_NR34: | 585 | case RI_NR34: |
409 | R_NR34 = b; | 586 | freq = 2048 - (((b&7)<<8) | R_NR33); |
410 | s3_freq(); | 587 | |
411 | if (b & 128) s3_init(); | 588 | if(freq) |
589 | S3.skip = SOUND_MAGIC_2 / freq; | ||
590 | else | ||
591 | S3.skip = 0; | ||
592 | |||
593 | S3.cont=b & 0x40; | ||
594 | if((b & 0x80) && (R_NR30 & 0x80)) | ||
595 | { | ||
596 | R_NR52 |= 4; | ||
597 | S3.len = 172 * (256 - R_NR31); | ||
598 | S3.pos = 0; | ||
599 | S3.on = 1; | ||
600 | } | ||
412 | break; | 601 | break; |
413 | case RI_NR41: | 602 | case RI_NR41: |
414 | R_NR41 = b; | 603 | S4.len = 172 * (64 - (b & 0x3f)); |
415 | S4.len = (64-(R_NR41&63)) << 13; | ||
416 | break; | 604 | break; |
417 | case RI_NR42: | 605 | case RI_NR42: |
418 | R_NR42 = b; | 606 | S4.envol = b >> 4; |
419 | S4.envol = R_NR42 >> 4; | 607 | S4.endir = b & 0x08; |
420 | S4.endir = (R_NR42>>3) & 1; | 608 | S4.enlenreload = S4.enlen = 689 * (b & 7); |
421 | S4.endir |= S4.endir - 1; | ||
422 | S4.enlen = (R_NR42 & 7) << 15; | ||
423 | break; | 609 | break; |
424 | case RI_NR43: | 610 | case RI_NR43: |
425 | R_NR43 = b; | 611 | freq = soundFreqRatio[b & 7]; |
426 | s4_freq(); | 612 | |
613 | S4.nsteps = b & 0x08; | ||
614 | S4.skip = (freq << 8) / NOISE_MAGIC; | ||
615 | S4.clock = b >> 4; | ||
616 | |||
617 | freq = freq / soundShiftClock[S4.clock]; | ||
618 | S4.shiftskip = (freq << 8) / NOISE_MAGIC; | ||
427 | break; | 619 | break; |
428 | case RI_NR44: | 620 | case RI_NR44: |
429 | R_NR44 = b; | 621 | S4.cont = b & 0x40; |
430 | if (b & 128) s4_init(); | 622 | if(b & 0x80) |
623 | { | ||
624 | R_NR52 |= 8; | ||
625 | S4.envol = R_NR42 >> 4; | ||
626 | S4.endir = R_NR42 & 0x08; | ||
627 | S4.len = 172 * (64 - (R_NR41 & 0x3f)); | ||
628 | S4.enlenreload = S4.enlen = 689 * (R_NR42 & 7); | ||
629 | |||
630 | S4.on = 1; | ||
631 | |||
632 | S4.pos = 0; | ||
633 | S4.shiftpos = 0; | ||
634 | |||
635 | freq = soundFreqRatio[R_NR43 & 7]; | ||
636 | |||
637 | S4.shiftpos = (freq << 8) / NOISE_MAGIC; | ||
638 | |||
639 | S4.nsteps = R_NR43 & 0x08; | ||
640 | |||
641 | freq = freq / soundShiftClock[R_NR43 >> 4]; | ||
642 | |||
643 | S4.shiftskip = (freq << 8) / NOISE_MAGIC; | ||
644 | if(S4.nsteps) | ||
645 | { | ||
646 | S4.shiftright = 0x7fff; | ||
647 | } | ||
648 | else | ||
649 | { | ||
650 | S4.shiftright = 0x7f; | ||
651 | } | ||
652 | } | ||
431 | break; | 653 | break; |
432 | case RI_NR50: | 654 | case RI_NR50: |
433 | R_NR50 = b; | 655 | snd.level1 = b & 7; |
656 | snd.level2 = (b >> 4) & 7; | ||
434 | break; | 657 | break; |
435 | case RI_NR51: | 658 | case RI_NR51: |
436 | R_NR51 = b; | 659 | snd.balance = b; |
437 | break; | 660 | break; |
438 | case RI_NR52: | 661 | case RI_NR52: |
439 | R_NR52 = b; | 662 | if (!(b & 0x80)) |
440 | if (!(R_NR52 & 128)) | 663 | { |
441 | sound_off(); | 664 | S1.on=0; |
665 | S2.on=0; | ||
666 | S3.on=0; | ||
667 | S4.on=0; | ||
668 | } | ||
442 | break; | 669 | break; |
443 | default: | ||
444 | return; | ||
445 | } | 670 | } |
671 | |||
672 | snd.gbDigitalSound = true; | ||
673 | |||
674 | if(S1.on && S1.envol != 0) | ||
675 | snd.gbDigitalSound = false; | ||
676 | if(S2.on && S2.envol != 0) | ||
677 | snd.gbDigitalSound = false; | ||
678 | if(S3.on && S3.outputlevel != 0) | ||
679 | snd.gbDigitalSound = false; | ||
680 | if(S4.on && S4.envol != 0) | ||
681 | snd.gbDigitalSound = false; | ||
682 | } | ||
683 | |||
684 | void sound_reset() | ||
685 | { | ||
686 | snd.level1 = 7; | ||
687 | snd.level2 = 7; | ||
688 | S1.on = S2.on = S3.on = S4.on = 0; | ||
689 | S1.len = S2.len = S3.len = S4.len = 0; | ||
690 | S1.skip = S2.skip = S3.skip = S4.skip = 0; | ||
691 | S1.pos = S2.pos = S3.pos = S4.pos = 0; | ||
692 | S1.cont = S2.cont = S3.cont = S4.cont = 0; | ||
693 | S1.envol = S2.envol = S4.envol = 0; | ||
694 | S1.enlen = S2.enlen = S4.enlen = 0; | ||
695 | S1.endir = S2.endir = S4.endir = 0; | ||
696 | S1.enlenreload = S2.enlenreload = S4.enlenreload = 0; | ||
697 | S1.swlen = 0; | ||
698 | S1.swlenreload = 0; | ||
699 | S1.swsteps = 0; | ||
700 | S1.swdir = 0; | ||
701 | S1.swstep = 0; | ||
702 | S1.wave = S2.wave = soundWavePattern[2]; | ||
703 | |||
704 | S3.outputlevel = 0; | ||
705 | |||
706 | S4.clock = 0; | ||
707 | S4.shiftright = 0x7f; | ||
708 | S4.nsteps = 0; | ||
709 | |||
710 | sound_write(0x10, 0x80); | ||
711 | sound_write(0x11, 0xbf); | ||
712 | sound_write(0x12, 0xf3); | ||
713 | sound_write(0x14, 0xbf); | ||
714 | sound_write(0x16, 0x3f); | ||
715 | sound_write(0x17, 0x00); | ||
716 | sound_write(0x19, 0xbf); | ||
717 | |||
718 | sound_write(0x1a, 0x7f); | ||
719 | sound_write(0x1b, 0xff); | ||
720 | sound_write(0x1c, 0xbf); | ||
721 | sound_write(0x1e, 0xbf); | ||
722 | |||
723 | sound_write(0x20, 0xff); | ||
724 | sound_write(0x21, 0x00); | ||
725 | sound_write(0x22, 0x00); | ||
726 | sound_write(0x23, 0xbf); | ||
727 | sound_write(0x24, 0x77); | ||
728 | sound_write(0x25, 0xf3); | ||
729 | |||
730 | sound_write(0x26, 0xf0); | ||
731 | |||
732 | S1.on = 0; | ||
733 | S2.on = 0; | ||
734 | S3.on = 0; | ||
735 | S4.on = 0; | ||
736 | |||
737 | int addr = 0x30; | ||
738 | while(addr < 0x40) | ||
739 | { | ||
740 | ram.hi[addr++] = 0x00; | ||
741 | ram.hi[addr++] = 0xff; | ||
742 | } | ||
743 | |||
744 | if (pcm.hz) | ||
745 | { | ||
746 | snd.rate = (1<<21) / pcm.hz; | ||
747 | snd.quality=44100 / pcm.hz; | ||
748 | } | ||
749 | else snd.rate = 0; | ||
750 | } | ||
751 | |||
752 | void sound_dirty() | ||
753 | { | ||
754 | sound_write(RI_NR10, R_NR10); | ||
755 | sound_write(RI_NR11, R_NR11); | ||
756 | sound_write(RI_NR12, R_NR12); | ||
757 | sound_write(RI_NR13, R_NR13); | ||
758 | sound_write(RI_NR14, R_NR14); | ||
759 | |||
760 | sound_write(RI_NR21, R_NR21); | ||
761 | sound_write(RI_NR22, R_NR22); | ||
762 | sound_write(RI_NR23, R_NR23); | ||
763 | sound_write(RI_NR24, R_NR24); | ||
764 | |||
765 | sound_write(RI_NR30, R_NR30); | ||
766 | sound_write(RI_NR31, R_NR31); | ||
767 | sound_write(RI_NR32, R_NR32); | ||
768 | sound_write(RI_NR33, R_NR33); | ||
769 | sound_write(RI_NR34, R_NR34); | ||
770 | |||
771 | sound_write(RI_NR42, R_NR42); | ||
772 | sound_write(RI_NR43, R_NR43); | ||
773 | sound_write(RI_NR44, R_NR44); | ||
774 | |||
775 | sound_write(RI_NR50, R_NR50); | ||
776 | sound_write(RI_NR51, R_NR51); | ||
777 | sound_write(RI_NR52, R_NR52); | ||
446 | } | 778 | } |
diff --git a/apps/plugins/rockboy/sound.h b/apps/plugins/rockboy/sound.h index 88897ef9ce..e40fbad2d5 100644 --- a/apps/plugins/rockboy/sound.h +++ b/apps/plugins/rockboy/sound.h | |||
@@ -5,18 +5,34 @@ | |||
5 | 5 | ||
6 | struct sndchan | 6 | struct sndchan |
7 | { | 7 | { |
8 | int on; | 8 | /* S1, S2, S3, S4 */ |
9 | unsigned pos; | 9 | int on, len, skip, cont; |
10 | int cnt, encnt, swcnt; | 10 | unsigned int pos; |
11 | int len, enlen, swlen; | 11 | |
12 | int swfreq; | 12 | /* S1, S2, S4 */ |
13 | int freq; | 13 | int enlen, envol, endir, enlenreload; |
14 | int envol, endir; | 14 | |
15 | /* S1, S2 */ | ||
16 | const byte *wave; | ||
17 | |||
18 | /* S1 only */ | ||
19 | int swlen, swlenreload, swsteps, swstep, swdir; | ||
20 | |||
21 | /* S3 only */ | ||
22 | int outputlevel; | ||
23 | |||
24 | /* S4 only */ | ||
25 | int shiftskip, shiftpos, shiftright, shiftleft; | ||
26 | int nsteps, clock; | ||
27 | |||
15 | }; | 28 | }; |
16 | 29 | ||
17 | struct snd | 30 | struct snd |
18 | { | 31 | { |
32 | int level1, level2, balance; | ||
33 | bool gbDigitalSound; | ||
19 | int rate; | 34 | int rate; |
35 | int quality; | ||
20 | struct sndchan ch[4]; | 36 | struct sndchan ch[4]; |
21 | }; | 37 | }; |
22 | 38 | ||
@@ -29,12 +45,8 @@ extern struct snd snd; | |||
29 | 45 | ||
30 | byte sound_read(byte r) ICODE_ATTR; | 46 | byte sound_read(byte r) ICODE_ATTR; |
31 | void sound_write(byte r, byte b) ICODE_ATTR; | 47 | void sound_write(byte r, byte b) ICODE_ATTR; |
32 | void sound_dirty(void) ICODE_ATTR; | 48 | void sound_dirty(void); |
33 | void sound_reset(void); | 49 | void sound_reset(void); |
34 | void sound_mix(void) ICODE_ATTR; | 50 | void sound_mix(void) ICODE_ATTR; |
35 | void s1_init(void); | ||
36 | void s2_init(void); | ||
37 | void s3_init(void); | ||
38 | void s4_init(void); | ||
39 | 51 | ||
40 | #endif | 52 | #endif |