ASM-accurate Sound.cpp and Organya.cpp (except for one function)

This commit is contained in:
Clownacy 2019-08-28 07:55:42 +01:00
parent e67c1e3640
commit 470c5d86d5
7 changed files with 1207 additions and 714 deletions

View file

@ -34,7 +34,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib" AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
OutputFile="$(OutDir)\$(ProjectName).exe" OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="" AdditionalLibraryDirectories=""
@ -85,7 +85,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib" AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
OutputFile="$(OutDir)\$(ProjectName).exe" OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="1" LinkIncremental="1"
IgnoreAllDefaultLibraries="FALSE" IgnoreAllDefaultLibraries="FALSE"
@ -135,7 +135,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib" AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
OutputFile="$(OutDir)\$(ProjectName).exe" OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="1" LinkIncremental="1"
IgnoreAllDefaultLibraries="FALSE" IgnoreAllDefaultLibraries="FALSE"
@ -186,7 +186,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib" AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
OutputFile="$(OutDir)\$(ProjectName).exe" OutputFile="$(OutDir)\$(ProjectName).exe"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="" AdditionalLibraryDirectories=""

View file

@ -963,6 +963,10 @@ addr = 0x41A5D0
name = "LoadTimeCounter" name = "LoadTimeCounter"
addr = 0x41A7C0 addr = 0x41A7C0
[[func]]
name = "MakeSoundObject8"
addr = 0x41A8F0
[[func]] [[func]]
name = "ChangeOrganFrequency" name = "ChangeOrganFrequency"
addr = 0x41ABA0 addr = 0x41ABA0
@ -983,7 +987,7 @@ name = "PlayOrganObject"
addr = 0x41ADC0 addr = 0x41ADC0
[[func]] [[func]]
name = "ReleaseOrganya" name = "ReleaseOrganyaObject"
addr = 0x41B2A0 addr = 0x41B2A0
[[func]] [[func]]
@ -1010,6 +1014,95 @@ addr = 0x41B4D0
name = "PlayDramObject" name = "PlayDramObject"
addr = 0x41B510 addr = 0x41B510
[[func]]
name = "OrgData::OrgData"
addr = 0x41B600
[[func]]
name = "OrgData::InitOrgData"
addr = 0x41B650
[[func]]
name = "OrgData::SetMusicInfo"
addr = 0x41B730
[[func]]
name = "OrgData::NoteAlloc"
addr = 0x41B890
[[func]]
name = "OrgData::ReleaseNote"
addr = 0x41BA70
[[func]]
name = "OrgData::InitMusicData"
addr = 0x41BAD0
[[func]]
name = "OrgData::GetMusicInfo"
addr = 0x41C0B0
[[func]]
name = "InitMMTimer"
addr = 0x41C180
[[func]]
name = "StartTimer"
addr = 0x41C1E0
size = 0x4A
[[func]]
name = "TimerProc"
addr = 0x41C230
[[func]]
name = "QuitMMTimer"
addr = 0x41C250
[[func]]
name = "OrgData::PlayData"
addr = 0x41C2B0
[[func]]
name = "OrgData::SetPlayPointer"
addr = 0x41C630
[[func]]
name = "StartOrganya"
addr = 0x41C6C0
[[func]]
name = "LoadOrganya"
addr = 0x41C6F0
[[func]]
name = "SetOrganyaPosition"
addr = 0x41C730
[[func]]
name = "GetOrganyaPosition"
addr = 0x41C770
[[func]]
name = "PlayOrganyaMusic"
addr = 0x41C790
[[func]]
name = "ChangeOrganyaVolume"
addr = 0x41C7C0
[[func]]
name = "StopOrganyaMusic"
addr = 0x41C7F0
[[func]]
name = "SetOrganyaFadeout"
addr = 0x41C880
[[func]]
name = "EndOrganya"
addr = 0x41C890
[[func]] [[func]]
name = "MakeWaveTables" name = "MakeWaveTables"
addr = 0x41C8F0 addr = 0x41C8F0
@ -1106,6 +1199,22 @@ addr = 0x41FA10
name = "ShootBullet" name = "ShootBullet"
addr = 0x41FE70 addr = 0x41FE70
[[func]]
name = "InitDirectSound"
addr = 0x4200C0
[[func]]
name = "EndDirectSound"
addr = 0x4201A0
[[func]]
name = "InitSoundObject"
addr = 0x420240
[[func]]
name = "LoadSoundObject"
addr = 0x420390
[[func]] [[func]]
name = "PlaySoundObject" name = "PlaySoundObject"
addr = 0x420640 addr = 0x420640
@ -1125,6 +1234,10 @@ name = "ChangeSoundPan"
addr = 0x4207A0 addr = 0x4207A0
size = 0x36 size = 0x36
[[func]]
name = "MakePixToneObject"
addr = 0x4207E0
[[func]] [[func]]
name = "TransferStage" name = "TransferStage"
addr = 0x420BE0 addr = 0x420BE0

