Add support for a (munte) mockingboard.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
fd9b2184bf
commit
259428a946
21 changed files with 630 additions and 60 deletions
|
@ -1,6 +1,9 @@
|
|||
include(FindPkgConfig)
|
||||
|
||||
add_library(appleii SHARED
|
||||
AY8910.cpp
|
||||
Mockingboard.cpp
|
||||
|
||||
Pravets.cpp
|
||||
Tape.cpp
|
||||
YamlHelper.cpp
|
||||
|
@ -25,6 +28,7 @@ add_library(appleii SHARED
|
|||
CardManager.cpp
|
||||
Disk2CardManager.cpp
|
||||
SaveState.cpp # uses g_CardMgr in m_ConfigNew (reverse order)
|
||||
Riff.cpp
|
||||
|
||||
linux/windows/memory.cpp
|
||||
linux/windows/handles.cpp
|
||||
|
@ -37,6 +41,7 @@ add_library(appleii SHARED
|
|||
linux/windows/misc.cpp
|
||||
linux/windows/winbase.cpp
|
||||
linux/windows/winuser.cpp
|
||||
linux/windows/dsound.cpp
|
||||
|
||||
linux/data.cpp
|
||||
linux/benchmark.cpp
|
||||
|
@ -47,7 +52,7 @@ add_library(appleii SHARED
|
|||
|
||||
linux/duplicates/Debug.cpp
|
||||
linux/duplicates/Video.cpp
|
||||
linux/duplicates/Mockingboard.cpp
|
||||
linux/duplicates/SoundCore.cpp
|
||||
linux/duplicates/Joystick.cpp
|
||||
linux/duplicates/Frame.cpp
|
||||
linux/duplicates/SerialComms.cpp
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "StdAfx.h"
|
||||
|
||||
#include "qapple.h"
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
|
|
|
@ -96,25 +96,6 @@ namespace
|
|||
REGSAVE(slotText.c_str(), (DWORD)newCardType);
|
||||
}
|
||||
|
||||
const std::vector<eApple2Type> computerTypes = {A2TYPE_APPLE2, A2TYPE_APPLE2PLUS, A2TYPE_APPLE2JPLUS, A2TYPE_APPLE2E,
|
||||
A2TYPE_APPLE2EENHANCED, A2TYPE_PRAVETS82, A2TYPE_PRAVETS8M, A2TYPE_PRAVETS8A,
|
||||
A2TYPE_TK30002E};
|
||||
|
||||
int getApple2ComputerType()
|
||||
{
|
||||
const eApple2Type type = GetApple2Type();
|
||||
const auto it = std::find(computerTypes.begin(), computerTypes.end(), type);
|
||||
if (it != computerTypes.end())
|
||||
{
|
||||
return std::distance(computerTypes.begin(), it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// default to A2E
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GlobalOptions::GlobalOptions()
|
||||
|
@ -222,11 +203,11 @@ void getAppleWinPreferences(PreferenceData & data)
|
|||
}
|
||||
|
||||
data.enhancedSpeed = pDisk2Card->GetEnhanceDisk();
|
||||
data.mouseInSlot4 = g_CardMgr.QuerySlot(SLOT4) == CT_MouseInterface;
|
||||
data.cpmInSlot5 = g_CardMgr.QuerySlot(SLOT5) == CT_Z80;
|
||||
data.cardInSlot4 = g_CardMgr.QuerySlot(SLOT4);
|
||||
data.cardInSlot5 = g_CardMgr.QuerySlot(SLOT5);
|
||||
data.hdInSlot7 = HD_CardIsEnabled();
|
||||
|
||||
data.apple2Type = getApple2ComputerType();
|
||||
data.apple2Type = GetApple2Type();
|
||||
|
||||
const std::string & saveState = Snapshot_GetFilename();
|
||||
if (!saveState.empty())
|
||||
|
@ -247,22 +228,19 @@ void setAppleWinPreferences(const PreferenceData & currentData, const Preference
|
|||
|
||||
if (currentData.apple2Type != newData.apple2Type)
|
||||
{
|
||||
const eApple2Type type = computerTypes[newData.apple2Type];
|
||||
SetApple2Type(type);
|
||||
REGSAVE(TEXT(REGVALUE_APPLE2_TYPE), type);
|
||||
const eCpuType cpu = ProbeMainCpuDefault(type);
|
||||
SetApple2Type(newData.apple2Type);
|
||||
REGSAVE(TEXT(REGVALUE_APPLE2_TYPE), newData.apple2Type);
|
||||
const eCpuType cpu = ProbeMainCpuDefault(newData.apple2Type);
|
||||
SetMainCpu(cpu);
|
||||
REGSAVE(TEXT(REGVALUE_CPU_TYPE), cpu);
|
||||
}
|
||||
if (currentData.mouseInSlot4 != newData.mouseInSlot4)
|
||||
if (currentData.cardInSlot4 != newData.cardInSlot4)
|
||||
{
|
||||
const SS_CARDTYPE card = newData.mouseInSlot4 ? CT_MouseInterface : CT_Empty;
|
||||
SetSlot(SLOT4, card);
|
||||
SetSlot(SLOT4, newData.cardInSlot4);
|
||||
}
|
||||
if (currentData.cpmInSlot5 != newData.cpmInSlot5)
|
||||
if (currentData.cardInSlot5 != newData.cardInSlot5)
|
||||
{
|
||||
const SS_CARDTYPE card = newData.cpmInSlot5 ? CT_Z80 : CT_Empty;
|
||||
SetSlot(SLOT5, card);
|
||||
SetSlot(SLOT5, newData.cardInSlot5);
|
||||
}
|
||||
if (currentData.hdInSlot7 != newData.hdInSlot7)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef CONFIGURATION_H
|
||||
#define CONFIGURATION_H
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Card.h"
|
||||
#include "Common.h"
|
||||
#include "preferences.h"
|
||||
|
||||
class GlobalOptions
|
||||
|
@ -29,9 +32,9 @@ struct PreferenceData
|
|||
{
|
||||
GlobalOptions options;
|
||||
|
||||
int apple2Type;
|
||||
bool mouseInSlot4;
|
||||
bool cpmInSlot5;
|
||||
eApple2Type apple2Type;
|
||||
SS_CARDTYPE cardInSlot4;
|
||||
SS_CARDTYPE cardInSlot5;
|
||||
bool hdInSlot7;
|
||||
bool hz50;
|
||||
|
||||
|
|
|
@ -118,6 +118,26 @@ namespace
|
|||
item->addChildren(items);
|
||||
}
|
||||
|
||||
const std::vector<eApple2Type> computerTypes = {A2TYPE_APPLE2, A2TYPE_APPLE2PLUS, A2TYPE_APPLE2JPLUS, A2TYPE_APPLE2E,
|
||||
A2TYPE_APPLE2EENHANCED, A2TYPE_PRAVETS82, A2TYPE_PRAVETS8M, A2TYPE_PRAVETS8A,
|
||||
A2TYPE_TK30002E};
|
||||
const std::vector<SS_CARDTYPE> cardsInSlot4 = {CT_Empty, CT_MouseInterface, CT_MockingboardC, CT_Phasor};
|
||||
const std::vector<SS_CARDTYPE> cardsInSlot5 = {CT_Empty, CT_Z80, CT_MockingboardC, CT_SAM};
|
||||
|
||||
template<class T>
|
||||
int getIndexInList(const std::vector<T> & values, const T value, const int defaultValue)
|
||||
{
|
||||
const auto it = std::find(values.begin(), values.end(), value);
|
||||
if (it != values.end())
|
||||
{
|
||||
return std::distance(values.begin(), it);
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Preferences::Preferences(QWidget *parent) :
|
||||
|
@ -193,9 +213,16 @@ void Preferences::setData(const PreferenceData & data)
|
|||
initialiseDisks(myHDs, data.hds);
|
||||
|
||||
ui->enhanced_speed->setChecked(data.enhancedSpeed);
|
||||
ui->apple2Type->setCurrentIndex(data.apple2Type);
|
||||
ui->mouse_4->setChecked(data.mouseInSlot4);
|
||||
ui->cpm_5->setChecked(data.cpmInSlot5);
|
||||
|
||||
const int apple2Index = getIndexInList(computerTypes, data.apple2Type, 2);
|
||||
ui->apple2Type->setCurrentIndex(apple2Index);
|
||||
|
||||
const int slot4Index = getIndexInList(cardsInSlot4, data.cardInSlot4, 0);
|
||||
ui->slot4_combo->setCurrentIndex(slot4Index);
|
||||
|
||||
const int slot5Index = getIndexInList(cardsInSlot4, data.cardInSlot5, 0);
|
||||
ui->slot5_combo->setCurrentIndex(slot5Index);
|
||||
|
||||
ui->hd_7->setChecked(data.hdInSlot7);
|
||||
|
||||
// synchronise
|
||||
|
@ -234,9 +261,9 @@ PreferenceData Preferences::getData() const
|
|||
fillData(myHDs, data.hds);
|
||||
|
||||
data.enhancedSpeed = ui->enhanced_speed->isChecked();
|
||||
data.apple2Type = ui->apple2Type->currentIndex();
|
||||
data.mouseInSlot4 = ui->mouse_4->isChecked();
|
||||
data.cpmInSlot5 = ui->cpm_5->isChecked();
|
||||
data.apple2Type = computerTypes[ui->apple2Type->currentIndex()];
|
||||
data.cardInSlot4 = cardsInSlot4[ui->slot4_combo->currentIndex()];
|
||||
data.cardInSlot5 = cardsInSlot5[ui->slot5_combo->currentIndex()];
|
||||
data.hdInSlot7 = ui->hd_7->isChecked();
|
||||
|
||||
data.saveState = ui->save_state->text();
|
||||
|
@ -339,3 +366,39 @@ void Preferences::on_colorButton_clicked()
|
|||
myMonochromeColor = dialog.currentColor();
|
||||
}
|
||||
}
|
||||
|
||||
void Preferences::on_slot4_combo_activated(int index)
|
||||
{
|
||||
const SS_CARDTYPE slot4Card = cardsInSlot4[index];
|
||||
if (slot4Card == CT_MockingboardC)
|
||||
{
|
||||
const int slot5Index = getIndexInList(cardsInSlot5, CT_MockingboardC, 0);
|
||||
ui->slot5_combo->setCurrentIndex(slot5Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
const SS_CARDTYPE slot5Card = cardsInSlot5[ui->slot5_combo->currentIndex()];
|
||||
if (slot5Card == CT_MockingboardC)
|
||||
{
|
||||
ui->slot5_combo->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Preferences::on_slot5_combo_activated(int index)
|
||||
{
|
||||
const SS_CARDTYPE slot5Card = cardsInSlot5[index];
|
||||
if (slot5Card == CT_MockingboardC)
|
||||
{
|
||||
const int slot4Index = getIndexInList(cardsInSlot4, CT_MockingboardC, 0);
|
||||
ui->slot4_combo->setCurrentIndex(slot4Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
const SS_CARDTYPE slot4Card = cardsInSlot4[ui->slot4_combo->currentIndex()];
|
||||
if (slot4Card == CT_MockingboardC)
|
||||
{
|
||||
ui->slot4_combo->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,10 @@ private slots:
|
|||
|
||||
void on_colorButton_clicked();
|
||||
|
||||
void on_slot4_combo_activated(int index);
|
||||
|
||||
void on_slot5_combo_activated(int index);
|
||||
|
||||
private:
|
||||
std::vector<QComboBox *> myDisks;
|
||||
std::vector<QComboBox *> myHDs;
|
||||
|
|
|
@ -47,13 +47,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="mouse_4">
|
||||
<property name="text">
|
||||
<string>Mouse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
|
@ -61,13 +54,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="cpm_5">
|
||||
<property name="text">
|
||||
<string>CP/M</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
|
@ -132,6 +118,54 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="slot4_combo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Empty</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mouse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mockingboard</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Phasor</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="slot5_combo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Empty</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>CP/M</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mockingboard</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SAM/DAC</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -12,11 +12,14 @@
|
|||
#include "Frame.h"
|
||||
#include "Memory.h"
|
||||
#include "LanguageCard.h"
|
||||
#include "Mockingboard.h"
|
||||
#include "MouseInterface.h"
|
||||
#include "ParallelPrinter.h"
|
||||
#include "Video.h"
|
||||
#include "SoundCore.h"
|
||||
#include "NTSC.h"
|
||||
#include "SaveState.h"
|
||||
#include "Riff.h"
|
||||
|
||||
#include "linux/data.h"
|
||||
#include "linux/benchmark.h"
|
||||
|
@ -44,6 +47,10 @@ namespace
|
|||
|
||||
void initialiseEmulator()
|
||||
{
|
||||
#ifdef RIFF_MB
|
||||
RiffInitWriteFile("/tmp/Mockingboard.wav", 44100, 2);
|
||||
#endif
|
||||
|
||||
g_fh = fopen("/tmp/applewin.txt", "w");
|
||||
setbuf(g_fh, nullptr);
|
||||
|
||||
|
@ -94,6 +101,8 @@ namespace
|
|||
break;
|
||||
}
|
||||
|
||||
DSInit();
|
||||
MB_Initialize();
|
||||
MemInitialize();
|
||||
VideoInitialize();
|
||||
|
||||
|
@ -111,6 +120,8 @@ namespace
|
|||
pMouseCard->Reset();
|
||||
}
|
||||
MemDestroy();
|
||||
MB_Destroy();
|
||||
DSUninit();
|
||||
}
|
||||
|
||||
void uninitialiseEmulator()
|
||||
|
@ -121,8 +132,8 @@ namespace
|
|||
|
||||
g_CardMgr.GetDisk2CardMgr().Destroy();
|
||||
ImageDestroy();
|
||||
fclose(g_fh);
|
||||
g_fh = nullptr;
|
||||
LogDone();
|
||||
RiffFinishWriteFile();
|
||||
}
|
||||
|
||||
qint64 emulatorTimeInMS()
|
||||
|
@ -315,6 +326,8 @@ void QApple::on_timer()
|
|||
const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
|
||||
g_dwCyclesThisFrame += uActualCyclesExecuted;
|
||||
g_CardMgr.GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted);
|
||||
MB_PeriodicUpdate(uActualCyclesExecuted);
|
||||
|
||||
// in case we run more than 1 frame
|
||||
g_dwCyclesThisFrame = g_dwCyclesThisFrame % dwClksPerFrame;
|
||||
++count;
|
||||
|
|
|
@ -61,6 +61,9 @@ static IPropertySheet * sg = NULL;
|
|||
IPropertySheet& sg_PropertySheet = *sg;
|
||||
static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
|
||||
|
||||
bool g_bDisableDirectSound = false;
|
||||
bool g_bDisableDirectSoundMockingboard = false;
|
||||
|
||||
void LogFileTimeUntilFirstKeyReadReset(void)
|
||||
{
|
||||
if (!g_fh)
|
||||
|
@ -371,3 +374,8 @@ void LoadConfiguration(void)
|
|||
g_bConfirmReboot = dwTmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
double Get6502BaseClock(void)
|
||||
{
|
||||
return (GetVideoRefreshRate() == VR_50HZ) ? CLK_6502_PAL : CLK_6502_NTSC;
|
||||
}
|
||||
|
|
148
source/linux/duplicates/SoundCore.cpp
Normal file
148
source/linux/duplicates/SoundCore.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "StdAfx.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "SoundCore.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
||||
bool g_bDSAvailable = false;
|
||||
static int g_nErrorInc = 20; // Old: 1
|
||||
|
||||
bool DSZeroVoiceWritableBuffer(PVOICE Voice, const char* pszDevName, DWORD dwBufferSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSReleaseSoundBuffer(VOICE* pVoice)
|
||||
{
|
||||
delete pVoice->lpDSBvoice;
|
||||
pVoice->lpDSBvoice = nullptr;
|
||||
}
|
||||
|
||||
int SoundCore_GetErrorInc()
|
||||
{
|
||||
return g_nErrorInc;
|
||||
}
|
||||
|
||||
LONG NewVolume(DWORD dwVolume, DWORD dwVolumeMax)
|
||||
{
|
||||
float fVol = (float) dwVolume / (float) dwVolumeMax; // 0.0=Max, 1.0=Min
|
||||
|
||||
return (LONG) ((float) DSBVOLUME_MIN * fVol);
|
||||
}
|
||||
|
||||
HRESULT DSGetSoundBuffer(VOICE* pVoice, DWORD dwFlags, DWORD dwBufferSize, DWORD nSampleRate, int nChannels)
|
||||
{
|
||||
IDirectSoundBuffer * dsVoice = new IDirectSoundBuffer;
|
||||
|
||||
dsVoice->flags = dwFlags;
|
||||
dsVoice->bufferSize = dwBufferSize;
|
||||
dsVoice->sampleRate = nSampleRate;
|
||||
dsVoice->channels = nChannels;
|
||||
dsVoice->soundBuffer.resize(dwBufferSize);
|
||||
|
||||
pVoice->lpDSBvoice = dsVoice;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool DSInit()
|
||||
{
|
||||
g_bDSAvailable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void DSUninit()
|
||||
{
|
||||
g_bDSAvailable = false;
|
||||
}
|
||||
|
||||
bool DSZeroVoiceBuffer(PVOICE Voice, const char* pszDevName, DWORD dwBufferSize)
|
||||
{
|
||||
#ifdef NO_DIRECT_X
|
||||
|
||||
return false;
|
||||
|
||||
#else
|
||||
|
||||
DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer
|
||||
SHORT* pDSLockedBuffer;
|
||||
|
||||
_ASSERT(Voice->lpDSBvoice);
|
||||
HRESULT hr = Voice->lpDSBvoice->Stop();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if(g_fh) fprintf(g_fh, "%s: DSStop failed (%08X)\n",pszDevName,hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = DSGetLock(Voice->lpDSBvoice, 0, 0, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, 0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if(g_fh) fprintf(g_fh, "%s: DSGetLock failed (%08X)\n",pszDevName,hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
_ASSERT(dwDSLockedBufferSize == dwBufferSize);
|
||||
memset(pDSLockedBuffer, 0x00, dwDSLockedBufferSize);
|
||||
|
||||
hr = Voice->lpDSBvoice->Unlock((void*)pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if(g_fh) fprintf(g_fh, "%s: DSUnlock failed (%08X)\n",pszDevName,hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = Voice->lpDSBvoice->Play(0,0,DSBPLAY_LOOPING);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if(g_fh) fprintf(g_fh, "%s: DSPlay failed (%08X)\n",pszDevName,hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // NO_DIRECT_X
|
||||
}
|
||||
|
||||
bool DSGetLock(LPDIRECTSOUNDBUFFER pVoice, DWORD dwOffset, DWORD dwBytes,
|
||||
SHORT** ppDSLockedBuffer0, DWORD* pdwDSLockedBufferSize0,
|
||||
SHORT** ppDSLockedBuffer1, DWORD* pdwDSLockedBufferSize1)
|
||||
{
|
||||
DWORD nStatus;
|
||||
HRESULT hr = pVoice->GetStatus(&nStatus);
|
||||
if(hr != DS_OK)
|
||||
return false;
|
||||
|
||||
if(nStatus & DSBSTATUS_BUFFERLOST)
|
||||
{
|
||||
do
|
||||
{
|
||||
hr = pVoice->Restore();
|
||||
if(hr == DSERR_BUFFERLOST)
|
||||
Sleep(10);
|
||||
}
|
||||
while(hr != DS_OK);
|
||||
}
|
||||
|
||||
// Get write only pointer(s) to sound buffer
|
||||
if(dwBytes == 0)
|
||||
{
|
||||
if(FAILED(hr = pVoice->Lock(0, 0,
|
||||
(void**)ppDSLockedBuffer0, pdwDSLockedBufferSize0,
|
||||
(void**)ppDSLockedBuffer1, pdwDSLockedBufferSize1,
|
||||
DSBLOCK_ENTIREBUFFER)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FAILED(hr = pVoice->Lock(dwOffset, dwBytes,
|
||||
(void**)ppDSLockedBuffer0, pdwDSLockedBufferSize0,
|
||||
(void**)ppDSLockedBuffer1, pdwDSLockedBufferSize1,
|
||||
0)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
12
source/linux/duplicates/Speaker.cpp
Normal file
12
source/linux/duplicates/Speaker.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "StdAfx.h"
|
||||
|
||||
#include "YamlHelper.h"
|
||||
#include "Common.h"
|
||||
|
||||
void SpkrLoadSnapshot(YamlLoadHelper&)
|
||||
{
|
||||
}
|
||||
|
||||
void SpkrSaveSnapshot(YamlSaveHelper&)
|
||||
{
|
||||
}
|
|
@ -14,3 +14,5 @@
|
|||
#include "linux/windows/gdi.h"
|
||||
#include "linux/windows/winbase.h"
|
||||
#include "linux/windows/winuser.h"
|
||||
#include "linux/windows/dsound.h"
|
||||
#include "linux/windows/winerror.h"
|
||||
|
|
112
source/linux/windows/dsound.cpp
Normal file
112
source/linux/windows/dsound.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
#include "linux/windows/dsound.h"
|
||||
#include "linux/windows/winerror.h"
|
||||
|
||||
HRESULT IDirectSoundNotify::SetNotificationPositions(DWORD cPositionNotifies, LPCDSBPOSITIONNOTIFY lpcPositionNotifies)
|
||||
{
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
IDirectSoundBuffer::IDirectSoundBuffer(): soundNotify(new IDirectSoundNotify)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::QueryInterface(int riid, void **ppvObject)
|
||||
{
|
||||
if (riid == IID_IDirectSoundNotify)
|
||||
{
|
||||
*ppvObject = soundNotify.get();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::Unlock( LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2 )
|
||||
{
|
||||
const size_t totalWrittenBytes = dwAudioBytes1 + dwAudioBytes2;
|
||||
writePosition = (writePosition + totalWrittenBytes) % this->soundBuffer.size();
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::Stop()
|
||||
{
|
||||
const DWORD mask = DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
|
||||
this->status &= ~mask;
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::SetCurrentPosition( DWORD dwNewPosition )
|
||||
{
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags )
|
||||
{
|
||||
this->status |= DSBSTATUS_PLAYING;
|
||||
if (dwFlags & DSBPLAY_LOOPING)
|
||||
{
|
||||
this->status |= DSBSTATUS_LOOPING;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::SetVolume( LONG lVolume )
|
||||
{
|
||||
this->volume = lVolume;
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::GetStatus( LPDWORD lpdwStatus )
|
||||
{
|
||||
*lpdwStatus = this->status;
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::Restore()
|
||||
{
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID * lplpvAudioPtr1, DWORD * lpdwAudioBytes1, LPVOID * lplpvAudioPtr2, DWORD * lpdwAudioBytes2, DWORD dwFlags )
|
||||
{
|
||||
if (dwFlags & DSBLOCK_ENTIREBUFFER)
|
||||
{
|
||||
*lplpvAudioPtr1 = this->soundBuffer.data();
|
||||
*lpdwAudioBytes1 = this->soundBuffer.size();
|
||||
if (lplpvAudioPtr2 && lpdwAudioBytes2)
|
||||
{
|
||||
*lplpvAudioPtr2 = nullptr;
|
||||
*lpdwAudioBytes2 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const DWORD availableInFirstPart = this->soundBuffer.size() - dwWriteCursor;
|
||||
|
||||
*lplpvAudioPtr1 = this->soundBuffer.data() + dwWriteCursor;
|
||||
*lpdwAudioBytes1 = std::min(availableInFirstPart, dwWriteBytes);
|
||||
|
||||
if (lplpvAudioPtr2 && lpdwAudioBytes2)
|
||||
{
|
||||
if (*lpdwAudioBytes1 < dwWriteBytes)
|
||||
{
|
||||
*lplpvAudioPtr2 = this->soundBuffer.data();
|
||||
*lpdwAudioBytes2 = std::min(dwWriteCursor, dwWriteBytes - *lpdwAudioBytes1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*lplpvAudioPtr2 = nullptr;
|
||||
*lpdwAudioBytes2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
HRESULT IDirectSoundBuffer::GetCurrentPosition( LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor )
|
||||
{
|
||||
*lpdwCurrentPlayCursor = this->writePosition;
|
||||
*lpdwCurrentWriteCursor = this->writePosition;
|
||||
return DS_OK;
|
||||
}
|
79
source/linux/windows/dsound.h
Normal file
79
source/linux/windows/dsound.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include "linux/windows/winbase.h"
|
||||
#include "linux/windows/winerror.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#define IID_IDirectSoundNotify 1234
|
||||
#define DS_OK 0
|
||||
#define DSBPN_OFFSETSTOP -1
|
||||
|
||||
#define DSBCAPS_CTRLVOLUME 0x00000080
|
||||
#define DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100
|
||||
#define DSBCAPS_LOCSOFTWARE 0x00000008
|
||||
|
||||
#define DSBVOLUME_MIN -10000
|
||||
#define DSBVOLUME_MAX 0
|
||||
|
||||
#define DSBPLAY_LOOPING 0x00000001
|
||||
|
||||
#define DSBSTATUS_PLAYING 0x00000001
|
||||
#define DSBSTATUS_BUFFERLOST 0x00000002
|
||||
#define DSBSTATUS_LOOPING 0x00000004
|
||||
|
||||
#define DSERR_BUFFERLOST MAKE_DSHRESULT(150)
|
||||
|
||||
#define DSBLOCK_ENTIREBUFFER 0x00000002
|
||||
|
||||
#define _FACDS 0x878
|
||||
#define MAKE_DSHRESULT(code) MAKE_HRESULT(1,_FACDS,code)
|
||||
|
||||
typedef struct _DSBPOSITIONNOTIFY
|
||||
{
|
||||
DWORD dwOffset;
|
||||
HANDLE hEventNotify;
|
||||
} DSBPOSITIONNOTIFY,*LPDSBPOSITIONNOTIFY;
|
||||
typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;
|
||||
|
||||
struct IDirectSoundNotify
|
||||
{
|
||||
HRESULT SetNotificationPositions(DWORD cPositionNotifies, LPCDSBPOSITIONNOTIFY lpcPositionNotifies);
|
||||
};
|
||||
typedef struct IDirectSoundNotify *LPDIRECTSOUNDNOTIFY,**LPLPDIRECTSOUNDNOTIFY;
|
||||
|
||||
struct IDirectSoundBuffer
|
||||
{
|
||||
std::unique_ptr<IDirectSoundNotify> soundNotify;
|
||||
std::vector<SHORT> soundBuffer;
|
||||
|
||||
size_t playPosition = 0;
|
||||
size_t writePosition = 0;
|
||||
|
||||
LONG volume = DSBVOLUME_MIN;
|
||||
DWORD flags = 0;
|
||||
DWORD bufferSize = 0;
|
||||
DWORD sampleRate = 0;
|
||||
WORD status = 0;
|
||||
int channels = 0;
|
||||
|
||||
IDirectSoundBuffer();
|
||||
|
||||
HRESULT QueryInterface(int riid, void **ppvObject);
|
||||
|
||||
HRESULT SetCurrentPosition( DWORD dwNewPosition );
|
||||
HRESULT GetCurrentPosition( LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor );
|
||||
|
||||
HRESULT Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID * lplpvAudioPtr1, DWORD * lpdwAudioBytes1, LPVOID * lplpvAudioPtr2, DWORD * lpdwAudioBytes2, DWORD dwFlags );
|
||||
HRESULT Unlock( LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2 );
|
||||
|
||||
HRESULT Stop();
|
||||
HRESULT Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags );
|
||||
|
||||
HRESULT SetVolume( LONG lVolume );
|
||||
|
||||
HRESULT GetStatus( LPDWORD lpdwStatus );
|
||||
HRESULT Restore();
|
||||
};
|
||||
typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER,**LPLPDIRECTSOUNDBUFFER;
|
|
@ -85,7 +85,7 @@ HANDLE CreateFile(LPCTSTR lpFileName,
|
|||
HANDLE hTemplateFile)
|
||||
{
|
||||
FILE * f = nullptr;
|
||||
if (dwCreationDisposition == CREATE_NEW)
|
||||
if (dwCreationDisposition == CREATE_NEW || dwCreationDisposition == CREATE_ALWAYS)
|
||||
{
|
||||
if (dwDesiredAccess & GENERIC_READ)
|
||||
f = fopen(lpFileName, "w+");
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct tagOFN {
|
|||
#define OFN_FILEMUSTEXIST 0x00001000
|
||||
#define OPEN_EXISTING 3
|
||||
#define CREATE_NEW 1
|
||||
#define CREATE_ALWAYS 2
|
||||
|
||||
#define GENERIC_READ 0x80000000
|
||||
#define GENERIC_WRITE 0x40000000
|
||||
|
|
|
@ -22,6 +22,7 @@ void strcpy_s(char * dest, size_t size, const char * source);
|
|||
#define _tcscpy strcpy
|
||||
#define _snprintf snprintf
|
||||
#define wsprintf sprintf
|
||||
#define sscanf_s sscanf
|
||||
|
||||
inline bool IsCharLower(char ch) {
|
||||
return isascii(ch) && islower(ch);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
DWORD WINAPI GetLastError(void)
|
||||
{
|
||||
|
@ -26,10 +28,54 @@ void LeaveCriticalSection(CRITICAL_SECTION * criticalSection)
|
|||
|
||||
void OutputDebugString(const char * str)
|
||||
{
|
||||
std::cerr << str << std::endl;
|
||||
std::cerr << str;
|
||||
}
|
||||
|
||||
void ExitProcess(int status)
|
||||
{
|
||||
exit(status);
|
||||
}
|
||||
|
||||
DWORD WINAPI WaitForMultipleObjects(DWORD,const HANDLE*,BOOL,DWORD)
|
||||
{
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
BOOL WINAPI GetExitCodeThread(HANDLE,LPDWORD code)
|
||||
{
|
||||
*code = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI SetEvent(HANDLE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID WINAPI Sleep(DWORD ms)
|
||||
{
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
BOOL WINAPI SetThreadPriority(HANDLE,INT)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE WINAPI CreateEvent(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)
|
||||
{
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES,SIZE_T,LPTHREAD_START_ROUTINE,LPVOID,DWORD,LPDWORD)
|
||||
{
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*counter)
|
||||
{
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
|
||||
counter->QuadPart = ms.count();
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,46 @@
|
|||
#include "linux/windows/wincompat.h"
|
||||
#include "linux/windows/handles.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
DWORD WINAPI GetLastError(void);
|
||||
void DeleteCriticalSection(CRITICAL_SECTION * criticalSection);
|
||||
void InitializeCriticalSection(CRITICAL_SECTION * criticalSection);
|
||||
void EnterCriticalSection(CRITICAL_SECTION * criticalSection);
|
||||
void LeaveCriticalSection(CRITICAL_SECTION * criticalSection);
|
||||
void OutputDebugString(const char * str);
|
||||
|
||||
#define INFINITE 0xFFFFFFFF
|
||||
#define WAIT_OBJECT_0 0
|
||||
#define WAIT_FAILED 0xffffffff
|
||||
#define STATUS_PENDING 0x00000103
|
||||
#define STILL_ACTIVE STATUS_PENDING
|
||||
|
||||
|
||||
#define THREAD_BASE_PRIORITY_LOWRT 15
|
||||
#define THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT
|
||||
|
||||
typedef DWORD (CALLBACK *LPTHREAD_START_ROUTINE)(LPVOID);
|
||||
typedef size_t SIZE_T;
|
||||
|
||||
BOOL WINAPI SetThreadPriority(HANDLE,INT);
|
||||
DWORD WINAPI WaitForMultipleObjects(DWORD,const HANDLE*,BOOL,DWORD);
|
||||
BOOL WINAPI GetExitCodeThread(HANDLE,LPDWORD);
|
||||
BOOL WINAPI SetEvent(HANDLE);
|
||||
VOID WINAPI Sleep(DWORD);
|
||||
HANDLE WINAPI CreateEvent(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR);
|
||||
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES,SIZE_T,LPTHREAD_START_ROUTINE,LPVOID,DWORD,LPDWORD);
|
||||
|
||||
typedef union _LARGE_INTEGER {
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
} DUMMYSTRUCTNAME;
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
} u;
|
||||
LONGLONG QuadPart;
|
||||
} LARGE_INTEGER;
|
||||
|
||||
BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*);
|
||||
|
|
|
@ -37,6 +37,8 @@ typedef signed short INT16; // why there was char instead of short? --bb ??????
|
|||
typedef unsigned short UINT16; // why there was char instead of short? --bb ??????????????????? 0_0
|
||||
#define __int64 long long
|
||||
|
||||
typedef long long LONGLONG;
|
||||
|
||||
typedef unsigned int UINT32;
|
||||
typedef unsigned char UINT8;
|
||||
typedef int INT32;
|
||||
|
|
20
source/linux/windows/winerror.h
Normal file
20
source/linux/windows/winerror.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "linux/windows/wincompat.h"
|
||||
|
||||
#define FAILED(stat) ((HRESULT)(stat)<0)
|
||||
#define E_NOINTERFACE HRESULT(0x80004002)
|
||||
#define S_OK HRESULT(0)
|
||||
#define SEVERITY_SUCCESS 0
|
||||
#define SEVERITY_ERROR 1
|
||||
|
||||
#define MAKE_HRESULT(sev,fac,code) \
|
||||
((HRESULT) (((unsigned int)(sev)<<31) | ((unsigned int)(fac)<<16) | ((unsigned int)(code))) )
|
||||
#define MAKE_SCODE(sev,fac,code) \
|
||||
((SCODE) (((unsigned int)(sev)<<31) | ((unsigned int)(fac)<<16) | ((unsigned int)(code))) )
|
||||
#define SUCCEEDED(stat) ((HRESULT)(stat)>=0)
|
||||
#define FAILED(stat) ((HRESULT)(stat)<0)
|
||||
#define IS_ERROR(stat) (((unsigned int)(stat)>>31) == SEVERITY_ERROR)
|
||||
|
||||
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
|
||||
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
|
Loading…
Add table
Reference in a new issue