Mercurial > vba-clojure
view src/gba/GBASound.cpp @ 536:c2ee7222a3c4
investigating a problem with bad sound when writing RAM with bootstrapping program
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 25 Jun 2012 14:23:16 -0500 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #if (defined(WIN32) && !defined(SDL))2 # include "../win32/stdafx.h"3 # include "../win32/VBA.h"4 #endif6 #include <cstring>7 #include <cassert>9 #include "GBASound.h"10 #include "../common/System.h" // SDL build needs this11 #include "../common/Util.h"12 #include "GBA.h"13 #include "GBAGlobals.h"15 #ifndef countof16 #define countof(a) (sizeof(a) / sizeof(a[0]))17 #endif19 soundtick_t USE_TICKS_AS = 380; // (16777216.0/44100.0); // FIXME: (16777216.0/280896.0)(fps) vs 60.0fps?21 #define SOUND_MAGIC 0x6000000022 #define SOUND_MAGIC_2 0x3000000023 #define NOISE_MAGIC (2097152.0 / 44100.0)25 extern bool8 stopState;27 u8 soundWavePattern[4][32] = {28 { 0x01, 0x01, 0x01, 0x01,29 0xff, 0xff, 0xff, 0xff,30 0xff, 0xff, 0xff, 0xff,31 0xff, 0xff, 0xff, 0xff,32 0xff, 0xff, 0xff, 0xff,33 0xff, 0xff, 0xff, 0xff,34 0xff, 0xff, 0xff, 0xff,35 0xff, 0xff, 0xff, 0xff },36 { 0x01, 0x01, 0x01, 0x01,37 0x01, 0x01, 0x01, 0x01,38 0xff, 0xff, 0xff, 0xff,39 0xff, 0xff, 0xff, 0xff,40 0xff, 0xff, 0xff, 0xff,41 0xff, 0xff, 0xff, 0xff,42 0xff, 0xff, 0xff, 0xff,43 0xff, 0xff, 0xff, 0xff },44 { 0x01, 0x01, 0x01, 0x01,45 0x01, 0x01, 0x01, 0x01,46 0x01, 0x01, 0x01, 0x01,47 0x01, 0x01, 0x01, 0x01,48 0xff, 0xff, 0xff, 0xff,49 0xff, 0xff, 0xff, 0xff,50 0xff, 0xff, 0xff, 0xff,51 0xff, 0xff, 0xff, 0xff },52 { 0x01, 0x01, 0x01, 0x01,53 0x01, 0x01, 0x01, 0x01,54 0x01, 0x01, 0x01, 0x01,55 0x01, 0x01, 0x01, 0x01,56 0x01, 0x01, 0x01, 0x01,57 0x01, 0x01, 0x01, 0x01,58 0xff, 0xff, 0xff, 0xff,59 0xff, 0xff, 0xff, 0xff }60 };62 int32 soundFreqRatio[8] = {63 1048576, // 064 524288, // 165 262144, // 266 174763, // 367 131072, // 468 104858, // 569 87381, // 670 74898 // 771 };73 int32 soundShiftClock[16] = {74 2, // 075 4, // 176 8, // 277 16, // 378 32, // 479 64, // 580 128, // 681 256, // 782 512, // 883 1024, // 984 2048, // 1085 4096, // 1186 8192, // 1287 16384, // 1388 1, // 1489 1 // 1590 };92 int32 soundVolume = 0;94 u8 soundBuffer[6][735];95 u16 soundFinalWave[1470];96 u16 soundFrameSound[735 * 30 * 2]; // for avi logging98 u32 soundBufferLen = 1470;99 u32 soundBufferTotalLen = 14700;100 int32 soundQuality = 2;101 int32 soundPaused = 1;102 int32 soundPlay = 0;103 soundtick_t soundTicks = soundQuality * USE_TICKS_AS;104 soundtick_t SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;105 u32 soundNextPosition = 0;107 int32 soundLevel1 = 0;108 int32 soundLevel2 = 0;109 int32 soundBalance = 0;110 int32 soundMasterOn = 0;111 u32 soundIndex = 0;112 u32 soundBufferIndex = 0;113 int32 soundFrameSoundWritten = 0;114 int32 soundDebug = 0;115 bool8 soundOffFlag = false;117 int32 sound1On = 0;118 int32 sound1ATL = 0;119 int32 sound1Skip = 0;120 int32 sound1Index = 0;121 int32 sound1Continue = 0;122 int32 sound1EnvelopeVolume = 0;123 int32 sound1EnvelopeATL = 0;124 int32 sound1EnvelopeUpDown = 0;125 int32 sound1EnvelopeATLReload = 0;126 int32 sound1SweepATL = 0;127 int32 sound1SweepATLReload = 0;128 int32 sound1SweepSteps = 0;129 int32 sound1SweepUpDown = 0;130 int32 sound1SweepStep = 0;131 u8 * sound1Wave = soundWavePattern[2];133 int32 sound2On = 0;134 int32 sound2ATL = 0;135 int32 sound2Skip = 0;136 int32 sound2Index = 0;137 int32 sound2Continue = 0;138 int32 sound2EnvelopeVolume = 0;139 int32 sound2EnvelopeATL = 0;140 int32 sound2EnvelopeUpDown = 0;141 int32 sound2EnvelopeATLReload = 0;142 u8 * sound2Wave = soundWavePattern[2];144 int32 sound3On = 0;145 int32 sound3ATL = 0;146 int32 sound3Skip = 0;147 int32 sound3Index = 0;148 int32 sound3Continue = 0;149 int32 sound3OutputLevel = 0;150 int32 sound3Last = 0;151 u8 sound3WaveRam[0x20];152 int32 sound3Bank = 0;153 int32 sound3DataSize = 0;154 int32 sound3ForcedOutput = 0;156 int32 sound4On = 0;157 int32 sound4Clock = 0;158 int32 sound4ATL = 0;159 int32 sound4Skip = 0;160 int32 sound4Index = 0;161 int32 sound4ShiftRight = 0x7f;162 int32 sound4ShiftSkip = 0;163 int32 sound4ShiftIndex = 0;164 int32 sound4NSteps = 0;165 int32 sound4CountDown = 0;166 int32 sound4Continue = 0;167 int32 sound4EnvelopeVolume = 0;168 int32 sound4EnvelopeATL = 0;169 int32 sound4EnvelopeUpDown = 0;170 int32 sound4EnvelopeATLReload = 0;172 int32 soundControl = 0;174 int32 soundDSFifoAIndex = 0;175 int32 soundDSFifoACount = 0;176 int32 soundDSFifoAWriteIndex = 0;177 bool8 soundDSAEnabled = false;178 int32 soundDSATimer = 0;179 u8 soundDSFifoA[32];180 u8 soundDSAValue = 0;182 int32 soundDSFifoBIndex = 0;183 int32 soundDSFifoBCount = 0;184 int32 soundDSFifoBWriteIndex = 0;185 bool8 soundDSBEnabled = false;186 int32 soundDSBTimer = 0;187 u8 soundDSFifoB[32];188 u8 soundDSBValue = 0;190 int32 soundEnableFlag = 0x3ff;191 int32 soundMutedFlag = 0;193 s16 soundFilter[4000];194 s16 soundRight[5] = { 0, 0, 0, 0, 0 };195 s16 soundLeft[5] = { 0, 0, 0, 0, 0 };196 int32 soundEchoIndex = 0;197 bool8 soundEcho = false;198 bool8 soundLowPass = false;199 bool8 soundReverse = false;201 static int32 soundTicks_int32;202 static int32 SOUND_CLOCK_TICKS_int32;203 static int32 soundDSBValue_int32;204 variable_desc soundSaveStruct[] = {205 { &soundPaused, sizeof(int32) },206 { &soundPlay, sizeof(int32) },207 { &soundTicks_int32, sizeof(int32) },208 { &SOUND_CLOCK_TICKS_int32, sizeof(int32) },209 { &soundLevel1, sizeof(int32) },210 { &soundLevel2, sizeof(int32) },211 { &soundBalance, sizeof(int32) },212 { &soundMasterOn, sizeof(int32) },213 { &soundIndex, sizeof(int32) },214 { &sound1On, sizeof(int32) },215 { &sound1ATL, sizeof(int32) },216 { &sound1Skip, sizeof(int32) },217 { &sound1Index, sizeof(int32) },218 { &sound1Continue, sizeof(int32) },219 { &sound1EnvelopeVolume, sizeof(int32) },220 { &sound1EnvelopeATL, sizeof(int32) },221 { &sound1EnvelopeATLReload, sizeof(int32) },222 { &sound1EnvelopeUpDown, sizeof(int32) },223 { &sound1SweepATL, sizeof(int32) },224 { &sound1SweepATLReload, sizeof(int32) },225 { &sound1SweepSteps, sizeof(int32) },226 { &sound1SweepUpDown, sizeof(int32) },227 { &sound1SweepStep, sizeof(int32) },228 { &sound2On, sizeof(int32) },229 { &sound2ATL, sizeof(int32) },230 { &sound2Skip, sizeof(int32) },231 { &sound2Index, sizeof(int32) },232 { &sound2Continue, sizeof(int32) },233 { &sound2EnvelopeVolume, sizeof(int32) },234 { &sound2EnvelopeATL, sizeof(int32) },235 { &sound2EnvelopeATLReload, sizeof(int32) },236 { &sound2EnvelopeUpDown, sizeof(int32) },237 { &sound3On, sizeof(int32) },238 { &sound3ATL, sizeof(int32) },239 { &sound3Skip, sizeof(int32) },240 { &sound3Index, sizeof(int32) },241 { &sound3Continue, sizeof(int32) },242 { &sound3OutputLevel, sizeof(int32) },243 { &sound4On, sizeof(int32) },244 { &sound4ATL, sizeof(int32) },245 { &sound4Skip, sizeof(int32) },246 { &sound4Index, sizeof(int32) },247 { &sound4Clock, sizeof(int32) },248 { &sound4ShiftRight, sizeof(int32) },249 { &sound4ShiftSkip, sizeof(int32) },250 { &sound4ShiftIndex, sizeof(int32) },251 { &sound4NSteps, sizeof(int32) },252 { &sound4CountDown, sizeof(int32) },253 { &sound4Continue, sizeof(int32) },254 { &sound4EnvelopeVolume, sizeof(int32) },255 { &sound4EnvelopeATL, sizeof(int32) },256 { &sound4EnvelopeATLReload, sizeof(int32) },257 { &sound4EnvelopeUpDown, sizeof(int32) },258 { &soundEnableFlag, sizeof(int32) },259 { &soundControl, sizeof(int32) },260 { &soundDSFifoAIndex, sizeof(int32) },261 { &soundDSFifoACount, sizeof(int32) },262 { &soundDSFifoAWriteIndex, sizeof(int32) },263 { &soundDSAEnabled, sizeof(bool8) },264 { &soundDSATimer, sizeof(int32) },265 { &soundDSFifoA[0], 32 },266 { &soundDSAValue, sizeof(u8) },267 { &soundDSFifoBIndex, sizeof(int32) },268 { &soundDSFifoBCount, sizeof(int32) },269 { &soundDSFifoBWriteIndex, sizeof(int32) },270 { &soundDSBEnabled, sizeof(int32) },271 { &soundDSBTimer, sizeof(int32) },272 { &soundDSFifoB[0], 32 },273 { &soundDSBValue_int32, sizeof(int32) }, // save as int32 because of a mistake of the past.274 { &soundBuffer[0][0], 6 * 735 },275 { &soundFinalWave[0], 2 * 735 },276 { NULL, 0 }277 };279 variable_desc soundSaveStructV2[] = {280 { &sound3WaveRam[0], 0x20 },281 { &sound3Bank, sizeof(int32) },282 { &sound3DataSize, sizeof(int32) },283 { &sound3ForcedOutput, sizeof(int32) },284 { NULL, 0 }285 };287 //variable_desc soundSaveStructV3[] = {288 // { &soundTicks, sizeof(soundtick_t) },289 // { &SOUND_CLOCK_TICKS, sizeof(soundtick_t) },290 // { &USE_TICKS_AS, sizeof(soundtick_t) },291 // { NULL, 0 }292 //};294 void soundEvent(u32 address, u8 data)295 {296 int freq = 0;298 switch (address)299 {300 case NR10:301 data &= 0x7f;302 sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7);303 sound1SweepSteps = data & 7;304 sound1SweepUpDown = data & 0x08;305 sound1SweepStep = 0;306 ioMem[address] = data;307 break;308 case NR11:309 sound1Wave = soundWavePattern[data >> 6];310 sound1ATL = 172 * (64 - (data & 0x3f));311 ioMem[address] = data;312 break;313 case NR12:314 sound1EnvelopeUpDown = data & 0x08;315 sound1EnvelopeATLReload = 689 * (data & 7);316 if ((data & 0xF8) == 0)317 sound1EnvelopeVolume = 0;318 ioMem[address] = data;319 break;320 case NR13:321 freq = (((int)(ioMem[NR14] & 7)) << 8) | data;322 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));323 freq = 2048 - freq;324 if (freq)325 {326 sound1Skip = SOUND_MAGIC / freq;327 }328 else329 sound1Skip = 0;330 ioMem[address] = data;331 break;332 case NR14:333 data &= 0xC7;334 freq = (((int)(data & 7) << 8) | ioMem[NR13]);335 freq = 2048 - freq;336 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));337 sound1Continue = data & 0x40;338 if (freq)339 {340 sound1Skip = SOUND_MAGIC / freq;341 }342 else343 sound1Skip = 0;344 if (data & 0x80)345 {346 ioMem[NR52] |= 1;347 sound1EnvelopeVolume = ioMem[NR12] >> 4;348 sound1EnvelopeUpDown = ioMem[NR12] & 0x08;349 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));350 sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (ioMem[NR12] & 7);351 sound1SweepATL = sound1SweepATLReload = 344 * ((ioMem[NR10] >> 4) & 7);352 sound1SweepSteps = ioMem[NR10] & 7;353 sound1SweepUpDown = ioMem[NR10] & 0x08;354 sound1SweepStep = 0;356 sound1Index = 0;357 sound1On = 1;358 }359 ioMem[address] = data;360 break;361 case NR21:362 sound2Wave = soundWavePattern[data >> 6];363 sound2ATL = 172 * (64 - (data & 0x3f));364 ioMem[address] = data;365 break;366 case NR22:367 sound2EnvelopeUpDown = data & 0x08;368 sound2EnvelopeATLReload = 689 * (data & 7);369 if ((data & 0xF8) == 0)370 sound2EnvelopeVolume = 0;371 ioMem[address] = data;372 break;373 case NR23:374 freq = (((int)(ioMem[NR24] & 7)) << 8) | data;375 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));376 freq = 2048 - freq;377 if (freq)378 {379 sound2Skip = SOUND_MAGIC / freq;380 }381 else382 sound2Skip = 0;383 ioMem[address] = data;384 break;385 case NR24:386 data &= 0xC7;387 freq = (((int)(data & 7) << 8) | ioMem[NR23]);388 freq = 2048 - freq;389 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));390 sound2Continue = data & 0x40;391 if (freq)392 {393 sound2Skip = SOUND_MAGIC / freq;394 }395 else396 sound2Skip = 0;397 if (data & 0x80)398 {399 ioMem[NR52] |= 2;400 sound2EnvelopeVolume = ioMem[NR22] >> 4;401 sound2EnvelopeUpDown = ioMem[NR22] & 0x08;402 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));403 sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (ioMem[NR22] & 7);405 sound2Index = 0;406 sound2On = 1;407 }408 ioMem[address] = data;409 break;410 case NR30:411 data &= 0xe0;412 if (!(data & 0x80))413 {414 ioMem[NR52] &= 0xfb;415 sound3On = 0;416 }417 if (((data >> 6) & 1) != sound3Bank)418 memcpy(&ioMem[0x90], &sound3WaveRam[(((data >> 6) & 1) * 0x10) ^ 0x10],419 0x10);420 sound3Bank = (data >> 6) & 1;421 sound3DataSize = (data >> 5) & 1;422 ioMem[address] = data;423 break;424 case NR31:425 sound3ATL = 172 * (256 - data);426 ioMem[address] = data;427 break;428 case NR32:429 data &= 0xe0;430 sound3OutputLevel = (data >> 5) & 3;431 sound3ForcedOutput = (data >> 7) & 1;432 ioMem[address] = data;433 break;434 case NR33:435 freq = 2048 - (((int)(ioMem[NR34] & 7) << 8) | data);436 if (freq)437 {438 sound3Skip = SOUND_MAGIC_2 / freq;439 }440 else441 sound3Skip = 0;442 ioMem[address] = data;443 break;444 case NR34:445 data &= 0xc7;446 freq = 2048 - (((data & 7) << 8) | (int)ioMem[NR33]);447 if (freq)448 {449 sound3Skip = SOUND_MAGIC_2 / freq;450 }451 else452 {453 sound3Skip = 0;454 }455 sound3Continue = data & 0x40;456 if ((data & 0x80) && (ioMem[NR30] & 0x80))457 {458 ioMem[NR52] |= 4;459 sound3ATL = 172 * (256 - ioMem[NR31]);460 sound3Index = 0;461 sound3On = 1;462 }463 ioMem[address] = data;464 break;465 case NR41:466 data &= 0x3f;467 sound4ATL = 172 * (64 - (data & 0x3f));468 ioMem[address] = data;469 break;470 case NR42:471 sound4EnvelopeUpDown = data & 0x08;472 sound4EnvelopeATLReload = 689 * (data & 7);473 if ((data & 0xF8) == 0)474 sound4EnvelopeVolume = 0;475 ioMem[address] = data;476 break;477 case NR43:478 freq = soundFreqRatio[data & 7];479 sound4NSteps = data & 0x08;481 sound4Skip = freq * NOISE_MAGIC;483 sound4Clock = data >> 4;485 freq = freq / soundShiftClock[sound4Clock];487 sound4ShiftSkip = freq * NOISE_MAGIC;488 ioMem[address] = data;489 break;490 case NR44:491 data &= 0xc0;492 sound4Continue = data & 0x40;493 if (data & 0x80)494 {495 ioMem[NR52] |= 8;496 sound4EnvelopeVolume = ioMem[NR42] >> 4;497 sound4EnvelopeUpDown = ioMem[NR42] & 0x08;498 sound4ATL = 172 * (64 - (ioMem[NR41] & 0x3f));499 sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (ioMem[NR42] & 7);501 sound4On = 1;503 sound4Index = 0;504 sound4ShiftIndex = 0;506 freq = soundFreqRatio[ioMem[NR43] & 7];508 sound4Skip = freq * NOISE_MAGIC;510 sound4NSteps = ioMem[NR43] & 0x08;512 freq = freq / soundShiftClock[ioMem[NR43] >> 4];514 sound4ShiftSkip = freq * NOISE_MAGIC;515 if (sound4NSteps)516 sound4ShiftRight = 0x7f;517 else518 sound4ShiftRight = 0x7fff;519 }520 ioMem[address] = data;521 break;522 case NR50:523 data &= 0x77;524 soundLevel1 = data & 7;525 soundLevel2 = (data >> 4) & 7;526 ioMem[address] = data;527 break;528 case NR51:529 soundBalance = (data & soundEnableFlag);530 ioMem[address] = data;531 break;532 case NR52:533 data &= 0x80;534 data |= ioMem[NR52] & 15;535 soundMasterOn = data & 0x80;536 if (!(data & 0x80))537 {538 sound1On = 0;539 sound2On = 0;540 sound3On = 0;541 sound4On = 0;542 }543 ioMem[address] = data;544 break;545 case 0x90:546 case 0x91:547 case 0x92:548 case 0x93:549 case 0x94:550 case 0x95:551 case 0x96:552 case 0x97:553 case 0x98:554 case 0x99:555 case 0x9a:556 case 0x9b:557 case 0x9c:558 case 0x9d:559 case 0x9e:560 case 0x9f:561 sound3WaveRam[(sound3Bank * 0x10) ^ 0x10 + (address & 15)] = data;562 break;563 }564 }566 void soundEvent(u32 address, u16 data)567 {568 switch (address)569 {570 case SGCNT0_H:571 data &= 0xFF0F;572 soundControl = data & 0x770F;;573 if (data & 0x0800)574 {575 soundDSFifoAWriteIndex = 0;576 soundDSFifoAIndex = 0;577 soundDSFifoACount = 0;578 soundDSAValue = 0;579 memset(soundDSFifoA, 0, 32);580 }581 soundDSAEnabled = (data & 0x0300) ? true : false;582 soundDSATimer = (data & 0x0400) ? 1 : 0;583 if (data & 0x8000)584 {585 soundDSFifoBWriteIndex = 0;586 soundDSFifoBIndex = 0;587 soundDSFifoBCount = 0;588 soundDSBValue = 0;589 memset(soundDSFifoB, 0, 32);590 }591 soundDSBEnabled = (data & 0x3000) ? true : false;592 soundDSBTimer = (data & 0x4000) ? 1 : 0;593 *((u16 *)&ioMem[address]) = data;594 break;595 case FIFOA_L:596 case FIFOA_H:597 soundDSFifoA[soundDSFifoAWriteIndex++] = data & 0xFF;598 soundDSFifoA[soundDSFifoAWriteIndex++] = data >> 8;599 soundDSFifoACount += 2;600 soundDSFifoAWriteIndex &= 31;601 *((u16 *)&ioMem[address]) = data;602 break;603 case FIFOB_L:604 case FIFOB_H:605 soundDSFifoB[soundDSFifoBWriteIndex++] = data & 0xFF;606 soundDSFifoB[soundDSFifoBWriteIndex++] = data >> 8;607 soundDSFifoBCount += 2;608 soundDSFifoBWriteIndex &= 31;609 *((u16 *)&ioMem[address]) = data;610 break;611 case 0x88:612 data &= 0xC3FF;613 *((u16 *)&ioMem[address]) = data;614 break;615 case 0x90:616 case 0x92:617 case 0x94:618 case 0x96:619 case 0x98:620 case 0x9a:621 case 0x9c:622 case 0x9e:623 *((u16 *)&sound3WaveRam[(sound3Bank * 0x10) ^ 0x10 + (address & 14)]) = data;624 *((u16 *)&ioMem[address]) = data;625 break;626 }627 }629 void soundChannel1()630 {631 int vol = sound1EnvelopeVolume;633 int freq = 0;634 int value = 0;636 if (sound1On && (sound1ATL || !sound1Continue))637 {638 sound1Index += soundQuality * sound1Skip;639 sound1Index &= 0x1fffffff;641 value = ((s8)sound1Wave[sound1Index >> 24]) * vol;642 }644 soundBuffer[0][soundIndex] = value;646 if (sound1On)647 {648 if (sound1ATL)649 {650 sound1ATL -= soundQuality;652 if (sound1ATL <= 0 && sound1Continue)653 {654 ioMem[NR52] &= 0xfe;655 sound1On = 0;656 }657 }659 if (sound1EnvelopeATL)660 {661 sound1EnvelopeATL -= soundQuality;663 if (sound1EnvelopeATL <= 0)664 {665 if (sound1EnvelopeUpDown)666 {667 if (sound1EnvelopeVolume < 15)668 sound1EnvelopeVolume++;669 }670 else671 {672 if (sound1EnvelopeVolume)673 sound1EnvelopeVolume--;674 }676 sound1EnvelopeATL += sound1EnvelopeATLReload;677 }678 }680 if (sound1SweepATL)681 {682 sound1SweepATL -= soundQuality;684 if (sound1SweepATL <= 0)685 {686 freq = (((int)(ioMem[NR14] & 7) << 8) | ioMem[NR13]);688 int updown = 1;690 if (sound1SweepUpDown)691 updown = -1;693 int newfreq = 0;694 if (sound1SweepSteps)695 {696 newfreq = freq + updown * freq / (1 << sound1SweepSteps);697 if (newfreq == freq)698 newfreq = 0;699 }700 else701 newfreq = freq;703 if (newfreq < 0)704 {705 sound1SweepATL += sound1SweepATLReload;706 }707 else if (newfreq > 2047)708 {709 sound1SweepATL = 0;710 sound1On = 0;711 ioMem[NR52] &= 0xfe;712 }713 else714 {715 sound1SweepATL += sound1SweepATLReload;716 sound1Skip = SOUND_MAGIC / (2048 - newfreq);718 ioMem[NR13] = newfreq & 0xff;719 ioMem[NR14] = (ioMem[NR14] & 0xf8) | ((newfreq >> 8) & 7);720 }721 }722 }723 }724 }726 void soundChannel2()727 {728 // int freq = 0;729 int vol = sound2EnvelopeVolume;731 int value = 0;733 if (sound2On && (sound2ATL || !sound2Continue))734 {735 sound2Index += soundQuality * sound2Skip;736 sound2Index &= 0x1fffffff;738 value = ((s8)sound2Wave[sound2Index >> 24]) * vol;739 }741 soundBuffer[1][soundIndex] = value;743 if (sound2On)744 {745 if (sound2ATL)746 {747 sound2ATL -= soundQuality;749 if (sound2ATL <= 0 && sound2Continue)750 {751 ioMem[NR52] &= 0xfd;752 sound2On = 0;753 }754 }756 if (sound2EnvelopeATL)757 {758 sound2EnvelopeATL -= soundQuality;760 if (sound2EnvelopeATL <= 0)761 {762 if (sound2EnvelopeUpDown)763 {764 if (sound2EnvelopeVolume < 15)765 sound2EnvelopeVolume++;766 }767 else768 {769 if (sound2EnvelopeVolume)770 sound2EnvelopeVolume--;771 }772 sound2EnvelopeATL += sound2EnvelopeATLReload;773 }774 }775 }776 }778 void soundChannel3()779 {780 int value = sound3Last;782 if (sound3On && (sound3ATL || !sound3Continue))783 {784 sound3Index += soundQuality * sound3Skip;785 if (sound3DataSize)786 {787 sound3Index &= 0x3fffffff;788 value = sound3WaveRam[sound3Index >> 25];789 }790 else791 {792 sound3Index &= 0x1fffffff;793 value = sound3WaveRam[sound3Bank * 0x10 + (sound3Index >> 25)];794 }796 if ((sound3Index & 0x01000000))797 {798 value &= 0x0f;799 }800 else801 {802 value >>= 4;803 }805 value -= 8;806 value *= 2;808 if (sound3ForcedOutput)809 {810 value = ((value >> 1) + value) >> 1;811 }812 else813 {814 switch (sound3OutputLevel)815 {816 case 0:817 value = 0;818 break;819 case 1:820 break;821 case 2:822 value = (value >> 1);823 break;824 case 3:825 value = (value >> 2);826 break;827 }828 }829 //value += 1;830 sound3Last = value;831 }833 soundBuffer[2][soundIndex] = value;835 if (sound3On)836 {837 if (sound3ATL)838 {839 sound3ATL -= soundQuality;841 if (sound3ATL <= 0 && sound3Continue)842 {843 ioMem[NR52] &= 0xfb;844 sound3On = 0;845 }846 }847 }848 }850 void soundChannel4()851 {852 int vol = sound4EnvelopeVolume;854 int value = 0;856 if (sound4Clock <= 0x0c)857 {858 if (sound4On && (sound4ATL || !sound4Continue))859 {860 #define NOISE_ONE_SAMP_SCALE 0x200000862 sound4Index += soundQuality * sound4Skip;863 sound4ShiftIndex += soundQuality * sound4ShiftSkip;865 if (sound4NSteps)866 {867 while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE)868 {869 sound4ShiftRight = (((sound4ShiftRight << 6) ^870 (sound4ShiftRight << 5)) & 0x40) |871 (sound4ShiftRight >> 1);872 sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE;873 }874 }875 else876 {877 while (sound4ShiftIndex >= NOISE_ONE_SAMP_SCALE)878 {879 sound4ShiftRight = (((sound4ShiftRight << 14) ^880 (sound4ShiftRight << 13)) & 0x4000) |881 (sound4ShiftRight >> 1);883 sound4ShiftIndex -= NOISE_ONE_SAMP_SCALE;884 }885 }887 sound4Index %= NOISE_ONE_SAMP_SCALE;888 sound4ShiftIndex %= NOISE_ONE_SAMP_SCALE;890 value = ((sound4ShiftRight & 1) * 2 - 1) * vol;891 }892 else893 {894 value = 0;895 }896 }898 soundBuffer[3][soundIndex] = value;900 if (sound4On)901 {902 if (sound4ATL)903 {904 sound4ATL -= soundQuality;906 if (sound4ATL <= 0 && sound4Continue)907 {908 ioMem[NR52] &= 0xfd;909 sound4On = 0;910 }911 }913 if (sound4EnvelopeATL)914 {915 sound4EnvelopeATL -= soundQuality;917 if (sound4EnvelopeATL <= 0)918 {919 if (sound4EnvelopeUpDown)920 {921 if (sound4EnvelopeVolume < 15)922 sound4EnvelopeVolume++;923 }924 else925 {926 if (sound4EnvelopeVolume)927 sound4EnvelopeVolume--;928 }929 sound4EnvelopeATL += sound4EnvelopeATLReload;930 }931 }932 }933 }935 void soundDirectSoundA()936 {937 soundBuffer[4][soundIndex] = soundDSAValue;938 }940 void soundDirectSoundATimer()941 {942 if (soundDSAEnabled)943 {944 if (soundDSFifoACount <= 16)945 {946 CPUCheckDMA(3, 2);947 if (soundDSFifoACount <= 16)948 {949 soundEvent(FIFOA_L, (u16)0);950 soundEvent(FIFOA_H, (u16)0);951 soundEvent(FIFOA_L, (u16)0);952 soundEvent(FIFOA_H, (u16)0);953 soundEvent(FIFOA_L, (u16)0);954 soundEvent(FIFOA_H, (u16)0);955 soundEvent(FIFOA_L, (u16)0);956 soundEvent(FIFOA_H, (u16)0);957 }958 }960 soundDSAValue = (soundDSFifoA[soundDSFifoAIndex]);961 soundDSFifoAIndex = (++soundDSFifoAIndex) & 31;962 soundDSFifoACount--;963 }964 else965 soundDSAValue = 0;966 }968 void soundDirectSoundB()969 {970 soundBuffer[5][soundIndex] = soundDSBValue;971 }973 void soundDirectSoundBTimer()974 {975 if (soundDSBEnabled)976 {977 if (soundDSFifoBCount <= 16)978 {979 CPUCheckDMA(3, 4);980 if (soundDSFifoBCount <= 16)981 {982 soundEvent(FIFOB_L, (u16)0);983 soundEvent(FIFOB_H, (u16)0);984 soundEvent(FIFOB_L, (u16)0);985 soundEvent(FIFOB_H, (u16)0);986 soundEvent(FIFOB_L, (u16)0);987 soundEvent(FIFOB_H, (u16)0);988 soundEvent(FIFOB_L, (u16)0);989 soundEvent(FIFOB_H, (u16)0);990 }991 }993 soundDSBValue = (soundDSFifoB[soundDSFifoBIndex]);994 soundDSFifoBIndex = (++soundDSFifoBIndex) & 31;995 soundDSFifoBCount--;996 }997 else998 {999 soundDSBValue = 0;1000 }1001 }1003 void soundTimerOverflow(int timer)1004 {1005 if (soundDSAEnabled && (soundDSATimer == timer))1006 {1007 soundDirectSoundATimer();1008 }1009 if (soundDSBEnabled && (soundDSBTimer == timer))1010 {1011 soundDirectSoundBTimer();1012 }1013 }1015 void soundMix()1016 {1017 int res = 0;1018 int cgbRes = 0;1019 int ratio = ioMem[0x82] & 3;1020 int dsaRatio = ioMem[0x82] & 4;1021 int dsbRatio = ioMem[0x82] & 8;1023 if (ioMem)1024 soundBalance = (ioMem[NR51] & soundEnableFlag & ~soundMutedFlag);1026 if (soundBalance & 16)1027 {1028 cgbRes = ((s8)soundBuffer[0][soundIndex]);1029 }1030 if (soundBalance & 32)1031 {1032 cgbRes += ((s8)soundBuffer[1][soundIndex]);1033 }1034 if (soundBalance & 64)1035 {1036 cgbRes += ((s8)soundBuffer[2][soundIndex]);1037 }1038 if (soundBalance & 128)1039 {1040 cgbRes += ((s8)soundBuffer[3][soundIndex]);1041 }1043 if ((soundControl & 0x0200) && (soundEnableFlag & 0x100))1044 {1045 if (!dsaRatio)1046 res = ((s8)soundBuffer[4][soundIndex]) >> 1;1047 else1048 res = ((s8)soundBuffer[4][soundIndex]);1049 }1051 if ((soundControl & 0x2000) && (soundEnableFlag & 0x200))1052 {1053 if (!dsbRatio)1054 res += ((s8)soundBuffer[5][soundIndex]) >> 1;1055 else1056 res += ((s8)soundBuffer[5][soundIndex]);1057 }1059 res = (res * 170);1060 cgbRes = (cgbRes * 52 * soundLevel1);1062 switch (ratio)1063 {1064 case 0:1065 case 3: // prohibited, but 25%1066 cgbRes >>= 2;1067 break;1068 case 1:1069 cgbRes >>= 1;1070 break;1071 case 2:1072 break;1073 }1075 res += cgbRes;1077 if (soundEcho)1078 {1079 res *= 2;1080 res += soundFilter[soundEchoIndex];1081 res /= 2;1082 soundFilter[soundEchoIndex++] = res;1083 }1085 if (soundLowPass)1086 {1087 soundLeft[4] = soundLeft[3];1088 soundLeft[3] = soundLeft[2];1089 soundLeft[2] = soundLeft[1];1090 soundLeft[1] = soundLeft[0];1091 soundLeft[0] = res;1092 res = (soundLeft[4] + 2 * soundLeft[3] + 8 * soundLeft[2] + 2 * soundLeft[1] +1093 soundLeft[0]) / 14;1094 }1096 bool noSpecialEffects = false;1097 #if (defined(WIN32) && !defined(SDL))1098 if (theApp.soundRecording || theApp.aviRecording || theApp.nvAudioLog)1099 noSpecialEffects = true;1100 #endif1102 if (!noSpecialEffects)1103 {1104 switch (soundVolume)1105 {1106 case 0:1107 case 1:1108 case 2:1109 case 3:1110 res *= (soundVolume + 1);1111 break;1112 case 4:1113 res >>= 2;1114 break;1115 case 5:1116 res >>= 1;1117 break;1118 }1119 }1121 if (res > 32767)1122 res = 32767;1123 if (res < -32768)1124 res = -32768;1126 if (soundReverse && !noSpecialEffects)1127 {1128 soundFinalWave[++soundBufferIndex] = res;1129 if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound))1130 /*assert(false)*/;1131 else1132 soundFrameSound[++soundFrameSoundWritten] = res;1133 }1134 else1135 {1136 soundFinalWave[soundBufferIndex++] = res;1137 if (soundFrameSoundWritten >= countof(soundFrameSound))1138 /*assert(false)*/;1139 else1140 soundFrameSound[soundFrameSoundWritten++] = res;1141 }1143 res = 0;1144 cgbRes = 0;1146 if (soundBalance & 1)1147 {1148 cgbRes = ((s8)soundBuffer[0][soundIndex]);1149 }1150 if (soundBalance & 2)1151 {1152 cgbRes += ((s8)soundBuffer[1][soundIndex]);1153 }1154 if (soundBalance & 4)1155 {1156 cgbRes += ((s8)soundBuffer[2][soundIndex]);1157 }1158 if (soundBalance & 8)1159 {1160 cgbRes += ((s8)soundBuffer[3][soundIndex]);1161 }1163 if ((soundControl & 0x0100) && (soundEnableFlag & 0x100))1164 {1165 if (!dsaRatio)1166 res = ((s8)soundBuffer[4][soundIndex]) >> 1;1167 else1168 res = ((s8)soundBuffer[4][soundIndex]);1169 }1171 if ((soundControl & 0x1000) && (soundEnableFlag & 0x200))1172 {1173 if (!dsbRatio)1174 res += ((s8)soundBuffer[5][soundIndex]) >> 1;1175 else1176 res += ((s8)soundBuffer[5][soundIndex]);1177 }1179 res = (res * 170);1180 cgbRes = (cgbRes * 52 * soundLevel1);1182 switch (ratio)1183 {1184 case 0:1185 case 3: // prohibited, but 25%1186 cgbRes >>= 2;1187 break;1188 case 1:1189 cgbRes >>= 1;1190 break;1191 case 2:1192 break;1193 }1195 res += cgbRes;1197 if (soundEcho)1198 {1199 res *= 2;1200 res += soundFilter[soundEchoIndex];1201 res /= 2;1202 soundFilter[soundEchoIndex++] = res;1204 if (soundEchoIndex >= 4000)1205 soundEchoIndex = 0;1206 }1208 if (soundLowPass)1209 {1210 soundRight[4] = soundRight[3];1211 soundRight[3] = soundRight[2];1212 soundRight[2] = soundRight[1];1213 soundRight[1] = soundRight[0];1214 soundRight[0] = res;1215 res = (soundRight[4] + 2 * soundRight[3] + 8 * soundRight[2] + 2 * soundRight[1] +1216 soundRight[0]) / 14;1217 }1219 if (!noSpecialEffects)1220 {1221 switch (soundVolume)1222 {1223 case 0:1224 case 1:1225 case 2:1226 case 3:1227 res *= (soundVolume + 1);1228 break;1229 case 4:1230 res >>= 2;1231 break;1232 case 5:1233 res >>= 1;1234 break;1235 }1236 }1238 if (res > 32767)1239 res = 32767;1240 if (res < -32768)1241 res = -32768;1243 if (soundReverse && !noSpecialEffects)1244 {1245 soundFinalWave[-1 + soundBufferIndex++] = res;1246 if ((soundFrameSoundWritten) >= countof(soundFrameSound))1247 /*assert(false)*/;1248 else1249 soundFrameSound[-1 + soundFrameSoundWritten++] = res;1250 }1251 else1252 {1253 soundFinalWave[soundBufferIndex++] = res;1254 if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound))1255 /*assert(false)*/;1256 else1257 soundFrameSound[soundFrameSoundWritten++] = res;1258 }1259 }1261 void soundTick()1262 {1263 if (systemSoundOn)1264 {1265 if (soundMasterOn && !stopState)1266 {1267 soundChannel1();1268 soundChannel2();1269 soundChannel3();1270 soundChannel4();1271 soundDirectSoundA();1272 soundDirectSoundB();1273 soundMix();1274 }1275 else1276 {1277 soundFinalWave[soundBufferIndex++] = 0;1278 soundFinalWave[soundBufferIndex++] = 0;1279 if ((soundFrameSoundWritten + 1) >= countof(soundFrameSound))1280 /*assert(false)*/;1281 else1282 {1283 soundFrameSound[soundFrameSoundWritten++] = 0;1284 soundFrameSound[soundFrameSoundWritten++] = 0;1285 }1286 }1288 soundIndex++;1290 if (2 * soundBufferIndex >= soundBufferLen)1291 {1292 if (systemSoundOn)1293 {1294 if (soundPaused)1295 {1296 soundResume();1297 }1299 systemSoundWriteToBuffer();1300 }1301 soundIndex = 0;1302 soundBufferIndex = 0;1303 }1304 }1305 }1307 void soundShutdown()1308 {1309 systemSoundShutdown();1310 }1312 void soundPause()1313 {1314 systemSoundPause();1315 }1317 void soundResume()1318 {1319 systemSoundResume();1320 }1322 void soundEnableChannels(int channels)1323 {1324 int c = (channels & 0x0f) << 4;1325 soundEnableFlag |= ((channels & 0x30f) | c);1326 }1328 void soundDisableChannels(int channels)1329 {1330 int c = (channels & 0x0f) << 4;1331 soundEnableFlag &= ~((channels & 0x30f) | c);1332 }1334 int soundGetEnabledChannels()1335 {1336 return (soundEnableFlag & 0x30f);1337 }1339 #if 01340 // unused1341 void soundMuteChannels(int channels)1342 {1343 soundMutedFlag |= channels & 0x30f;1344 }1346 void soundUnmuteChannels(int channels)1347 {1348 soundMutedFlag &= ~(channels & 0x30f);1349 }1351 int soundGetMutedChannels()1352 {1353 return (soundMutedFlag & 0x30f);1354 }1355 #endif1357 void soundReset()1358 {1359 systemSoundReset();1361 soundPaused = 1;1362 soundPlay = 0;1363 SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;1364 soundTicks = SOUND_CLOCK_TICKS;1365 soundNextPosition = 0;1366 soundMasterOn = 1;1367 soundIndex = 0;1368 soundBufferIndex = 0;1369 soundLevel1 = 7;1370 soundLevel2 = 7;1372 sound1On = 0;1373 sound1ATL = 0;1374 sound1Skip = 0;1375 sound1Index = 0;1376 sound1Continue = 0;1377 sound1EnvelopeVolume = 0;1378 sound1EnvelopeATL = 0;1379 sound1EnvelopeUpDown = 0;1380 sound1EnvelopeATLReload = 0;1381 sound1SweepATL = 0;1382 sound1SweepATLReload = 0;1383 sound1SweepSteps = 0;1384 sound1SweepUpDown = 0;1385 sound1SweepStep = 0;1386 sound1Wave = soundWavePattern[2];1388 sound2On = 0;1389 sound2ATL = 0;1390 sound2Skip = 0;1391 sound2Index = 0;1392 sound2Continue = 0;1393 sound2EnvelopeVolume = 0;1394 sound2EnvelopeATL = 0;1395 sound2EnvelopeUpDown = 0;1396 sound2EnvelopeATLReload = 0;1397 sound2Wave = soundWavePattern[2];1399 sound3On = 0;1400 sound3ATL = 0;1401 sound3Skip = 0;1402 sound3Index = 0;1403 sound3Continue = 0;1404 sound3OutputLevel = 0;1405 sound3Last = 0;1406 sound3Bank = 0;1407 sound3DataSize = 0;1408 sound3ForcedOutput = 0;1410 sound4On = 0;1411 sound4Clock = 0;1412 sound4ATL = 0;1413 sound4Skip = 0;1414 sound4Index = 0;1415 sound4ShiftRight = 0x7f;1416 sound4NSteps = 0;1417 sound4CountDown = 0;1418 sound4Continue = 0;1419 sound4EnvelopeVolume = 0;1420 sound4EnvelopeATL = 0;1421 sound4EnvelopeUpDown = 0;1422 sound4EnvelopeATLReload = 0;1424 sound1On = 0;1425 sound2On = 0;1426 sound3On = 0;1427 sound4On = 0;1429 int addr = 0x90;1431 while (addr < 0xA0)1432 {1433 ioMem[addr++] = 0x00;1434 ioMem[addr++] = 0xff;1435 }1437 addr = 0;1438 while (addr < 0x20)1439 {1440 sound3WaveRam[addr++] = 0x00;1441 sound3WaveRam[addr++] = 0xff;1442 }1444 memset(soundFinalWave, 0, soundBufferLen);1446 memset(soundFilter, 0, sizeof(soundFilter));1447 soundEchoIndex = 0;1448 }1450 bool soundInit()1451 {1452 if (systemSoundInit())1453 {1454 memset(soundBuffer[0], 0, 735 * 2);1455 memset(soundBuffer[1], 0, 735 * 2);1456 memset(soundBuffer[2], 0, 735 * 2);1457 memset(soundBuffer[3], 0, 735 * 2);1459 memset(soundFinalWave, 0, soundBufferLen);1461 soundPaused = 1;1462 return true;1463 }1464 return false;1465 }1467 void soundSetQuality(int quality)1468 {1469 if (soundQuality != quality && systemSoundCanChangeQuality())1470 {1471 if (!soundOffFlag)1472 soundShutdown();1473 soundQuality = quality;1474 soundNextPosition = 0;1475 if (!soundOffFlag)1476 soundInit();1477 SOUND_CLOCK_TICKS = USE_TICKS_AS * soundQuality;1478 soundIndex = 0;1479 soundBufferIndex = 0;1480 }1481 else if (soundQuality != quality)1482 {1483 soundNextPosition = 0;1484 SOUND_CLOCK_TICKS = USE_TICKS_AS * soundQuality;1485 soundIndex = 0;1486 soundBufferIndex = 0;1487 }1488 }1490 void soundSaveGame(gzFile gzFile)1491 {1492 soundTicks_int32 = (int32) soundTicks;1493 SOUND_CLOCK_TICKS_int32 = (int32) SOUND_CLOCK_TICKS;1494 soundDSBValue_int32 = (int32) soundDSBValue;1496 utilWriteData(gzFile, soundSaveStruct);1497 utilWriteData(gzFile, soundSaveStructV2);1499 utilGzWrite(gzFile, &soundQuality, sizeof(int32));1500 //utilWriteData(gzFile, soundSaveStructV3);1501 }1503 void soundReadGame(gzFile gzFile, int version)1504 {1505 int32 oldSoundPaused = soundPaused;1506 int32 oldSoundEnableFlag = soundEnableFlag;1507 utilReadData(gzFile, soundSaveStruct);1508 soundPaused = oldSoundPaused;1509 soundEnableFlag = oldSoundEnableFlag;1511 if (version >= SAVE_GAME_VERSION_3)1512 {1513 utilReadData(gzFile, soundSaveStructV2);1514 }1515 else1516 {1517 sound3Bank = (ioMem[NR30] >> 6) & 1;1518 sound3DataSize = (ioMem[NR30] >> 5) & 1;1519 sound3ForcedOutput = (ioMem[NR32] >> 7) & 1;1520 // nothing better to do here...1521 memcpy(&sound3WaveRam[0x00], &ioMem[0x90], 0x10);1522 memcpy(&sound3WaveRam[0x10], &ioMem[0x90], 0x10);1523 }1524 soundBufferIndex = soundIndex * 2;1526 int quality = 1;1527 utilGzRead(gzFile, &quality, sizeof(int32));1528 soundSetQuality(quality);1530 sound1Wave = soundWavePattern[ioMem[NR11] >> 6];1531 sound2Wave = soundWavePattern[ioMem[NR21] >> 6];1533 //if(version >= SAVE_GAME_VERSION_14) {1534 // utilReadData(gzFile, soundSaveStructV3);1535 //}1536 //else {1537 soundTicks = (soundtick_t) soundTicks_int32;1538 SOUND_CLOCK_TICKS = (soundtick_t) SOUND_CLOCK_TICKS_int32;1539 //}1540 soundDSBValue = (u8) (soundDSBValue_int32 & 0xff);1541 }