View file

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include "SDL.h" #include "SDL.h"
#include "SDL_syswm.h"
#include "WindowsWrapper.h" #include "WindowsWrapper.h"
@ -347,11 +348,16 @@ int main(int argc, char *argv[])
CortBox(&clip_rect, 0x000000); CortBox(&clip_rect, 0x000000);
PutBitmap3(&clip_rect, (WINDOW_WIDTH - 64) / 2, (WINDOW_HEIGHT - 8) / 2, &loading_rect, SURFACE_ID_LOADING); PutBitmap3(&clip_rect, (WINDOW_WIDTH - 64) / 2, (WINDOW_HEIGHT - 8) / 2, &loading_rect, SURFACE_ID_LOADING);
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(gWindow, &wmInfo);
ghWnd = wmInfo.info.win.window;
// Draw to screen // Draw to screen
if (Flip_SystemTask(ghWnd)) if (Flip_SystemTask(ghWnd))
{ {
// Initialize sound // Initialize sound
InitDirectSound(); InitDirectSound(ghWnd);
// Initialize joystick // Initialize joystick
if (config.bJoystick && InitDirectInput()) if (config.bJoystick && InitDirectInput())

File diff suppressed because it is too large Load diff

View file

@ -1,57 +1,18 @@
#pragma once #pragma once
#include <dsound.h>
#include "WindowsWrapper.h" #include "WindowsWrapper.h"
//Below are Organya song data structures
struct NOTELIST
{
NOTELIST *from; //Previous address
NOTELIST *to; //Next address
long x; //Position
unsigned char length; //Sound length
unsigned char y; //Sound height
unsigned char volume; //Volume
unsigned char pan;
};
//Track data * 8
struct TRACKDATA
{
unsigned short freq; //Frequency (1000 is default)
unsigned char wave_no; //Waveform No.
signed char pipi;
unsigned short note_num; //Number of notes
NOTELIST *note_p;
NOTELIST *note_list;
};
//Unique information held in songs
struct MUSICINFO
{
unsigned short wait;
BOOL loaded;
BOOL playing;
unsigned char line; //Number of lines in one measure
unsigned char dot; //Number of dots per line
unsigned short alloc_note; //Number of allocated notes
long repeat_x; //Repeat
long end_x; //End of song (Return to repeat)
TRACKDATA tdata[16];
};
BOOL MakeOrganyaWave(signed char track, signed char wave_no, signed char pipi); BOOL MakeOrganyaWave(signed char track, signed char wave_no, signed char pipi);
void OrganyaPlayData(); void OrganyaPlayData();
void SetPlayPointer(long x); void SetPlayPointer(long x);
void LoadOrganya(const char *name); BOOL LoadOrganya(const char *name);
void SetOrganyaPosition(unsigned int x); void SetOrganyaPosition(unsigned int x);
unsigned int GetOrganyaPosition(); unsigned int GetOrganyaPosition();
void PlayOrganyaMusic(); void PlayOrganyaMusic();
BOOL ChangeOrganyaVolume(signed int volume); BOOL ChangeOrganyaVolume(signed int volume);
void StopOrganyaMusic(); void StopOrganyaMusic();
void SetOrganyaFadeout(); void SetOrganyaFadeout();
void OrganyaStartTimer(unsigned int wait); BOOL StartOrganya(LPDIRECTSOUND lpDS, const char *wave_filename);
void OrganyaEndTimer();
void StartOrganya();
void EndOrganya(); void EndOrganya();

View file

@ -1,6 +1,15 @@
// Some of the original source code for this file can be found here: // Some of the original source code for this file can be found here:
// https://github.com/shbow/organya/blob/master/source/Sound.cpp // https://github.com/shbow/organya/blob/master/source/Sound.cpp
/*
TODO - Code style
Pixel's code was *extremely* Windows-centric, to the point of using
things like ZeroMemory and LPCSTR instead of standard things like
memset and const char*. For now, the decompilation is accurate despite
not using these since they're just macros that evaluate to the portable
equivalents.
*/
#include "Sound.h" #include "Sound.h"
#include <math.h> #include <math.h>
@ -8,352 +17,393 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "SDL.h" #include <dsound.h>
#include "WindowsWrapper.h" #include "WindowsWrapper.h"
#include "CommonDefines.h"
#include "Organya.h" #include "Organya.h"
#include "PixTone.h" #include "PixTone.h"
#include "Tags.h"
#define FREQUENCY 44100 #define FREQUENCY 44100
#ifdef RASPBERRY_PI LPDIRECTSOUND lpDS; // DirectSoundオブジェクト (DirectSound object)
#define STREAM_SIZE 0x400 // Larger buffer to prevent stutter LPDIRECTSOUNDBUFFER lpPRIMARYBUFFER; // 一時バッファ (Temporary buffer)
#else LPDIRECTSOUNDBUFFER lpSECONDARYBUFFER[SE_MAX];
#define STREAM_SIZE 0x100 // FREQUENCY/200 rounded to the nearest power of 2 (SDL2 *needs* a power-of-2 buffer size)
#endif
#define clamp(x, y, z) (((x) > (z)) ? (z) : ((x) < (y)) ? (y) : (x)) // DirectSoundの開始 (Starting DirectSound)
BOOL InitDirectSound(HWND hwnd)
//Audio device
SDL_AudioDeviceID audioDevice;
//Keep track of all existing sound buffers
SOUNDBUFFER *soundBuffers;
//Sound buffer code
SOUNDBUFFER::SOUNDBUFFER(size_t bufSize)
{ {
//Lock audio buffer int i;
SDL_LockAudioDevice(audioDevice); DSBUFFERDESC1 dsbd;
//Set parameters // DirectDrawの初期化 (DirectDraw initialization)
size = bufSize; if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
playing = false;
looping = false;
looped = false;
frequency = 0.0;
volume = 1.0;
volume_l = 1.0;
volume_r = 1.0;
samplePosition = 0.0;
//Create waveform buffer
data = new unsigned char[bufSize];
memset(data, 0x80, bufSize);
//Add to buffer list
this->next = soundBuffers;
soundBuffers = this;
//Unlock audio buffer
SDL_UnlockAudioDevice(audioDevice);
}
SOUNDBUFFER::~SOUNDBUFFER()
{
//Lock audio buffer
SDL_LockAudioDevice(audioDevice);
//Free buffer
if (data)
delete[] data;
//Remove from buffer list
for (SOUNDBUFFER **soundBuffer = &soundBuffers; *soundBuffer != NULL; soundBuffer = &(*soundBuffer)->next)
{ {
if (*soundBuffer == this) lpDS = NULL;
{ StartOrganya(lpDS, "Org\\Wave.dat");
*soundBuffer = this->next;
break;
}
}
//Unlock audio buffer
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Release()
{
//TODO: find a better and more stable(?) way to handle this function
delete this;
}
void SOUNDBUFFER::Lock(unsigned char **outBuffer, size_t *outSize)
{
SDL_LockAudioDevice(audioDevice);
if (outBuffer != NULL)
*outBuffer = data;
if (outSize != NULL)
*outSize = size;
}
void SOUNDBUFFER::Unlock()
{
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetCurrentPosition(unsigned long dwNewPosition)
{
SDL_LockAudioDevice(audioDevice);
samplePosition = dwNewPosition;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetFrequency(unsigned long dwFrequency)
{
SDL_LockAudioDevice(audioDevice);
frequency = (double)dwFrequency;
SDL_UnlockAudioDevice(audioDevice);
}
float MillibelToVolume(long lVolume)
{
//Volume is in hundredths of decibels, from 0 to -10000
lVolume = clamp(lVolume, (long)-10000, (long)0);
return (float)pow(10.0, lVolume / 2000.0);
}
void SOUNDBUFFER::SetVolume(long lVolume)
{
SDL_LockAudioDevice(audioDevice);
volume = MillibelToVolume(lVolume);
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetPan(long lPan)
{
SDL_LockAudioDevice(audioDevice);
volume_l = MillibelToVolume(-lPan);
volume_r = MillibelToVolume(lPan);
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Play(bool bLooping)
{
SDL_LockAudioDevice(audioDevice);
playing = true;
looping = bLooping;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Stop()
{
SDL_LockAudioDevice(audioDevice);
playing = false;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Mix(float *buffer, size_t frames)
{
if (!playing) //This sound buffer isn't playing
return;
for (size_t i = 0; i < frames; ++i)
{
const double freqPosition = frequency / FREQUENCY; //This is added to position at the end
//Get the in-between sample this is (linear interpolation)
const float sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 128.0f);
const float sample2 = ((looping || (((size_t)samplePosition) + 1) < size) ? data[(((size_t)samplePosition) + 1) % size] : 128.0f);
//Interpolate sample
const float subPos = (float)fmod(samplePosition, 1.0);
const float sampleA = sample1 + (sample2 - sample1) * subPos;
//Convert sample to float32
const float sampleConvert = (sampleA - 128.0f) / 128.0f;
//Mix
*buffer++ += (float)(sampleConvert * volume * volume_l);
*buffer++ += (float)(sampleConvert * volume * volume_r);
//Increment position
samplePosition += freqPosition;
if (samplePosition >= size)
{
if (looping)
{
samplePosition = fmod(samplePosition, size);
looped = true;
}
else
{
samplePosition = 0.0;
playing = false;
looped = false;
break;
}
}
}
}
//Sound mixer
void AudioCallback(void *userdata, Uint8 *stream, int len)
{
(void)userdata;
float *buffer = (float*)stream;
const size_t frames = len / (sizeof(float) * 2);
//Clear stream
for (size_t i = 0; i < frames * 2; ++i)
buffer[i] = 0.0f;
//Mix sounds to primary buffer
for (SOUNDBUFFER *sound = soundBuffers; sound != NULL; sound = sound->next)
sound->Mix(buffer, frames);
}
//Sound things
SOUNDBUFFER* lpSECONDARYBUFFER[SE_MAX];
BOOL InitDirectSound()
{
//Init sound
SDL_InitSubSystem(SDL_INIT_AUDIO);
//Open audio device
SDL_AudioSpec want, have;
//Set specifications we want
SDL_memset(&want, 0, sizeof(want));
want.freq = FREQUENCY;
want.format = AUDIO_F32;
want.channels = 2;
want.samples = STREAM_SIZE;
want.callback = AudioCallback;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
if (audioDevice == 0)
{
printf("Failed to open audio device\nSDL Error: %s\n", SDL_GetError());
return FALSE; return FALSE;
} }
//Unpause audio device lpDS->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE);
SDL_PauseAudioDevice(audioDevice, 0);
for (unsigned int i = 0; i < SE_MAX; ++i) // 一次バッファの初期化 (Initializing the primary buffer)
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
dsbd.dwSize = sizeof(DSBUFFERDESC1);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpPRIMARYBUFFER, NULL);
for (i = 0; i < SE_MAX; i++)
lpSECONDARYBUFFER[i] = NULL; lpSECONDARYBUFFER[i] = NULL;
//Start organya StartOrganya(lpDS, "Org\\Wave.dat");
StartOrganya();
return TRUE; return TRUE;
} }
void EndDirectSound() // DirectSoundの終了 (Exit DirectSound)
void EndDirectSound(void)
{ {
int i;
if (lpDS == NULL)
return;
EndOrganya(); EndOrganya();
for (unsigned int i = 0; i < SE_MAX; ++i) for (i = 0; i < SE_MAX; i++)
if (lpSECONDARYBUFFER[i]) if (lpSECONDARYBUFFER[i] != NULL)
lpSECONDARYBUFFER[i]->Release(); lpSECONDARYBUFFER[i]->Release();
SDL_QuitSubSystem(SDL_INIT_AUDIO); if (lpPRIMARYBUFFER != NULL)
lpPRIMARYBUFFER->Release();
SDL_CloseAudioDevice(audioDevice); if (lpDS != NULL)
lpDS->Release();
lpDS = NULL;
}
// サウンドの設定 (Sound settings)
BOOL InitSoundObject(LPCSTR resname, int no)
{
HRSRC hrscr;
DSBUFFERDESC1 dsbd;
DWORD *lpdword; // リソースのアドレス (Resource address)
if (lpDS == NULL)
return TRUE;
// リソースの検索 (Search for resources)
if ((hrscr = FindResourceA(NULL, resname, "WAVE")) == NULL)
return FALSE;
// リソースのアドレスを取得 (Get resource address)
lpdword = (DWORD*)LockResource(LoadResource(NULL, hrscr));
// 二次バッファの生成 (Create secondary buffer)
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
dsbd.dwSize = sizeof(DSBUFFERDESC1);
dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbd.dwBufferBytes = *(DWORD*)((BYTE*)lpdword+0x36); // WAVEデータのサイズ (WAVE data size)
dsbd.lpwfxFormat = (LPWAVEFORMATEX)(lpdword+5);
if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
return FALSE;
LPVOID lpbuf1, lpbuf2;
DWORD dwbuf1, dwbuf2;
// 二次バッファのロック (Secondary buffer lock)
lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)lpdword+0x36), &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0);
// 音源データの設定 (Sound source data settings)
CopyMemory(lpbuf1, (BYTE*)lpdword+0x3A, dwbuf1);
if (dwbuf2 != 0)
CopyMemory(lpbuf2, (BYTE*)lpdword+0x3A+dwbuf1, dwbuf2);
// 二次バッファのロック解除 (Unlock secondary buffer)
lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
return TRUE;
}
BOOL LoadSoundObject(LPCSTR file_name, int no)
{
char path[PATH_LENGTH];
DWORD i;
DWORD file_size = 0;
char check_box[58];
FILE *fp;
HANDLE hFile;
sprintf(path, "%s\\%s", gModulePath, file_name);
if (lpDS == NULL)
return TRUE;
hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
file_size = GetFileSize(hFile, NULL);
CloseHandle(hFile);
if ((fp = fopen(path, "rb")) == NULL)
return FALSE;
for (i = 0; i < 58; i++)
fread(&check_box[i], sizeof(char), 1, fp);
if (check_box[0] != 'R')
return FALSE;
if (check_box[1] != 'I')
return FALSE;
if (check_box[2] != 'F')
return FALSE;
if (check_box[3] != 'F')
return FALSE;
DWORD *wp;
wp = (DWORD*)malloc(file_size); // ファイルのワークスペースを作る (Create a file workspace)
fseek(fp, 0, SEEK_SET);
for (i = 0; i < file_size; i++)
fread((BYTE*)wp+i, sizeof(BYTE), 1, fp);
fclose(fp);
// セカンダリバッファの生成 (Create secondary buffer)
DSBUFFERDESC1 dsbd;
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
dsbd.dwSize = sizeof(DSBUFFERDESC1);
dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbd.dwBufferBytes = *(DWORD*)((BYTE*)wp+0x36); // WAVEデータのサイズ (WAVE data size)
dsbd.lpwfxFormat = (LPWAVEFORMATEX)(wp+5);
if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
{
#ifdef FIX_BUGS
free(wp); // The updated Organya source code includes this fix
#endif
return FALSE;
}
LPVOID lpbuf1, lpbuf2;
DWORD dwbuf1, dwbuf2;
HRESULT hr;
hr = lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)wp+0x36), &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0);
if (hr != DS_OK)
{
#ifdef FIX_BUGS
free(wp); // The updated Organya source code includes this fix
#endif
return FALSE;
}
CopyMemory(lpbuf1, (BYTE*)wp+0x3A, dwbuf1); // +3aはデータの頭 (+ 3a is the head of the data)
if (dwbuf2 != 0)
CopyMemory(lpbuf2, (BYTE*)wp+0x3A+dwbuf1, dwbuf2);
lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
free(wp);
return TRUE;
} }
//Sound effects playing
void PlaySoundObject(int no, int mode) void PlaySoundObject(int no, int mode)
{ {
if (lpSECONDARYBUFFER[no]) if (lpDS == NULL)
return;
if (lpSECONDARYBUFFER[no] != NULL)
{ {
switch (mode) switch (mode)
{ {
case 0: case 0: // 停止 (Stop)
lpSECONDARYBUFFER[no]->Stop(); lpSECONDARYBUFFER[no]->Stop();
break; break;
case 1: case 1: // 再生 (Playback)
lpSECONDARYBUFFER[no]->Stop(); lpSECONDARYBUFFER[no]->Stop();
lpSECONDARYBUFFER[no]->SetCurrentPosition(0); lpSECONDARYBUFFER[no]->SetCurrentPosition(0);
lpSECONDARYBUFFER[no]->Play(false); lpSECONDARYBUFFER[no]->Play(0, 0, 0);
break; break;
case -1: case -1:// ループ再生 (Loop playback)
lpSECONDARYBUFFER[no]->Play(true); lpSECONDARYBUFFER[no]->Play(0, 0, DSBPLAY_LOOPING);
break; break;
} }
} }
} }
void ChangeSoundFrequency(int no, unsigned long rate) void ChangeSoundFrequency(int no, DWORD rate) // 100がMIN9999がMAXで2195?がノーマル (100 is MIN, 9999 is MAX, and 2195 is normal)
{ {
if (lpDS == NULL)
return;
lpSECONDARYBUFFER[no]->SetFrequency((rate * 10) + 100); lpSECONDARYBUFFER[no]->SetFrequency((rate * 10) + 100);
} }
void ChangeSoundVolume(int no, long volume) void ChangeSoundVolume(int no, long volume) // 300がMAXで300がノーマル (300 is MAX and 300 is normal)
{ {
if (lpDS == NULL)
return;
lpSECONDARYBUFFER[no]->SetVolume((volume - 300) * 8); lpSECONDARYBUFFER[no]->SetVolume((volume - 300) * 8);
} }
void ChangeSoundPan(int no, long pan) void ChangeSoundPan(int no, long pan) // 512がMAXで256がノーマル (512 is MAX and 256 is normal)
{ {
if (lpDS == NULL)
return;
lpSECONDARYBUFFER[no]->SetPan((pan - 256) * 10); lpSECONDARYBUFFER[no]->SetPan((pan - 256) * 10);
} }
int MakePixToneObject(const PIXTONEPARAMETER *ptp, int ptp_num, int no) int MakePixToneObject(const PIXTONEPARAMETER *ptp, int ptp_num, int no)
{ {
int sample_count = 0; typedef struct WavHeader
for (int i = 0; i < ptp_num; ++i)
{ {
if (ptp[i].size > sample_count) char riff_header[4];
sample_count = ptp[i].size; unsigned long wav_size;
char wav_header[4];
char fmt_header[4];
unsigned long fmt_chunk_size;
unsigned short audio_format;
unsigned short num_channels;
unsigned long sample_rate;
unsigned long byte_rate;
unsigned short sample_alignment;
unsigned short bit_depth;
char data_header[4];
unsigned long data_bytes;
} WavHeader;
int i;
int j;
DSBUFFERDESC1 dsbd;
WavHeader wav_header;
const PIXTONEPARAMETER *ptp_pointer;
int sample_count;
unsigned char *pcm_buffer;
unsigned char *mixed_pcm_buffer;
if (lpDS == NULL)
return 0;
const char *riff = "RIFF";
const char *fmt = "fmt ";
const char *wave = "WAVE";
const char *data = "data";
wav_header.bit_depth = 8;
wav_header.sample_rate = 22050;
wav_header.num_channels = 1;
wav_header.audio_format = WAVE_FORMAT_PCM;
wav_header.fmt_chunk_size = 16;
memcpy(wav_header.riff_header, riff, 4);
memcpy(wav_header.fmt_header, fmt, 4);
memcpy(wav_header.wav_header, wave, 4);
memcpy(wav_header.data_header, data, 4);
wav_header.sample_alignment = (wav_header.bit_depth / 8) * wav_header.num_channels;
wav_header.byte_rate = (wav_header.bit_depth / 8) * wav_header.num_channels * wav_header.sample_rate;
wav_header.data_bytes = wav_header.sample_alignment * ptp->size;
wav_header.wav_size = wav_header.data_bytes + 36;
ptp_pointer = ptp;
sample_count = 0;
for (i = 0; i < ptp_num; i++)
{
if (ptp_pointer->size > sample_count)
sample_count = ptp_pointer->size;
++ptp_pointer;
} }
unsigned char *pcm_buffer = (unsigned char*)malloc(sample_count); ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
unsigned char *mixed_pcm_buffer = (unsigned char*)malloc(sample_count); dsbd.dwSize = sizeof(DSBUFFERDESC1);
memset(pcm_buffer, 0x80, sample_count); dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
memset(mixed_pcm_buffer, 0x80, sample_count); dsbd.dwBufferBytes = sample_count;
dsbd.lpwfxFormat = (WAVEFORMATEX*)&wav_header.audio_format;
for (int i = 0; i < ptp_num; ++i) if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], 0) != DS_OK)
{ return -1;
if (!MakePixelWaveData(&ptp[i], pcm_buffer))
pcm_buffer = mixed_pcm_buffer = NULL;
pcm_buffer = (unsigned char*)malloc(sample_count);
mixed_pcm_buffer = (unsigned char*)malloc(sample_count);
if (pcm_buffer == NULL || mixed_pcm_buffer == NULL)
{ {
if (pcm_buffer != NULL)
free(pcm_buffer); free(pcm_buffer);
if (mixed_pcm_buffer != NULL)
free(mixed_pcm_buffer); free(mixed_pcm_buffer);
return -1; return -1;
} }
for (int j = 0; j < ptp[i].size; ++j) memset(pcm_buffer, 0x80, sample_count);
memset(mixed_pcm_buffer, 0x80, sample_count);
ptp_pointer = ptp;
for (i = 0; i < ptp_num; i++)
{
if (!MakePixelWaveData(ptp_pointer, pcm_buffer))
{
if (pcm_buffer)
free(pcm_buffer);
if (mixed_pcm_buffer)
free(mixed_pcm_buffer);
return -1;
}
for (j = 0; j < ptp_pointer->size; j++)
{ {
if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 < -0x7F) if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 < -0x7F)
mixed_pcm_buffer[j] = 0; mixed_pcm_buffer[j] = 0;
else if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 > 0x7F) else if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 > 0x7F)
mixed_pcm_buffer[j] = 0xFF; mixed_pcm_buffer[j] = 0xFF;
else else
mixed_pcm_buffer[j] += pcm_buffer[j] + -0x80; mixed_pcm_buffer[j] = mixed_pcm_buffer[j] + pcm_buffer[j] - 0x80;
}
} }
lpSECONDARYBUFFER[no] = new SOUNDBUFFER(sample_count); ++ptp_pointer;
}
unsigned char *buf; // Maybe this used to be something to prevent audio popping?
lpSECONDARYBUFFER[no]->Lock(&buf, NULL); mixed_pcm_buffer[0] = mixed_pcm_buffer[0];
memcpy(buf, mixed_pcm_buffer, sample_count); mixed_pcm_buffer[sample_count - 1] = mixed_pcm_buffer[sample_count - 1];
lpSECONDARYBUFFER[no]->Unlock();
lpSECONDARYBUFFER[no]->SetFrequency(22050);
LPVOID lpbuf1, lpbuf2;
DWORD dwbuf1, dwbuf2;
lpSECONDARYBUFFER[no]->Lock(0, sample_count, &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0);
CopyMemory(lpbuf1, mixed_pcm_buffer, dwbuf1);
if (dwbuf2 != 0)
CopyMemory(lpbuf2, mixed_pcm_buffer + dwbuf1, dwbuf2);
lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
if (pcm_buffer != NULL)
free(pcm_buffer); free(pcm_buffer);
if (mixed_pcm_buffer != NULL)
free(mixed_pcm_buffer); free(mixed_pcm_buffer);
return sample_count; return sample_count;

