wii7800/src/Sound.cpp
Chris Smith 3e4adaee79
Xm and more (#17)
* Added partial XM support
Added POT support to Pokey
Modifed Pokey and TIA Buffers
Fixed issue where pokey counter was not being reset
Added temporary hack to get Pac320 to work (may cause issues)

* Added Pokey @450 support
Added Support for carts about 144k
Improved cart detection (via header and by size)
Fixed issue occurring when Kangaroo and Holey were enabled (caused
backgroud to be displayed causing large black squares)

* Added ability to edit cartridge DB in UI
Added disable bios, left/right switch, swap buttons, pokey@450, and xm
to cartridge database.
Fixed Pokey pops that were occurring
Removed WSYNC, cycle stealing, and swap buttons from global settings

* Fixed bug with cart db UI and dual analog

* Added XM to save states

* Defaults to latest save state when loading cart

* Minor menu fix (able to select spacer)

* Reorganized advanced menu

* Added whether cart was loaded from db in debug

* Temporarily disable BIOS support
Will enable once issue is resolved

* Reduced TIA volume slightly

* Fixed controller for crossbow and alien brigade

* Added Bentley Bear's Crystal Quest to DB

* Bank switching fixes, new cart type
Fixed 64k cart bank switching when specifying out of range bank
Added new cartridge mode "Standard RAM". 64k or less w/ RAM at $4000
Removed global high score cart setting
Added per-cartridge setting for HSC (default to header value)

* Updates to prosystem database
Cartridge size uses file size (vs. header)
Default controllers to joysticks
Fix database load issue (sometimes read into next entry)
Added default cart title (when not in header or DB)
Added another default screen size
Fixed vsync issue (caused stutter, mostly on PAL titles)

* Many homebrew additions to cart database
Fixed issue where some IM hacks were not loading
Updated db editor to always write out pokey450 and XM settings

* More cart database entries

* Updated readme files and images for 0.5 release

* Updated readme

* Updated release date
2020-03-24 19:30:12 -07:00

244 lines
7.9 KiB
C++

// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Sound.cpp
// ----------------------------------------------------------------------------
#include "Sound.h"
#include "ProSystem.h"
#include <SDL.h>
#include "wii_direct_sound.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define SOUND_SOURCE "Sound.cpp"
int wii_sound_length = 0;
int wii_convert_length = 0;
#define MAX_BUFFER_SIZE 8192
/* LUDO: */
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef struct {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
# define WAVE_FORMAT_PCM 0
static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 48000, 48000, 1, 8, 0};
static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT;
static bool sound_muted = false;
static void wii_storeSound( byte* sample, int length )
{
PlaySound( (u8*)sample, length );
}
// ----------------------------------------------------------------------------
// GetSampleLength
// ----------------------------------------------------------------------------
static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) {
uint sampleLength = length / unitMax;
uint sampleRemain = length % unitMax;
if(sampleRemain != 0 && sampleRemain >= unit) {
sampleLength++;
}
return sampleLength;
}
// ----------------------------------------------------------------------------
// Resample
// ----------------------------------------------------------------------------
static void sound_Resample(const byte* source, byte* target, int length) {
int measurement = sound_format.nSamplesPerSec;
int sourceIndex = 0;
int targetIndex = 0;
int max = ((prosystem_frequency * prosystem_scanlines) << 1);
while (targetIndex < length) {
if (measurement >= max) {
target[targetIndex++] = source[sourceIndex];
measurement -= max;
} else {
sourceIndex++;
measurement += sound_format.nSamplesPerSec;
}
}
}
// ----------------------------------------------------------------------------
// Initialize
// ----------------------------------------------------------------------------
bool sound_Initialize() {
InitialiseAudio();
return true;
}
// ----------------------------------------------------------------------------
// SetFormat
// ----------------------------------------------------------------------------
bool sound_SetFormat(WAVEFORMATEX format) {
sound_format = format;
return true;
}
// ----------------------------------------------------------------------------
// Store
// ----------------------------------------------------------------------------
byte sample[MAX_BUFFER_SIZE] = {0};
byte pokeySample[MAX_BUFFER_SIZE] = {0};
#ifdef TRACE_SOUND
static int maxTia = 0, minTia = 0, maxPokey = 0, minPokey = 0;
static u64 sumTia = 0, sumPokey = 0;
static int scount = 0;
static u64 stotalCount = 0;
#endif
bool sound_Store( ) {
bool pokey = (cartridge_pokey || xm_pokey_enabled);
if( sound_muted ) sound_SetMuted( false );
memset( sample, 0, MAX_BUFFER_SIZE );
uint length = 48000 / prosystem_frequency; /* sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); */ /* 48000 / prosystem_frequency */
sound_Resample(tia_buffer, sample, length);
tia_Clear(); // WII
if(pokey) {
memset( pokeySample, 0, MAX_BUFFER_SIZE );
sound_Resample(pokey_buffer, pokeySample, length);
for(uint index = 0; index < length; index++) {
#ifdef TRACE_SOUND
stotalCount++;
if (sample[index] > maxTia) maxTia = sample[index];
if (sample[index] < minTia) minTia = sample[index];
if (pokeySample[index] > maxPokey) maxPokey = pokeySample[index];
if (pokeySample[index] < minPokey) minPokey = pokeySample[index];
sumTia += sample[index];
sumPokey += pokeySample[index];
#endif
u32 sound = sample[index] + pokeySample[index];
sample[index] = sound >> 1;
}
}
else {
for(uint index = 0; index < length; index++) {
#ifdef TRACE_SOUND
stotalCount++;
sumTia += sample[index];
if (sample[index] > maxTia) maxTia = sample[index];
if (sample[index] < minTia) minTia = sample[index];
#endif
sample[index] = sample[index] * 0.75; //>> 1;
}
}
pokey_Clear(); // WII
wii_storeSound( sample, length );
#ifdef TRACE_SOUND
if (scount++ == 60) {
net_print_string(NULL, 0, "Pokey: max %d, min %d, avg: %f (sum:%llu, count:%llu)\n",
maxPokey, minPokey, (sumPokey/(double)stotalCount), sumPokey, stotalCount);
net_print_string(NULL, 0, "TIA: max %d, min %d, avg: %f (sum:%llu, count:%llu)\n",
maxTia, minTia, (sumTia/(double)stotalCount), sumTia, stotalCount);
scount = stotalCount = 0;
maxPokey = minPokey = sumPokey = 0;
maxTia = minTia = sumTia = 0;
}
#endif
return true;
}
// ----------------------------------------------------------------------------
// Play
// ----------------------------------------------------------------------------
bool sound_Play( ) {
ResetAudio();
return true;
}
// ----------------------------------------------------------------------------
// Stop
// ----------------------------------------------------------------------------
bool sound_Stop( ) {
StopAudio();
return true;
}
// ----------------------------------------------------------------------------
// SetSampleRate
// ----------------------------------------------------------------------------
bool sound_SetSampleRate(uint rate) {
sound_format.nSamplesPerSec = rate;
sound_format.nAvgBytesPerSec = rate;
return sound_SetFormat(sound_format);
}
// ----------------------------------------------------------------------------
// GetSampleRate
// ----------------------------------------------------------------------------
uint sound_GetSampleRate( ) {
return sound_format.nSamplesPerSec;
}
// ----------------------------------------------------------------------------
// SetMuted
// ----------------------------------------------------------------------------
bool sound_SetMuted(bool muted) {
if(sound_muted != muted) {
if(!muted) {
if(!sound_Play( )) {
return false;
}
}
else {
if(!sound_Stop( )) {
return false;
}
}
sound_muted = muted;
}
return true;
}
// ----------------------------------------------------------------------------
// IsMuted
// ----------------------------------------------------------------------------
bool sound_IsMuted( ) {
return sound_muted;
}