View file

@ -2,52 +2,19 @@
#include <stddef.h> #include <stddef.h>
#include <dsound.h>
#include "WindowsWrapper.h" #include "WindowsWrapper.h"
#include "PixTone.h" #include "PixTone.h"
class SOUNDBUFFER
{
public:
SOUNDBUFFER(size_t bufSize);
~SOUNDBUFFER();
void Release();
void Lock(unsigned char **buffer, size_t *size);
void Unlock();
void SetCurrentPosition(unsigned long dwNewPosition);
void SetFrequency(unsigned long dwFrequency);
void SetVolume(long lVolume);
void SetPan(long lPan);
void Play(bool bLooping);
void Stop();
void Mix(float *buffer, size_t frames);
SOUNDBUFFER *next;
private:
unsigned char *data;
size_t size;
bool playing;
bool looping;
bool looped;
double frequency;
double volume;
double volume_l;
double volume_r;
double samplePosition;
};
#define SE_MAX 160 // According to the Organya source code release, this is the real name for this constant #define SE_MAX 160 // According to the Organya source code release, this is the real name for this constant
extern SOUNDBUFFER* lpSECONDARYBUFFER[SE_MAX];
BOOL InitDirectSound(); extern LPDIRECTSOUND lpDS;
void EndDirectSound(); extern LPDIRECTSOUNDBUFFER lpSECONDARYBUFFER[SE_MAX];
BOOL InitDirectSound(HWND hwnd);
void EndDirectSound(void);
void PlaySoundObject(int no, int mode); void PlaySoundObject(int no, int mode);
void ChangeSoundFrequency(int no, unsigned long rate); void ChangeSoundFrequency(int no, unsigned long rate);
void ChangeSoundVolume(int no, long volume); void ChangeSoundVolume(int no, long volume);